1use logicaffeine_base::Arena;
8use crate::ast::{LogicExpr, ModalDomain, ModalVector, NeoEventData, QuantifierKind, Term};
9use logicaffeine_base::{Interner, Symbol};
10use crate::token::TokenType;
11
12pub struct KripkeContext {
18 world_counter: u32,
19 current_world: Symbol,
20 clock_counter: u32,
23 domain_hint: Option<ModalDomain>,
27}
28
29impl KripkeContext {
30 pub fn new(interner: &mut Interner) -> Self {
31 Self {
32 world_counter: 0,
33 current_world: interner.intern("w0"),
34 clock_counter: 0,
35 domain_hint: None,
36 }
37 }
38
39 pub fn fresh_world(&mut self, interner: &mut Interner) -> Symbol {
40 self.world_counter += 1;
41 interner.intern(&format!("w{}", self.world_counter))
42 }
43
44 pub fn clock_counter(&self) -> u32 {
46 self.clock_counter
47 }
48
49 pub fn domain_hint(&self) -> Option<ModalDomain> {
51 self.domain_hint
52 }
53
54 fn tick_clock(&mut self) {
56 self.clock_counter += 1;
57 }
58
59 fn set_domain_hint(&mut self, domain: ModalDomain) {
61 self.domain_hint = Some(domain);
62 }
63
64 fn clear_domain_hint(&mut self) {
66 self.domain_hint = None;
67 }
68}
69
70pub fn apply_kripke_lowering<'a>(
79 expr: &'a LogicExpr<'a>,
80 expr_arena: &'a Arena<LogicExpr<'a>>,
81 term_arena: &'a Arena<Term<'a>>,
82 interner: &mut Interner,
83) -> &'a LogicExpr<'a> {
84 let mut ctx = KripkeContext::new(interner);
85 lower_expr(expr, &mut ctx, expr_arena, term_arena, interner)
86}
87
88fn lower_expr<'a>(
89 expr: &'a LogicExpr<'a>,
90 ctx: &mut KripkeContext,
91 expr_arena: &'a Arena<LogicExpr<'a>>,
92 term_arena: &'a Arena<Term<'a>>,
93 interner: &mut Interner,
94) -> &'a LogicExpr<'a> {
95 match expr {
96 LogicExpr::Modal { vector, operand } => {
97 lower_modal(vector, operand, ctx, expr_arena, term_arena, interner)
98 }
99
100 LogicExpr::Predicate { name, args, world } => {
101 if world.is_none() {
102 expr_arena.alloc(LogicExpr::Predicate {
104 name: *name,
105 args: *args,
106 world: Some(ctx.current_world),
107 })
108 } else {
109 expr
110 }
111 }
112
113 LogicExpr::Quantifier { kind, variable, body, island_id } => {
114 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
115 expr_arena.alloc(LogicExpr::Quantifier {
116 kind: *kind,
117 variable: *variable,
118 body: new_body,
119 island_id: *island_id,
120 })
121 }
122
123 LogicExpr::BinaryOp { left, op, right } => {
124 let new_left = lower_expr(left, ctx, expr_arena, term_arena, interner);
125 let new_right = lower_expr(right, ctx, expr_arena, term_arena, interner);
126 expr_arena.alloc(LogicExpr::BinaryOp {
127 left: new_left,
128 op: op.clone(),
129 right: new_right,
130 })
131 }
132
133 LogicExpr::UnaryOp { op, operand } => {
134 let new_operand = lower_expr(operand, ctx, expr_arena, term_arena, interner);
135 expr_arena.alloc(LogicExpr::UnaryOp {
136 op: op.clone(),
137 operand: new_operand,
138 })
139 }
140
141 LogicExpr::NeoEvent(data) => {
142 if data.world.is_none() {
144 expr_arena.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
145 event_var: data.event_var,
146 verb: data.verb,
147 roles: data.roles,
148 modifiers: data.modifiers,
149 suppress_existential: data.suppress_existential,
150 world: Some(ctx.current_world),
151 })))
152 } else {
153 expr
154 }
155 }
156
157 LogicExpr::Temporal { operator, body } => {
158 use crate::ast::logic::TemporalOperator;
159 ctx.set_domain_hint(ModalDomain::Temporal);
161 let result = match operator {
162 TemporalOperator::Always => {
164 lower_temporal_unary(
166 body, ctx, expr_arena, term_arena, interner,
167 "Accessible_Temporal", true,
168 )
169 }
170 TemporalOperator::Eventually => {
171 lower_temporal_unary(
173 body, ctx, expr_arena, term_arena, interner,
174 "Reachable_Temporal", false,
175 )
176 }
177 TemporalOperator::BoundedEventually(n) => {
178 let lowered_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
180 expr_arena.alloc(LogicExpr::Temporal {
181 operator: TemporalOperator::BoundedEventually(*n),
182 body: lowered_body,
183 })
184 }
185 TemporalOperator::Next => {
186 ctx.tick_clock();
188 lower_temporal_unary(
189 body, ctx, expr_arena, term_arena, interner,
190 "Next_Temporal", true,
191 )
192 }
193 TemporalOperator::Past | TemporalOperator::Future => {
195 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
196 expr_arena.alloc(LogicExpr::Temporal {
197 operator: *operator,
198 body: new_body,
199 })
200 }
201 };
202 ctx.clear_domain_hint();
203 result
204 }
205
206 LogicExpr::TemporalBinary { operator, left, right } => {
207 let new_left = lower_expr(left, ctx, expr_arena, term_arena, interner);
210 let new_right = lower_expr(right, ctx, expr_arena, term_arena, interner);
211
212 let source_world = ctx.current_world;
214 let target_world = ctx.fresh_world(interner);
215 let next_name = interner.intern("Next_Temporal");
216 let accessibility = expr_arena.alloc(LogicExpr::Predicate {
217 name: next_name,
218 args: term_arena.alloc_slice([
219 Term::Variable(source_world),
220 Term::Variable(target_world),
221 ]),
222 world: None,
223 });
224
225 let recursive_body = expr_arena.alloc(LogicExpr::BinaryOp {
227 left: accessibility,
228 op: crate::token::TokenType::And,
229 right: expr_arena.alloc(LogicExpr::TemporalBinary {
230 operator: *operator,
231 left: new_left,
232 right: new_right,
233 }),
234 });
235 let existential = expr_arena.alloc(LogicExpr::Quantifier {
236 kind: QuantifierKind::Existential,
237 variable: target_world,
238 body: recursive_body,
239 island_id: 0,
240 });
241 let left_and_next = expr_arena.alloc(LogicExpr::BinaryOp {
242 left: new_left,
243 op: crate::token::TokenType::And,
244 right: existential,
245 });
246 expr_arena.alloc(LogicExpr::BinaryOp {
247 left: new_right,
248 op: crate::token::TokenType::Or,
249 right: left_and_next,
250 })
251 }
252
253 LogicExpr::Aspectual { operator, body } => {
254 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
255 expr_arena.alloc(LogicExpr::Aspectual {
256 operator: *operator,
257 body: new_body,
258 })
259 }
260
261 LogicExpr::Voice { operator, body } => {
262 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
263 expr_arena.alloc(LogicExpr::Voice {
264 operator: *operator,
265 body: new_body,
266 })
267 }
268
269 LogicExpr::Lambda { variable, body } => {
270 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
271 expr_arena.alloc(LogicExpr::Lambda {
272 variable: *variable,
273 body: new_body,
274 })
275 }
276
277 LogicExpr::App { function, argument } => {
278 let new_function = lower_expr(function, ctx, expr_arena, term_arena, interner);
279 let new_argument = lower_expr(argument, ctx, expr_arena, term_arena, interner);
280 expr_arena.alloc(LogicExpr::App {
281 function: new_function,
282 argument: new_argument,
283 })
284 }
285
286 LogicExpr::Intensional { operator, content } => {
287 let new_content = lower_expr(content, ctx, expr_arena, term_arena, interner);
288 expr_arena.alloc(LogicExpr::Intensional {
289 operator: *operator,
290 content: new_content,
291 })
292 }
293
294 LogicExpr::Control { verb, subject, object, infinitive } => {
295 let new_infinitive = lower_expr(infinitive, ctx, expr_arena, term_arena, interner);
296 expr_arena.alloc(LogicExpr::Control {
297 verb: *verb,
298 subject: *subject,
299 object: *object,
300 infinitive: new_infinitive,
301 })
302 }
303
304 LogicExpr::Scopal { operator, body } => {
305 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
306 expr_arena.alloc(LogicExpr::Scopal {
307 operator: *operator,
308 body: new_body,
309 })
310 }
311
312 LogicExpr::Question { wh_variable, body } => {
313 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
314 expr_arena.alloc(LogicExpr::Question {
315 wh_variable: *wh_variable,
316 body: new_body,
317 })
318 }
319
320 LogicExpr::YesNoQuestion { body } => {
321 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
322 expr_arena.alloc(LogicExpr::YesNoQuestion { body: new_body })
323 }
324
325 LogicExpr::Focus { kind, focused, scope } => {
326 let new_scope = lower_expr(scope, ctx, expr_arena, term_arena, interner);
327 expr_arena.alloc(LogicExpr::Focus {
328 kind: *kind,
329 focused: *focused,
330 scope: new_scope,
331 })
332 }
333
334 LogicExpr::Distributive { predicate } => {
335 let new_predicate = lower_expr(predicate, ctx, expr_arena, term_arena, interner);
336 expr_arena.alloc(LogicExpr::Distributive {
337 predicate: new_predicate,
338 })
339 }
340
341 LogicExpr::Counterfactual { antecedent, consequent } => {
342 let new_antecedent = lower_expr(antecedent, ctx, expr_arena, term_arena, interner);
343 let new_consequent = lower_expr(consequent, ctx, expr_arena, term_arena, interner);
344 expr_arena.alloc(LogicExpr::Counterfactual {
345 antecedent: new_antecedent,
346 consequent: new_consequent,
347 })
348 }
349
350 LogicExpr::Event { predicate, adverbs } => {
351 let new_predicate = lower_expr(predicate, ctx, expr_arena, term_arena, interner);
352 expr_arena.alloc(LogicExpr::Event {
353 predicate: new_predicate,
354 adverbs: *adverbs,
355 })
356 }
357
358 LogicExpr::Imperative { action } => {
359 let new_action = lower_expr(action, ctx, expr_arena, term_arena, interner);
360 expr_arena.alloc(LogicExpr::Imperative { action: new_action })
361 }
362 LogicExpr::Exclamative { degree_var, body } => {
363 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
364 expr_arena.alloc(LogicExpr::Exclamative { degree_var: *degree_var, body: new_body })
365 }
366 LogicExpr::Optative { wish } => {
367 let new_wish = lower_expr(wish, ctx, expr_arena, term_arena, interner);
368 expr_arena.alloc(LogicExpr::Optative { wish: new_wish })
369 }
370 LogicExpr::Implicature { assertion, implicature } => {
371 let new_assertion = lower_expr(assertion, ctx, expr_arena, term_arena, interner);
372 let new_implicature = lower_expr(implicature, ctx, expr_arena, term_arena, interner);
373 expr_arena.alloc(LogicExpr::Implicature {
374 assertion: new_assertion,
375 implicature: new_implicature,
376 })
377 }
378
379 LogicExpr::Causal { effect, cause } => {
380 let new_effect = lower_expr(effect, ctx, expr_arena, term_arena, interner);
381 let new_cause = lower_expr(cause, ctx, expr_arena, term_arena, interner);
382 expr_arena.alloc(LogicExpr::Causal {
383 effect: new_effect,
384 cause: new_cause,
385 })
386 }
387
388 LogicExpr::Concessive { main, concession } => {
389 let new_main = lower_expr(main, ctx, expr_arena, term_arena, interner);
390 let new_concession = lower_expr(concession, ctx, expr_arena, term_arena, interner);
391 expr_arena.alloc(LogicExpr::Concessive {
392 main: new_main,
393 concession: new_concession,
394 })
395 }
396
397 LogicExpr::Presupposition { assertion, presupposition } => {
398 let new_assertion = lower_expr(assertion, ctx, expr_arena, term_arena, interner);
399 let new_presupposition = lower_expr(presupposition, ctx, expr_arena, term_arena, interner);
400 expr_arena.alloc(LogicExpr::Presupposition {
401 assertion: new_assertion,
402 presupposition: new_presupposition,
403 })
404 }
405
406 LogicExpr::TemporalAnchor { anchor, body } => {
407 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
408 expr_arena.alloc(LogicExpr::TemporalAnchor {
409 anchor: *anchor,
410 body: new_body,
411 })
412 }
413
414 LogicExpr::GroupQuantifier { group_var, count, member_var, restriction, body } => {
415 let new_restriction = lower_expr(restriction, ctx, expr_arena, term_arena, interner);
416 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
417 expr_arena.alloc(LogicExpr::GroupQuantifier {
418 group_var: *group_var,
419 count: *count,
420 member_var: *member_var,
421 restriction: new_restriction,
422 body: new_body,
423 })
424 }
425
426 LogicExpr::Identity { .. }
428 | LogicExpr::Metaphor { .. }
429 | LogicExpr::Categorical(_)
430 | LogicExpr::Relation(_)
431 | LogicExpr::Atom(_)
432 | LogicExpr::Superlative { .. }
433 | LogicExpr::Comparative { .. }
434 | LogicExpr::SpeechAct { .. } => expr,
435 }
436}
437
438fn lower_modal<'a>(
439 vector: &ModalVector,
440 operand: &'a LogicExpr<'a>,
441 ctx: &mut KripkeContext,
442 expr_arena: &'a Arena<LogicExpr<'a>>,
443 term_arena: &'a Arena<Term<'a>>,
444 interner: &mut Interner,
445) -> &'a LogicExpr<'a> {
446 let source_world = ctx.current_world;
447 let target_world = ctx.fresh_world(interner);
448
449 let old_world = ctx.current_world;
451 ctx.current_world = target_world;
452 let lowered_operand = lower_expr(operand, ctx, expr_arena, term_arena, interner);
453 ctx.current_world = old_world;
454
455 let access_name = match vector.domain {
457 ModalDomain::Alethic => interner.intern("Accessible_Alethic"),
458 ModalDomain::Deontic => interner.intern("Accessible_Deontic"),
459 ModalDomain::Temporal => interner.intern("Accessible_Temporal"),
460 };
461
462 let accessibility = expr_arena.alloc(LogicExpr::Predicate {
463 name: access_name,
464 args: term_arena.alloc_slice([
465 Term::Variable(source_world),
466 Term::Variable(target_world),
467 ]),
468 world: None, });
470
471 if vector.force > 0.5 {
472 let implication = expr_arena.alloc(LogicExpr::BinaryOp {
474 left: accessibility,
475 op: TokenType::Implies,
476 right: lowered_operand,
477 });
478 expr_arena.alloc(LogicExpr::Quantifier {
479 kind: QuantifierKind::Universal,
480 variable: target_world,
481 body: implication,
482 island_id: 0,
483 })
484 } else if vector.force <= 0.0 {
485 let negated = expr_arena.alloc(LogicExpr::UnaryOp {
489 op: TokenType::Not,
490 operand: lowered_operand,
491 });
492 let implication = expr_arena.alloc(LogicExpr::BinaryOp {
493 left: accessibility,
494 op: TokenType::Implies,
495 right: negated,
496 });
497 expr_arena.alloc(LogicExpr::Quantifier {
498 kind: QuantifierKind::Universal,
499 variable: target_world,
500 body: implication,
501 island_id: 0,
502 })
503 } else {
504 let conjunction = expr_arena.alloc(LogicExpr::BinaryOp {
506 left: accessibility,
507 op: TokenType::And,
508 right: lowered_operand,
509 });
510 expr_arena.alloc(LogicExpr::Quantifier {
511 kind: QuantifierKind::Existential,
512 variable: target_world,
513 body: conjunction,
514 island_id: 0,
515 })
516 }
517}
518
519fn lower_temporal_unary<'a>(
523 body: &'a LogicExpr<'a>,
524 ctx: &mut KripkeContext,
525 expr_arena: &'a Arena<LogicExpr<'a>>,
526 term_arena: &'a Arena<Term<'a>>,
527 interner: &mut Interner,
528 predicate_name: &str,
529 is_universal: bool,
530) -> &'a LogicExpr<'a> {
531 let source_world = ctx.current_world;
532 let target_world = ctx.fresh_world(interner);
533
534 let old_world = ctx.current_world;
536 ctx.current_world = target_world;
537 let lowered_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
538 ctx.current_world = old_world;
539
540 let access_name = interner.intern(predicate_name);
542 let accessibility = expr_arena.alloc(LogicExpr::Predicate {
543 name: access_name,
544 args: term_arena.alloc_slice([
545 Term::Variable(source_world),
546 Term::Variable(target_world),
547 ]),
548 world: None,
549 });
550
551 if is_universal {
552 let implication = expr_arena.alloc(LogicExpr::BinaryOp {
554 left: accessibility,
555 op: TokenType::Implies,
556 right: lowered_body,
557 });
558 expr_arena.alloc(LogicExpr::Quantifier {
559 kind: QuantifierKind::Universal,
560 variable: target_world,
561 body: implication,
562 island_id: 0,
563 })
564 } else {
565 let conjunction = expr_arena.alloc(LogicExpr::BinaryOp {
567 left: accessibility,
568 op: TokenType::And,
569 right: lowered_body,
570 });
571 expr_arena.alloc(LogicExpr::Quantifier {
572 kind: QuantifierKind::Existential,
573 variable: target_world,
574 body: conjunction,
575 island_id: 0,
576 })
577 }
578}