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