1use crate::ast::{
13 AspectOperator, LogicExpr, ModalVector, NounPhrase, QuantifierKind, TemporalOperator, VoiceOperator, Term,
14 ThematicRole,
15};
16use logicaffeine_base::Interner;
17use crate::lexicon::Definiteness;
18use crate::token::{FocusKind, TokenType};
19
20#[derive(Debug, Clone, PartialEq)]
22pub enum TermView<'a> {
23 Constant(&'a str),
24 Variable(&'a str),
25 Function(&'a str, Vec<TermView<'a>>),
26 Group(Vec<TermView<'a>>),
27 Possessed {
28 possessor: Box<TermView<'a>>,
29 possessed: &'a str,
30 },
31 Sigma(&'a str),
32 Intension(&'a str),
33 Proposition(Box<ExprView<'a>>),
34 Value {
35 kind: NumberKindView<'a>,
36 unit: Option<&'a str>,
37 dimension: Option<crate::ast::Dimension>,
38 },
39}
40
41#[derive(Debug, Clone, PartialEq)]
42pub enum NumberKindView<'a> {
43 Real(f64),
44 Integer(i64),
45 Symbolic(&'a str),
46}
47
48#[derive(Debug, Clone, PartialEq)]
49pub struct NounPhraseView<'a> {
50 pub definiteness: Option<Definiteness>,
51 pub adjectives: Vec<&'a str>,
52 pub noun: &'a str,
53 pub possessor: Option<Box<NounPhraseView<'a>>>,
54 pub pps: Vec<Box<ExprView<'a>>>,
55 pub superlative: Option<&'a str>,
56}
57
58#[derive(Debug, Clone, PartialEq)]
59pub enum ExprView<'a> {
60 Predicate {
61 name: &'a str,
62 args: Vec<TermView<'a>>,
63 },
64 Identity {
65 left: TermView<'a>,
66 right: TermView<'a>,
67 },
68 Metaphor {
69 tenor: TermView<'a>,
70 vehicle: TermView<'a>,
71 },
72 Quantifier {
73 kind: QuantifierKind,
74 variable: &'a str,
75 body: Box<ExprView<'a>>,
76 },
77 Categorical {
78 quantifier: TokenType,
79 subject: NounPhraseView<'a>,
80 copula_negative: bool,
81 predicate: NounPhraseView<'a>,
82 },
83 Relation {
84 subject: NounPhraseView<'a>,
85 verb: &'a str,
86 object: NounPhraseView<'a>,
87 },
88 Modal {
89 vector: ModalVector,
90 operand: Box<ExprView<'a>>,
91 },
92 Temporal {
93 operator: TemporalOperator,
94 body: Box<ExprView<'a>>,
95 },
96 Aspectual {
97 operator: AspectOperator,
98 body: Box<ExprView<'a>>,
99 },
100 Voice {
101 operator: VoiceOperator,
102 body: Box<ExprView<'a>>,
103 },
104 BinaryOp {
105 left: Box<ExprView<'a>>,
106 op: TokenType,
107 right: Box<ExprView<'a>>,
108 },
109 UnaryOp {
110 op: TokenType,
111 operand: Box<ExprView<'a>>,
112 },
113 Question {
114 wh_variable: &'a str,
115 body: Box<ExprView<'a>>,
116 },
117 YesNoQuestion {
118 body: Box<ExprView<'a>>,
119 },
120 Atom(&'a str),
121 Lambda {
122 variable: &'a str,
123 body: Box<ExprView<'a>>,
124 },
125 App {
126 function: Box<ExprView<'a>>,
127 argument: Box<ExprView<'a>>,
128 },
129 Intensional {
130 operator: &'a str,
131 content: Box<ExprView<'a>>,
132 },
133 Event {
134 predicate: Box<ExprView<'a>>,
135 adverbs: Vec<&'a str>,
136 },
137 NeoEvent {
138 event_var: &'a str,
139 verb: &'a str,
140 roles: Vec<(ThematicRole, TermView<'a>)>,
141 modifiers: Vec<&'a str>,
142 },
143 Imperative {
144 action: Box<ExprView<'a>>,
145 },
146 SpeechAct {
147 performer: &'a str,
148 act_type: &'a str,
149 content: Box<ExprView<'a>>,
150 },
151 Counterfactual {
152 antecedent: Box<ExprView<'a>>,
153 consequent: Box<ExprView<'a>>,
154 },
155 Causal {
156 effect: Box<ExprView<'a>>,
157 cause: Box<ExprView<'a>>,
158 },
159 Comparative {
160 adjective: &'a str,
161 subject: TermView<'a>,
162 object: TermView<'a>,
163 difference: Option<Box<TermView<'a>>>,
164 },
165 Superlative {
166 adjective: &'a str,
167 subject: TermView<'a>,
168 domain: &'a str,
169 },
170 Scopal {
171 operator: &'a str,
172 body: Box<ExprView<'a>>,
173 },
174 Control {
175 verb: &'a str,
176 subject: TermView<'a>,
177 object: Option<TermView<'a>>,
178 infinitive: Box<ExprView<'a>>,
179 },
180 Presupposition {
181 assertion: Box<ExprView<'a>>,
182 presupposition: Box<ExprView<'a>>,
183 },
184 Focus {
185 kind: FocusKind,
186 focused: TermView<'a>,
187 scope: Box<ExprView<'a>>,
188 },
189 TemporalAnchor {
190 anchor: &'a str,
191 body: Box<ExprView<'a>>,
192 },
193 Distributive {
194 predicate: Box<ExprView<'a>>,
195 },
196 GroupQuantifier {
197 group_var: &'a str,
198 count: u32,
199 member_var: &'a str,
200 restriction: Box<ExprView<'a>>,
201 body: Box<ExprView<'a>>,
202 },
203}
204
205pub trait Resolve<'a> {
206 type Output;
207 fn resolve(&self, interner: &'a Interner) -> Self::Output;
208}
209
210impl<'a, 'b> Resolve<'a> for Term<'b> {
211 type Output = TermView<'a>;
212
213 fn resolve(&self, interner: &'a Interner) -> TermView<'a> {
214 match self {
215 Term::Constant(s) => TermView::Constant(interner.resolve(*s)),
216 Term::Variable(s) => TermView::Variable(interner.resolve(*s)),
217 Term::Function(name, args) => TermView::Function(
218 interner.resolve(*name),
219 args.iter().map(|a| a.resolve(interner)).collect(),
220 ),
221 Term::Group(members) => {
222 TermView::Group(members.iter().map(|m| m.resolve(interner)).collect())
223 }
224 Term::Possessed {
225 possessor,
226 possessed,
227 } => TermView::Possessed {
228 possessor: Box::new(possessor.resolve(interner)),
229 possessed: interner.resolve(*possessed),
230 },
231 Term::Sigma(predicate) => TermView::Sigma(interner.resolve(*predicate)),
232 Term::Intension(predicate) => TermView::Intension(interner.resolve(*predicate)),
233 Term::Proposition(expr) => {
234 TermView::Proposition(Box::new(expr.resolve(interner)))
235 }
236 Term::Value { kind, unit, dimension } => {
237 use crate::ast::NumberKind;
238 let kind_view = match kind {
239 NumberKind::Real(r) => NumberKindView::Real(*r),
240 NumberKind::Integer(i) => NumberKindView::Integer(*i),
241 NumberKind::Symbolic(s) => NumberKindView::Symbolic(interner.resolve(*s)),
242 };
243 TermView::Value {
244 kind: kind_view,
245 unit: unit.map(|u| interner.resolve(u)),
246 dimension: *dimension,
247 }
248 }
249 }
250 }
251}
252
253impl<'a, 'b> Resolve<'a> for NounPhrase<'b> {
254 type Output = NounPhraseView<'a>;
255
256 fn resolve(&self, interner: &'a Interner) -> NounPhraseView<'a> {
257 NounPhraseView {
258 definiteness: self.definiteness,
259 adjectives: self.adjectives.iter().map(|s| interner.resolve(*s)).collect(),
260 noun: interner.resolve(self.noun),
261 possessor: self.possessor.map(|p| Box::new(p.resolve(interner))),
262 pps: self.pps.iter().map(|pp| Box::new(pp.resolve(interner))).collect(),
263 superlative: self.superlative.map(|s| interner.resolve(s)),
264 }
265 }
266}
267
268impl<'a, 'b> Resolve<'a> for LogicExpr<'b> {
269 type Output = ExprView<'a>;
270
271 fn resolve(&self, interner: &'a Interner) -> ExprView<'a> {
272 match self {
273 LogicExpr::Predicate { name, args, .. } => ExprView::Predicate {
274 name: interner.resolve(*name),
275 args: args.iter().map(|a| a.resolve(interner)).collect(),
276 },
277 LogicExpr::Identity { left, right } => ExprView::Identity {
278 left: left.resolve(interner),
279 right: right.resolve(interner),
280 },
281 LogicExpr::Metaphor { tenor, vehicle } => ExprView::Metaphor {
282 tenor: tenor.resolve(interner),
283 vehicle: vehicle.resolve(interner),
284 },
285 LogicExpr::Quantifier { kind, variable, body, .. } => ExprView::Quantifier {
286 kind: *kind,
287 variable: interner.resolve(*variable),
288 body: Box::new(body.resolve(interner)),
289 },
290 LogicExpr::Categorical(data) => ExprView::Categorical {
291 quantifier: data.quantifier.clone(),
292 subject: data.subject.resolve(interner),
293 copula_negative: data.copula_negative,
294 predicate: data.predicate.resolve(interner),
295 },
296 LogicExpr::Relation(data) => ExprView::Relation {
297 subject: data.subject.resolve(interner),
298 verb: interner.resolve(data.verb),
299 object: data.object.resolve(interner),
300 },
301 LogicExpr::Modal { vector, operand } => ExprView::Modal {
302 vector: *vector,
303 operand: Box::new(operand.resolve(interner)),
304 },
305 LogicExpr::Temporal { operator, body } => ExprView::Temporal {
306 operator: *operator,
307 body: Box::new(body.resolve(interner)),
308 },
309 LogicExpr::Aspectual { operator, body } => ExprView::Aspectual {
310 operator: *operator,
311 body: Box::new(body.resolve(interner)),
312 },
313 LogicExpr::Voice { operator, body } => ExprView::Voice {
314 operator: *operator,
315 body: Box::new(body.resolve(interner)),
316 },
317 LogicExpr::BinaryOp { left, op, right } => ExprView::BinaryOp {
318 left: Box::new(left.resolve(interner)),
319 op: op.clone(),
320 right: Box::new(right.resolve(interner)),
321 },
322 LogicExpr::UnaryOp { op, operand } => ExprView::UnaryOp {
323 op: op.clone(),
324 operand: Box::new(operand.resolve(interner)),
325 },
326 LogicExpr::Question { wh_variable, body } => ExprView::Question {
327 wh_variable: interner.resolve(*wh_variable),
328 body: Box::new(body.resolve(interner)),
329 },
330 LogicExpr::YesNoQuestion { body } => ExprView::YesNoQuestion {
331 body: Box::new(body.resolve(interner)),
332 },
333 LogicExpr::Atom(s) => ExprView::Atom(interner.resolve(*s)),
334 LogicExpr::Lambda { variable, body } => ExprView::Lambda {
335 variable: interner.resolve(*variable),
336 body: Box::new(body.resolve(interner)),
337 },
338 LogicExpr::App { function, argument } => ExprView::App {
339 function: Box::new(function.resolve(interner)),
340 argument: Box::new(argument.resolve(interner)),
341 },
342 LogicExpr::Intensional { operator, content } => ExprView::Intensional {
343 operator: interner.resolve(*operator),
344 content: Box::new(content.resolve(interner)),
345 },
346 LogicExpr::Event { predicate, adverbs } => ExprView::Event {
347 predicate: Box::new(predicate.resolve(interner)),
348 adverbs: adverbs.iter().map(|s| interner.resolve(*s)).collect(),
349 },
350 LogicExpr::NeoEvent(data) => ExprView::NeoEvent {
351 event_var: interner.resolve(data.event_var),
352 verb: interner.resolve(data.verb),
353 roles: data.roles.iter().map(|(role, term)| (*role, term.resolve(interner))).collect(),
354 modifiers: data.modifiers.iter().map(|s| interner.resolve(*s)).collect(),
355 },
356 LogicExpr::Imperative { action } => ExprView::Imperative {
357 action: Box::new(action.resolve(interner)),
358 },
359 LogicExpr::SpeechAct {
360 performer,
361 act_type,
362 content,
363 } => ExprView::SpeechAct {
364 performer: interner.resolve(*performer),
365 act_type: interner.resolve(*act_type),
366 content: Box::new(content.resolve(interner)),
367 },
368 LogicExpr::Counterfactual { antecedent, consequent } => ExprView::Counterfactual {
369 antecedent: Box::new(antecedent.resolve(interner)),
370 consequent: Box::new(consequent.resolve(interner)),
371 },
372 LogicExpr::Causal { effect, cause } => ExprView::Causal {
373 effect: Box::new(effect.resolve(interner)),
374 cause: Box::new(cause.resolve(interner)),
375 },
376 LogicExpr::Comparative { adjective, subject, object, difference } => ExprView::Comparative {
377 adjective: interner.resolve(*adjective),
378 subject: subject.resolve(interner),
379 object: object.resolve(interner),
380 difference: difference.map(|d| Box::new(d.resolve(interner))),
381 },
382 LogicExpr::Superlative { adjective, subject, domain } => ExprView::Superlative {
383 adjective: interner.resolve(*adjective),
384 subject: subject.resolve(interner),
385 domain: interner.resolve(*domain),
386 },
387 LogicExpr::Scopal { operator, body } => ExprView::Scopal {
388 operator: interner.resolve(*operator),
389 body: Box::new(body.resolve(interner)),
390 },
391 LogicExpr::Control {
392 verb,
393 subject,
394 object,
395 infinitive,
396 } => ExprView::Control {
397 verb: interner.resolve(*verb),
398 subject: subject.resolve(interner),
399 object: object.map(|o| o.resolve(interner)),
400 infinitive: Box::new(infinitive.resolve(interner)),
401 },
402 LogicExpr::Presupposition { assertion, presupposition } => ExprView::Presupposition {
403 assertion: Box::new(assertion.resolve(interner)),
404 presupposition: Box::new(presupposition.resolve(interner)),
405 },
406 LogicExpr::Focus { kind, focused, scope } => ExprView::Focus {
407 kind: *kind,
408 focused: focused.resolve(interner),
409 scope: Box::new(scope.resolve(interner)),
410 },
411 LogicExpr::TemporalAnchor { anchor, body } => ExprView::TemporalAnchor {
412 anchor: interner.resolve(*anchor),
413 body: Box::new(body.resolve(interner)),
414 },
415 LogicExpr::Distributive { predicate } => ExprView::Distributive {
416 predicate: Box::new(predicate.resolve(interner)),
417 },
418 LogicExpr::GroupQuantifier { group_var, count, member_var, restriction, body } => ExprView::GroupQuantifier {
419 group_var: interner.resolve(*group_var),
420 count: *count,
421 member_var: interner.resolve(*member_var),
422 restriction: Box::new(restriction.resolve(interner)),
423 body: Box::new(body.resolve(interner)),
424 },
425 }
426 }
427}
428
429#[cfg(test)]
430mod term_view_tests {
431 use super::*;
432 use logicaffeine_base::Arena;
433
434 #[test]
435 fn resolve_term_constant() {
436 let mut interner = Interner::new();
437 let sym = interner.intern("Socrates");
438 let term = Term::Constant(sym);
439 assert_eq!(term.resolve(&interner), TermView::Constant("Socrates"));
440 }
441
442 #[test]
443 fn resolve_term_variable() {
444 let mut interner = Interner::new();
445 let x = interner.intern("x");
446 let term = Term::Variable(x);
447 assert_eq!(term.resolve(&interner), TermView::Variable("x"));
448 }
449
450 #[test]
451 fn resolve_term_function() {
452 let mut interner = Interner::new();
453 let term_arena: Arena<Term> = Arena::new();
454 let father = interner.intern("father");
455 let john = interner.intern("John");
456 let term = Term::Function(father, term_arena.alloc_slice([Term::Constant(john)]));
457
458 assert_eq!(
459 term.resolve(&interner),
460 TermView::Function("father", vec![TermView::Constant("John")])
461 );
462 }
463
464 #[test]
465 fn resolve_term_group() {
466 let mut interner = Interner::new();
467 let term_arena: Arena<Term> = Arena::new();
468 let j = interner.intern("John");
469 let m = interner.intern("Mary");
470 let term = Term::Group(term_arena.alloc_slice([Term::Constant(j), Term::Constant(m)]));
471
472 assert_eq!(
473 term.resolve(&interner),
474 TermView::Group(vec![
475 TermView::Constant("John"),
476 TermView::Constant("Mary")
477 ])
478 );
479 }
480
481 #[test]
482 fn resolve_term_possessed() {
483 let mut interner = Interner::new();
484 let term_arena: Arena<Term> = Arena::new();
485 let john = interner.intern("John");
486 let dog = interner.intern("dog");
487 let term = Term::Possessed {
488 possessor: term_arena.alloc(Term::Constant(john)),
489 possessed: dog,
490 };
491
492 assert_eq!(
493 term.resolve(&interner),
494 TermView::Possessed {
495 possessor: Box::new(TermView::Constant("John")),
496 possessed: "dog",
497 }
498 );
499 }
500
501 #[test]
502 fn term_view_equality_is_bit_exact() {
503 let a = TermView::Constant("test");
504 let b = TermView::Constant("test");
505 let c = TermView::Constant("Test");
506 assert_eq!(a, b);
507 assert_ne!(a, c);
508 }
509
510 #[test]
511 fn nested_function_resolve() {
512 let mut interner = Interner::new();
513 let term_arena: Arena<Term> = Arena::new();
514 let f = interner.intern("f");
515 let g = interner.intern("g");
516 let x = interner.intern("x");
517
518 let inner = Term::Function(g, term_arena.alloc_slice([Term::Variable(x)]));
519 let outer = Term::Function(f, term_arena.alloc_slice([inner]));
520
521 assert_eq!(
522 outer.resolve(&interner),
523 TermView::Function(
524 "f",
525 vec![TermView::Function("g", vec![TermView::Variable("x")])]
526 )
527 );
528 }
529}
530
531#[cfg(test)]
532mod expr_view_tests {
533 use super::*;
534 use logicaffeine_base::Arena;
535 use crate::ast::ModalDomain;
536
537 #[test]
538 fn resolve_expr_predicate() {
539 let mut interner = Interner::new();
540 let term_arena: Arena<Term> = Arena::new();
541 let mortal = interner.intern("Mortal");
542 let x = interner.intern("x");
543 let expr = LogicExpr::Predicate {
544 name: mortal,
545 args: term_arena.alloc_slice([Term::Variable(x)]),
546 world: None,
547 };
548
549 assert_eq!(
550 expr.resolve(&interner),
551 ExprView::Predicate {
552 name: "Mortal",
553 args: vec![TermView::Variable("x")],
554 }
555 );
556 }
557
558 #[test]
559 fn resolve_expr_identity() {
560 let mut interner = Interner::new();
561 let term_arena: Arena<Term> = Arena::new();
562 let clark = interner.intern("Clark");
563 let superman = interner.intern("Superman");
564 let expr = LogicExpr::Identity {
565 left: term_arena.alloc(Term::Constant(clark)),
566 right: term_arena.alloc(Term::Constant(superman)),
567 };
568
569 assert_eq!(
570 expr.resolve(&interner),
571 ExprView::Identity {
572 left: TermView::Constant("Clark"),
573 right: TermView::Constant("Superman"),
574 }
575 );
576 }
577
578 #[test]
579 fn resolve_expr_quantifier() {
580 let mut interner = Interner::new();
581 let expr_arena: Arena<LogicExpr> = Arena::new();
582 let term_arena: Arena<Term> = Arena::new();
583 let x = interner.intern("x");
584 let mortal = interner.intern("Mortal");
585
586 let body = expr_arena.alloc(LogicExpr::Predicate {
587 name: mortal,
588 args: term_arena.alloc_slice([Term::Variable(x)]),
589 world: None,
590 });
591 let expr = LogicExpr::Quantifier {
592 kind: QuantifierKind::Universal,
593 variable: x,
594 body,
595 island_id: 0,
596 };
597
598 assert_eq!(
599 expr.resolve(&interner),
600 ExprView::Quantifier {
601 kind: QuantifierKind::Universal,
602 variable: "x",
603 body: Box::new(ExprView::Predicate {
604 name: "Mortal",
605 args: vec![TermView::Variable("x")],
606 }),
607 }
608 );
609 }
610
611 #[test]
612 fn resolve_expr_atom() {
613 let mut interner = Interner::new();
614 let p = interner.intern("P");
615 let expr = LogicExpr::Atom(p);
616
617 assert_eq!(expr.resolve(&interner), ExprView::Atom("P"));
618 }
619
620 #[test]
621 fn resolve_expr_binary_op() {
622 let mut interner = Interner::new();
623 let expr_arena: Arena<LogicExpr> = Arena::new();
624 let p = interner.intern("P");
625 let q = interner.intern("Q");
626 let expr = LogicExpr::BinaryOp {
627 left: expr_arena.alloc(LogicExpr::Atom(p)),
628 op: TokenType::And,
629 right: expr_arena.alloc(LogicExpr::Atom(q)),
630 };
631
632 assert_eq!(
633 expr.resolve(&interner),
634 ExprView::BinaryOp {
635 left: Box::new(ExprView::Atom("P")),
636 op: TokenType::And,
637 right: Box::new(ExprView::Atom("Q")),
638 }
639 );
640 }
641
642 #[test]
643 fn resolve_expr_lambda() {
644 let mut interner = Interner::new();
645 let expr_arena: Arena<LogicExpr> = Arena::new();
646 let x = interner.intern("x");
647 let p = interner.intern("P");
648 let expr = LogicExpr::Lambda {
649 variable: x,
650 body: expr_arena.alloc(LogicExpr::Atom(p)),
651 };
652
653 assert_eq!(
654 expr.resolve(&interner),
655 ExprView::Lambda {
656 variable: "x",
657 body: Box::new(ExprView::Atom("P")),
658 }
659 );
660 }
661
662 #[test]
663 fn resolve_expr_temporal() {
664 let mut interner = Interner::new();
665 let expr_arena: Arena<LogicExpr> = Arena::new();
666 let run = interner.intern("Run");
667 let expr = LogicExpr::Temporal {
668 operator: TemporalOperator::Past,
669 body: expr_arena.alloc(LogicExpr::Atom(run)),
670 };
671
672 assert_eq!(
673 expr.resolve(&interner),
674 ExprView::Temporal {
675 operator: TemporalOperator::Past,
676 body: Box::new(ExprView::Atom("Run")),
677 }
678 );
679 }
680
681 #[test]
682 fn resolve_expr_modal() {
683 use crate::ast::ModalFlavor;
684 let mut interner = Interner::new();
685 let expr_arena: Arena<LogicExpr> = Arena::new();
686 let rain = interner.intern("Rain");
687 let expr = LogicExpr::Modal {
688 vector: ModalVector {
689 domain: ModalDomain::Alethic,
690 force: 1.0,
691 flavor: ModalFlavor::Root,
692 },
693 operand: expr_arena.alloc(LogicExpr::Atom(rain)),
694 };
695
696 assert_eq!(
697 expr.resolve(&interner),
698 ExprView::Modal {
699 vector: ModalVector {
700 domain: ModalDomain::Alethic,
701 force: 1.0,
702 flavor: ModalFlavor::Root,
703 },
704 operand: Box::new(ExprView::Atom("Rain")),
705 }
706 );
707 }
708
709 #[test]
710 fn modal_vector_equality_is_bit_exact() {
711 use crate::ast::ModalFlavor;
712 let v1 = ModalVector {
713 domain: ModalDomain::Alethic,
714 force: 0.5,
715 flavor: ModalFlavor::Root,
716 };
717 let v2 = ModalVector {
718 domain: ModalDomain::Alethic,
719 force: 0.5,
720 flavor: ModalFlavor::Root,
721 };
722 let v3 = ModalVector {
723 domain: ModalDomain::Alethic,
724 force: 0.51,
725 flavor: ModalFlavor::Root,
726 };
727
728 assert_eq!(v1, v2);
729 assert_ne!(v1, v3);
730 }
731
732 #[test]
733 fn resolve_expr_unary_op() {
734 let mut interner = Interner::new();
735 let expr_arena: Arena<LogicExpr> = Arena::new();
736 let p = interner.intern("P");
737 let expr = LogicExpr::UnaryOp {
738 op: TokenType::Not,
739 operand: expr_arena.alloc(LogicExpr::Atom(p)),
740 };
741
742 assert_eq!(
743 expr.resolve(&interner),
744 ExprView::UnaryOp {
745 op: TokenType::Not,
746 operand: Box::new(ExprView::Atom("P")),
747 }
748 );
749 }
750
751 #[test]
752 fn resolve_expr_app() {
753 let mut interner = Interner::new();
754 let expr_arena: Arena<LogicExpr> = Arena::new();
755 let f = interner.intern("f");
756 let x = interner.intern("x");
757 let expr = LogicExpr::App {
758 function: expr_arena.alloc(LogicExpr::Atom(f)),
759 argument: expr_arena.alloc(LogicExpr::Atom(x)),
760 };
761
762 assert_eq!(
763 expr.resolve(&interner),
764 ExprView::App {
765 function: Box::new(ExprView::Atom("f")),
766 argument: Box::new(ExprView::Atom("x")),
767 }
768 );
769 }
770
771 #[test]
772 fn expr_view_equality_complex() {
773 let a = ExprView::Quantifier {
774 kind: QuantifierKind::Universal,
775 variable: "x",
776 body: Box::new(ExprView::Predicate {
777 name: "P",
778 args: vec![TermView::Variable("x")],
779 }),
780 };
781 let b = ExprView::Quantifier {
782 kind: QuantifierKind::Universal,
783 variable: "x",
784 body: Box::new(ExprView::Predicate {
785 name: "P",
786 args: vec![TermView::Variable("x")],
787 }),
788 };
789 assert_eq!(a, b);
790 }
791}