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 {
14 world_counter: u32,
15 current_world: Symbol,
16}
17
18impl KripkeContext {
19 pub fn new(interner: &mut Interner) -> Self {
20 Self {
21 world_counter: 0,
22 current_world: interner.intern("w0"),
23 }
24 }
25
26 pub fn fresh_world(&mut self, interner: &mut Interner) -> Symbol {
27 self.world_counter += 1;
28 interner.intern(&format!("w{}", self.world_counter))
29 }
30}
31
32pub fn apply_kripke_lowering<'a>(
41 expr: &'a LogicExpr<'a>,
42 expr_arena: &'a Arena<LogicExpr<'a>>,
43 term_arena: &'a Arena<Term<'a>>,
44 interner: &mut Interner,
45) -> &'a LogicExpr<'a> {
46 let mut ctx = KripkeContext::new(interner);
47 lower_expr(expr, &mut ctx, expr_arena, term_arena, interner)
48}
49
50fn lower_expr<'a>(
51 expr: &'a LogicExpr<'a>,
52 ctx: &mut KripkeContext,
53 expr_arena: &'a Arena<LogicExpr<'a>>,
54 term_arena: &'a Arena<Term<'a>>,
55 interner: &mut Interner,
56) -> &'a LogicExpr<'a> {
57 match expr {
58 LogicExpr::Modal { vector, operand } => {
59 lower_modal(vector, operand, ctx, expr_arena, term_arena, interner)
60 }
61
62 LogicExpr::Predicate { name, args, world } => {
63 if world.is_none() {
64 expr_arena.alloc(LogicExpr::Predicate {
66 name: *name,
67 args: *args,
68 world: Some(ctx.current_world),
69 })
70 } else {
71 expr
72 }
73 }
74
75 LogicExpr::Quantifier { kind, variable, body, island_id } => {
76 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
77 expr_arena.alloc(LogicExpr::Quantifier {
78 kind: *kind,
79 variable: *variable,
80 body: new_body,
81 island_id: *island_id,
82 })
83 }
84
85 LogicExpr::BinaryOp { left, op, right } => {
86 let new_left = lower_expr(left, ctx, expr_arena, term_arena, interner);
87 let new_right = lower_expr(right, ctx, expr_arena, term_arena, interner);
88 expr_arena.alloc(LogicExpr::BinaryOp {
89 left: new_left,
90 op: op.clone(),
91 right: new_right,
92 })
93 }
94
95 LogicExpr::UnaryOp { op, operand } => {
96 let new_operand = lower_expr(operand, ctx, expr_arena, term_arena, interner);
97 expr_arena.alloc(LogicExpr::UnaryOp {
98 op: op.clone(),
99 operand: new_operand,
100 })
101 }
102
103 LogicExpr::NeoEvent(data) => {
104 if data.world.is_none() {
106 expr_arena.alloc(LogicExpr::NeoEvent(Box::new(NeoEventData {
107 event_var: data.event_var,
108 verb: data.verb,
109 roles: data.roles,
110 modifiers: data.modifiers,
111 suppress_existential: data.suppress_existential,
112 world: Some(ctx.current_world),
113 })))
114 } else {
115 expr
116 }
117 }
118
119 LogicExpr::Temporal { operator, body } => {
120 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
121 expr_arena.alloc(LogicExpr::Temporal {
122 operator: *operator,
123 body: new_body,
124 })
125 }
126
127 LogicExpr::Aspectual { operator, body } => {
128 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
129 expr_arena.alloc(LogicExpr::Aspectual {
130 operator: *operator,
131 body: new_body,
132 })
133 }
134
135 LogicExpr::Voice { operator, body } => {
136 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
137 expr_arena.alloc(LogicExpr::Voice {
138 operator: *operator,
139 body: new_body,
140 })
141 }
142
143 LogicExpr::Lambda { variable, body } => {
144 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
145 expr_arena.alloc(LogicExpr::Lambda {
146 variable: *variable,
147 body: new_body,
148 })
149 }
150
151 LogicExpr::App { function, argument } => {
152 let new_function = lower_expr(function, ctx, expr_arena, term_arena, interner);
153 let new_argument = lower_expr(argument, ctx, expr_arena, term_arena, interner);
154 expr_arena.alloc(LogicExpr::App {
155 function: new_function,
156 argument: new_argument,
157 })
158 }
159
160 LogicExpr::Intensional { operator, content } => {
161 let new_content = lower_expr(content, ctx, expr_arena, term_arena, interner);
162 expr_arena.alloc(LogicExpr::Intensional {
163 operator: *operator,
164 content: new_content,
165 })
166 }
167
168 LogicExpr::Control { verb, subject, object, infinitive } => {
169 let new_infinitive = lower_expr(infinitive, ctx, expr_arena, term_arena, interner);
170 expr_arena.alloc(LogicExpr::Control {
171 verb: *verb,
172 subject: *subject,
173 object: *object,
174 infinitive: new_infinitive,
175 })
176 }
177
178 LogicExpr::Scopal { operator, body } => {
179 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
180 expr_arena.alloc(LogicExpr::Scopal {
181 operator: *operator,
182 body: new_body,
183 })
184 }
185
186 LogicExpr::Question { wh_variable, body } => {
187 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
188 expr_arena.alloc(LogicExpr::Question {
189 wh_variable: *wh_variable,
190 body: new_body,
191 })
192 }
193
194 LogicExpr::YesNoQuestion { body } => {
195 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
196 expr_arena.alloc(LogicExpr::YesNoQuestion { body: new_body })
197 }
198
199 LogicExpr::Focus { kind, focused, scope } => {
200 let new_scope = lower_expr(scope, ctx, expr_arena, term_arena, interner);
201 expr_arena.alloc(LogicExpr::Focus {
202 kind: *kind,
203 focused: *focused,
204 scope: new_scope,
205 })
206 }
207
208 LogicExpr::Distributive { predicate } => {
209 let new_predicate = lower_expr(predicate, ctx, expr_arena, term_arena, interner);
210 expr_arena.alloc(LogicExpr::Distributive {
211 predicate: new_predicate,
212 })
213 }
214
215 LogicExpr::Counterfactual { antecedent, consequent } => {
216 let new_antecedent = lower_expr(antecedent, ctx, expr_arena, term_arena, interner);
217 let new_consequent = lower_expr(consequent, ctx, expr_arena, term_arena, interner);
218 expr_arena.alloc(LogicExpr::Counterfactual {
219 antecedent: new_antecedent,
220 consequent: new_consequent,
221 })
222 }
223
224 LogicExpr::Event { predicate, adverbs } => {
225 let new_predicate = lower_expr(predicate, ctx, expr_arena, term_arena, interner);
226 expr_arena.alloc(LogicExpr::Event {
227 predicate: new_predicate,
228 adverbs: *adverbs,
229 })
230 }
231
232 LogicExpr::Imperative { action } => {
233 let new_action = lower_expr(action, ctx, expr_arena, term_arena, interner);
234 expr_arena.alloc(LogicExpr::Imperative { action: new_action })
235 }
236
237 LogicExpr::Causal { effect, cause } => {
238 let new_effect = lower_expr(effect, ctx, expr_arena, term_arena, interner);
239 let new_cause = lower_expr(cause, ctx, expr_arena, term_arena, interner);
240 expr_arena.alloc(LogicExpr::Causal {
241 effect: new_effect,
242 cause: new_cause,
243 })
244 }
245
246 LogicExpr::Presupposition { assertion, presupposition } => {
247 let new_assertion = lower_expr(assertion, ctx, expr_arena, term_arena, interner);
248 let new_presupposition = lower_expr(presupposition, ctx, expr_arena, term_arena, interner);
249 expr_arena.alloc(LogicExpr::Presupposition {
250 assertion: new_assertion,
251 presupposition: new_presupposition,
252 })
253 }
254
255 LogicExpr::TemporalAnchor { anchor, body } => {
256 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
257 expr_arena.alloc(LogicExpr::TemporalAnchor {
258 anchor: *anchor,
259 body: new_body,
260 })
261 }
262
263 LogicExpr::GroupQuantifier { group_var, count, member_var, restriction, body } => {
264 let new_restriction = lower_expr(restriction, ctx, expr_arena, term_arena, interner);
265 let new_body = lower_expr(body, ctx, expr_arena, term_arena, interner);
266 expr_arena.alloc(LogicExpr::GroupQuantifier {
267 group_var: *group_var,
268 count: *count,
269 member_var: *member_var,
270 restriction: new_restriction,
271 body: new_body,
272 })
273 }
274
275 LogicExpr::Identity { .. }
277 | LogicExpr::Metaphor { .. }
278 | LogicExpr::Categorical(_)
279 | LogicExpr::Relation(_)
280 | LogicExpr::Atom(_)
281 | LogicExpr::Superlative { .. }
282 | LogicExpr::Comparative { .. }
283 | LogicExpr::SpeechAct { .. } => expr,
284 }
285}
286
287fn lower_modal<'a>(
288 vector: &ModalVector,
289 operand: &'a LogicExpr<'a>,
290 ctx: &mut KripkeContext,
291 expr_arena: &'a Arena<LogicExpr<'a>>,
292 term_arena: &'a Arena<Term<'a>>,
293 interner: &mut Interner,
294) -> &'a LogicExpr<'a> {
295 let source_world = ctx.current_world;
296 let target_world = ctx.fresh_world(interner);
297
298 let old_world = ctx.current_world;
300 ctx.current_world = target_world;
301 let lowered_operand = lower_expr(operand, ctx, expr_arena, term_arena, interner);
302 ctx.current_world = old_world;
303
304 let access_name = match vector.domain {
306 ModalDomain::Alethic => interner.intern("Accessible_Alethic"),
307 ModalDomain::Deontic => interner.intern("Accessible_Deontic"),
308 };
309
310 let accessibility = expr_arena.alloc(LogicExpr::Predicate {
311 name: access_name,
312 args: term_arena.alloc_slice([
313 Term::Variable(source_world),
314 Term::Variable(target_world),
315 ]),
316 world: None, });
318
319 if vector.force > 0.5 {
320 let implication = expr_arena.alloc(LogicExpr::BinaryOp {
322 left: accessibility,
323 op: TokenType::If,
324 right: lowered_operand,
325 });
326 expr_arena.alloc(LogicExpr::Quantifier {
327 kind: QuantifierKind::Universal,
328 variable: target_world,
329 body: implication,
330 island_id: 0,
331 })
332 } else {
333 let conjunction = expr_arena.alloc(LogicExpr::BinaryOp {
335 left: accessibility,
336 op: TokenType::And,
337 right: lowered_operand,
338 });
339 expr_arena.alloc(LogicExpr::Quantifier {
340 kind: QuantifierKind::Existential,
341 variable: target_world,
342 body: conjunction,
343 island_id: 0,
344 })
345 }
346}