1use std::fmt::Write;
52
53use super::ast::*;
54use crate::ast::Visibility;
55
56#[derive(Debug, Default)]
62pub struct PluralityCodeGen {
63 output: String,
65 indent: usize,
67 #[allow(dead_code)]
69 module_name: String,
70}
71
72impl PluralityCodeGen {
73 pub fn new(module_name: &str) -> Self {
75 Self {
76 output: String::new(),
77 indent: 0,
78 module_name: module_name.to_string(),
79 }
80 }
81
82 pub fn generate_item(&mut self, item: &PluralityItem) -> String {
84 match item {
85 PluralityItem::Alter(def) => self.generate_alter_def(def),
86 PluralityItem::Headspace(def) => self.generate_headspace_def(def),
87 PluralityItem::Reality(def) => self.generate_reality_def(def),
88 PluralityItem::CoConChannel(channel) => self.generate_cocon_channel(channel),
89 PluralityItem::TriggerHandler(handler) => self.generate_trigger_handler(handler),
90 }
91 }
92
93 pub fn generate_alter_def(&mut self, def: &AlterDef) -> String {
95 self.output.clear();
96
97 self.write_visibility(&def.visibility);
99 self.writeln(&format!("struct {} {{", def.name.name));
100 self.indent += 1;
101
102 self.writeln("pub archetype: Option<Archetype>,");
104 self.writeln("pub preferred_reality: RealityLayer,");
105 self.writeln("pub abilities: Vec<Ability>,");
106 self.writeln("pub triggers: Vec<TriggerDef>,");
107 self.writeln("pub anima: AnimaState,");
108 self.writeln("pub state_machine: AlterStateMachine,");
109 self.writeln("pub state: AlterRuntimeState,");
110
111 self.indent -= 1;
112 self.writeln("}");
113 self.writeln("");
114
115 self.generate_alter_default(def);
117
118 self.generate_alter_trait_impl(def);
120
121 if !def.body.methods.is_empty() {
123 self.writeln(&format!("impl {} {{", def.name.name));
124 self.indent += 1;
125
126 for method in &def.body.methods {
127 self.generate_alter_method(method);
128 }
129
130 self.indent -= 1;
131 self.writeln("}");
132 }
133
134 self.output.clone()
135 }
136
137 fn generate_alter_default(&mut self, def: &AlterDef) {
139 self.writeln(&format!("impl Default for {} {{", def.name.name));
140 self.indent += 1;
141 self.writeln("fn default() -> Self {");
142 self.indent += 1;
143 self.writeln("Self {");
144 self.indent += 1;
145
146 if let Some(archetype) = &def.body.archetype {
148 self.writeln(&format!("archetype: Some({}),", expr_to_string(archetype)));
149 } else {
150 self.writeln("archetype: None,");
151 }
152
153 if let Some(reality) = &def.body.preferred_reality {
155 self.writeln(&format!("preferred_reality: {},", expr_to_string(reality)));
156 } else {
157 self.writeln("preferred_reality: RealityLayer::Grounded,");
158 }
159
160 self.write("abilities: vec![");
162 for (i, ability) in def.body.abilities.iter().enumerate() {
163 if i > 0 {
164 self.write(", ");
165 }
166 self.write(&expr_to_string(ability));
167 }
168 self.writeln("],");
169
170 self.write("triggers: vec![");
172 for (i, trigger) in def.body.triggers.iter().enumerate() {
173 if i > 0 {
174 self.write(", ");
175 }
176 self.write(&expr_to_string(trigger));
177 }
178 self.writeln("],");
179
180 self.generate_anima_init(&def.body.anima);
182
183 self.generate_state_machine_init(&def.body.states);
185
186 self.writeln("state: AlterRuntimeState::Dormant,");
188
189 self.indent -= 1;
190 self.writeln("}");
191 self.indent -= 1;
192 self.writeln("}");
193 self.indent -= 1;
194 self.writeln("}");
195 self.writeln("");
196 }
197
198 fn generate_alter_trait_impl(&mut self, def: &AlterDef) {
200 self.writeln(&format!("impl Alter for {} {{", def.name.name));
201 self.indent += 1;
202
203 let category = match def.category {
205 AlterCategory::Council => "AlterCategory::Council",
206 AlterCategory::Servant => "AlterCategory::Servant",
207 AlterCategory::Fragment => "AlterCategory::Fragment",
208 AlterCategory::Hidden => "AlterCategory::Hidden",
209 AlterCategory::Persecutor => "AlterCategory::Persecutor",
210 AlterCategory::Custom => "AlterCategory::Custom",
211 };
212 self.writeln(&format!(
213 "fn category(&self) -> AlterCategory {{ {} }}",
214 category
215 ));
216
217 let can_front = matches!(def.category, AlterCategory::Council);
219 self.writeln(&format!("fn can_front(&self) -> bool {{ {} }}", can_front));
220
221 self.writeln(&format!(
223 "fn name(&self) -> &'static str {{ \"{}\" }}",
224 def.name.name
225 ));
226
227 self.writeln("fn archetype(&self) -> Option<&Archetype> { self.archetype.as_ref() }");
229
230 self.writeln("fn preferred_reality(&self) -> RealityLayer { self.preferred_reality }");
232
233 self.writeln("fn abilities(&self) -> &[Ability] { &self.abilities }");
235
236 self.writeln("fn triggers(&self) -> &[TriggerDef] { &self.triggers }");
238
239 self.writeln("fn anima(&self) -> &AnimaState { &self.anima }");
241 self.writeln("fn anima_mut(&mut self) -> &mut AnimaState { &mut self.anima }");
242
243 self.writeln("fn state(&self) -> AlterRuntimeState { self.state }");
245 self.writeln("fn set_state(&mut self, state: AlterRuntimeState) { self.state = state; }");
246
247 self.indent -= 1;
248 self.writeln("}");
249 self.writeln("");
250 }
251
252 fn generate_anima_init(&mut self, anima: &Option<AnimaConfig>) {
254 if let Some(config) = anima {
255 self.writeln("anima: AnimaState {");
256 self.indent += 1;
257
258 if let Some(arousal) = &config.base_arousal {
259 self.writeln(&format!("arousal: {},", expr_to_string(arousal)));
260 } else {
261 self.writeln("arousal: 0.5,");
262 }
263
264 if let Some(dominance) = &config.base_dominance {
265 self.writeln(&format!("dominance: {},", expr_to_string(dominance)));
266 } else {
267 self.writeln("dominance: 0.5,");
268 }
269
270 if let Some(expressiveness) = &config.expressiveness {
271 self.writeln(&format!("expressiveness: {},", expr_to_string(expressiveness)));
272 } else {
273 self.writeln("expressiveness: 0.5,");
274 }
275
276 if let Some(susceptibility) = &config.susceptibility {
277 self.writeln(&format!("susceptibility: {},", expr_to_string(susceptibility)));
278 } else {
279 self.writeln("susceptibility: 0.5,");
280 }
281
282 self.writeln("..Default::default()");
283 self.indent -= 1;
284 self.writeln("},");
285 } else {
286 self.writeln("anima: AnimaState::default(),");
287 }
288 }
289
290 fn generate_state_machine_init(&mut self, states: &Option<AlterStateMachine>) {
292 if let Some(sm) = states {
293 self.writeln("state_machine: AlterStateMachine {");
294 self.indent += 1;
295 self.writeln("transitions: vec![");
296 self.indent += 1;
297
298 for transition in &sm.transitions {
299 self.writeln("AlterTransitionDef {");
300 self.indent += 1;
301 self.writeln(&format!(
302 "from: AlterRuntimeState::{:?},",
303 transition.from
304 ));
305 self.writeln(&format!(
306 "to: AlterRuntimeState::{:?},",
307 transition.to
308 ));
309 self.writeln(&format!(
310 "on: TriggerCondition::from({}),",
311 expr_to_string(&transition.on)
312 ));
313
314 if let Some(guard) = &transition.guard {
315 self.writeln(&format!(
316 "guard: Some(Box::new(|ctx| {})),",
317 expr_to_string(guard)
318 ));
319 } else {
320 self.writeln("guard: None,");
321 }
322
323 if transition.action.is_some() {
324 self.writeln("action: Some(Box::new(|ctx| { /* action */ })),");
325 } else {
326 self.writeln("action: None,");
327 }
328
329 self.indent -= 1;
330 self.writeln("},");
331 }
332
333 self.indent -= 1;
334 self.writeln("],");
335 self.indent -= 1;
336 self.writeln("},");
337 } else {
338 self.writeln("state_machine: AlterStateMachine::default(),");
339 }
340 }
341
342 fn generate_alter_method(&mut self, method: &AlterMethod) {
344 self.write_visibility(&method.visibility);
345
346 if method.is_async {
347 self.write("async ");
348 }
349
350 self.write(&format!("fn {}(&", method.name.name));
351 if method.params.iter().any(|p| is_self_pattern(&p.pattern)) {
352 self.write("mut self");
353 } else {
354 self.write("self");
355 }
356
357 for param in &method.params {
358 if !is_self_pattern(¶m.pattern) {
359 self.write(&format!(", {}", pattern_to_string(¶m.pattern)));
360 self.write(&format!(": {}", type_to_string(¶m.ty)));
361 }
362 }
363 self.write(")");
364
365 if let Some(ret_ty) = &method.return_type {
366 self.write(&format!(" -> {}", type_to_string(ret_ty)));
367 }
368
369 if let Some(_body) = &method.body {
370 self.writeln(" {");
371 self.indent += 1;
372 self.writeln("// Method body");
373 self.indent -= 1;
374 self.writeln("}");
375 } else {
376 self.writeln(";");
377 }
378 }
379
380 pub fn generate_headspace_def(&mut self, def: &HeadspaceDef) -> String {
382 self.output.clear();
383
384 self.write_visibility(&def.visibility);
386 self.writeln(&format!("mod {} {{", def.name.name.to_lowercase()));
387 self.indent += 1;
388 self.writeln("use super::*;");
389 self.writeln("");
390
391 for location in &def.locations {
393 self.generate_location_struct(location);
394 }
395
396 self.writeln(&format!("pub struct {} {{", def.name.name));
398 self.indent += 1;
399 for location in &def.locations {
400 self.writeln(&format!(
401 "pub {}: {},",
402 location.name.name.to_lowercase(),
403 location.name.name
404 ));
405 }
406 self.indent -= 1;
407 self.writeln("}");
408 self.writeln("");
409
410 if !def.methods.is_empty() {
412 self.writeln(&format!("impl {} {{", def.name.name));
413 self.indent += 1;
414 for method in &def.methods {
415 self.generate_alter_method(method);
416 }
417 self.indent -= 1;
418 self.writeln("}");
419 }
420
421 self.indent -= 1;
422 self.writeln("}");
423
424 self.output.clone()
425 }
426
427 fn generate_location_struct(&mut self, location: &LocationDef) {
429 self.writeln(&format!("pub struct {} {{", location.name.name));
430 self.indent += 1;
431 self.writeln(&format!(
432 "pub location_type: {},",
433 location.location_type.name
434 ));
435
436 for (field_name, _) in &location.fields {
437 self.writeln(&format!("pub {}: LocationField,", field_name.name));
439 }
440
441 if !location.connections.is_empty() {
442 self.writeln("pub connections: Vec<ConsciousnessStream>,");
443 }
444
445 if !location.hazards.is_empty() {
446 self.writeln("pub hazards: Vec<Hazard>,");
447 }
448
449 self.indent -= 1;
450 self.writeln("}");
451 self.writeln("");
452 }
453
454 pub fn generate_reality_def(&mut self, def: &RealityDef) -> String {
456 self.output.clear();
457
458 self.write_visibility(&def.visibility);
460 self.writeln(&format!("struct {} {{", def.name.name));
461 self.indent += 1;
462
463 for layer in &def.layers {
464 self.writeln(&format!(
465 "pub {}: {}Layer,",
466 layer.name.name.to_lowercase(),
467 layer.name.name
468 ));
469 }
470
471 self.indent -= 1;
472 self.writeln("}");
473 self.writeln("");
474
475 for layer in &def.layers {
477 self.writeln(&format!("pub struct {}Layer {{", layer.name.name));
478 self.indent += 1;
479 for (field_name, _) in &layer.fields {
480 self.writeln(&format!("pub {}: RealityValue,", field_name.name));
481 }
482 self.indent -= 1;
483 self.writeln("}");
484 self.writeln("");
485 }
486
487 self.writeln(&format!("impl Superimposed for {} {{", def.name.name));
489 self.indent += 1;
490
491 self.writeln("fn current(&self, perception: &PerceptionState) -> &dyn RealityLayerView {");
492 self.indent += 1;
493 self.writeln("match perception.current_layer() {");
494 self.indent += 1;
495
496 for layer in &def.layers {
497 self.writeln(&format!(
498 "RealityLayer::{} => &self.{},",
499 layer.name.name,
500 layer.name.name.to_lowercase()
501 ));
502 }
503 self.writeln("_ => &self.grounded,");
504
505 self.indent -= 1;
506 self.writeln("}");
507 self.indent -= 1;
508 self.writeln("}");
509
510 if !def.transforms.is_empty() {
512 self.writeln("");
513 self.writeln("fn check_transform(&self, perception: &PerceptionState) -> Option<RealityLayer> {");
514 self.indent += 1;
515
516 for transform in &def.transforms {
517 self.writeln(&format!(
518 "if perception.current_layer() == RealityLayer::{} && ({}) {{",
519 transform.from.name,
520 expr_to_string(&transform.condition)
521 ));
522 self.indent += 1;
523 self.writeln(&format!(
524 "return Some(RealityLayer::{});",
525 transform.to.name
526 ));
527 self.indent -= 1;
528 self.writeln("}");
529 }
530
531 self.writeln("None");
532 self.indent -= 1;
533 self.writeln("}");
534 }
535
536 self.indent -= 1;
537 self.writeln("}");
538
539 self.output.clone()
540 }
541
542 pub fn generate_cocon_channel(&mut self, channel: &CoConChannel) -> String {
544 self.output.clear();
545
546 self.writeln(&format!("pub struct {}Channel {{", channel.name.name));
548 self.indent += 1;
549 self.writeln("participants: Vec<AlterId>,");
550 self.writeln("active: bool,");
551 self.indent -= 1;
552 self.writeln("}");
553 self.writeln("");
554
555 self.writeln(&format!("impl {}Channel {{", channel.name.name));
557 self.indent += 1;
558
559 self.writeln("pub fn new() -> Self {");
561 self.indent += 1;
562 self.writeln("Self {");
563 self.indent += 1;
564 self.write("participants: vec![");
565 for (i, p) in channel.participants.iter().enumerate() {
566 if i > 0 {
567 self.write(", ");
568 }
569 self.write(&format!("AlterId::{}", p.name));
570 }
571 self.writeln("],");
572 self.writeln("active: false,");
573 self.indent -= 1;
574 self.writeln("}");
575 self.indent -= 1;
576 self.writeln("}");
577 self.writeln("");
578
579 self.writeln("pub fn activate(&mut self, system: &PluralSystem) -> Result<(), ChannelError> {");
581 self.indent += 1;
582 self.writeln("for &p in &self.participants {");
583 self.indent += 1;
584 self.writeln("if !system.is_cocon(p) {");
585 self.indent += 1;
586 self.writeln("return Err(ChannelError::NotCoConscious(p));");
587 self.indent -= 1;
588 self.writeln("}");
589 self.indent -= 1;
590 self.writeln("}");
591 self.writeln("self.active = true;");
592 self.writeln("Ok(())");
593 self.indent -= 1;
594 self.writeln("}");
595
596 self.indent -= 1;
597 self.writeln("}");
598
599 self.output.clone()
600 }
601
602 pub fn generate_trigger_handler(&mut self, handler: &TriggerHandler) -> String {
604 self.output.clear();
605
606 self.writeln(&format!(
608 "pub fn handle_{}(ctx: &mut TriggerContext) -> TriggerResult {{",
609 handler.pattern.trigger_type.name.to_lowercase()
610 ));
611 self.indent += 1;
612
613 if !handler.pattern.fields.is_empty() {
615 self.write(&format!(
616 "let {} {{ ",
617 handler.pattern.trigger_type.name
618 ));
619 for (i, (field, binding)) in handler.pattern.fields.iter().enumerate() {
620 if i > 0 {
621 self.write(", ");
622 }
623 if field.name != binding.name {
624 self.write(&format!("{}: {}", field.name, binding.name));
625 } else {
626 self.write(&binding.name);
627 }
628 }
629 self.writeln(" } = ctx.trigger();");
630 }
631
632 if let Some(guard) = &handler.guard {
634 self.writeln(&format!("if !({}) {{", expr_to_string(guard)));
635 self.indent += 1;
636 self.writeln("return TriggerResult::Ignored;");
637 self.indent -= 1;
638 self.writeln("}");
639 }
640
641 self.writeln("// Handler body");
643 self.writeln("TriggerResult::Handled");
644
645 self.indent -= 1;
646 self.writeln("}");
647
648 self.output.clone()
649 }
650
651 pub fn generate_switch_expr(&mut self, expr: &SwitchExpr) -> String {
653 let mut out = String::new();
654
655 if expr.forced {
656 write!(out, "system.force_switch(").unwrap();
657 } else {
658 write!(out, "system.propose_switch(").unwrap();
659 }
660
661 write!(out, "SwitchRequest {{").unwrap();
662 write!(out, " target: {},", alter_expr_to_string(&expr.target)).unwrap();
663
664 if let Some(reason) = &expr.config.reason {
665 write!(out, " reason: {},", expr_to_string(reason)).unwrap();
666 }
667
668 if let Some(urgency) = &expr.config.urgency {
669 write!(out, " urgency: {},", expr_to_string(urgency)).unwrap();
670 }
671
672 if let Some(requires) = &expr.config.requires {
673 write!(out, " requires: {},", expr_to_string(requires)).unwrap();
674 }
675
676 write!(out, " bypass_deliberation: {},", expr.config.bypass_deliberation).unwrap();
677 write!(out, " ..Default::default() }})").unwrap();
678
679 if expr.config.then_block.is_some() || expr.config.else_block.is_some() {
681 write!(out, ".handle(|result| match result {{ ").unwrap();
682 if expr.config.then_block.is_some() {
683 write!(out, "SwitchResult::Success => {{ /* then block */ }}, ").unwrap();
684 }
685 if expr.config.else_block.is_some() {
686 write!(out, "SwitchResult::Denied(_) => {{ /* else block */ }}, ").unwrap();
687 }
688 if expr.config.emergency_block.is_some() {
689 write!(out, "SwitchResult::Emergency => {{ /* emergency block */ }}, ").unwrap();
690 }
691 write!(out, "_ => {{}} }})").unwrap();
692 }
693
694 out
695 }
696
697 pub fn generate_split_expr(&mut self, expr: &SplitExpr) -> String {
699 let mut out = String::new();
700
701 write!(out, "system.process_split(SplitRequest {{").unwrap();
702 write!(out, " parent: {},", alter_expr_to_string(&expr.parent)).unwrap();
703
704 if let Some(purpose) = &expr.config.purpose {
705 write!(out, " purpose: {},", expr_to_string(purpose)).unwrap();
706 }
707
708 if let Some(memories) = &expr.config.memories {
709 write!(out, " memories: {},", expr_to_string(memories)).unwrap();
710 }
711
712 if let Some(traits) = &expr.config.traits {
713 write!(out, " traits: {},", expr_to_string(traits)).unwrap();
714 }
715
716 write!(out, " ..Default::default() }})").unwrap();
717
718 out
719 }
720
721 pub fn generate_alter_block(&mut self, block: &AlterBlock) -> String {
723 let mut out = String::new();
724
725 write!(out, "{{ let _alter_guard = system.enter_alter::<").unwrap();
726 write!(out, "{}", alter_expr_to_string(&block.alter)).unwrap();
727 write!(out, ">();").unwrap();
728 write!(out, " /* block body */ }}").unwrap();
729
730 out
731 }
732
733 fn write(&mut self, s: &str) {
736 self.output.push_str(s);
737 }
738
739 fn writeln(&mut self, s: &str) {
740 for _ in 0..self.indent {
741 self.output.push_str(" ");
742 }
743 self.output.push_str(s);
744 self.output.push('\n');
745 }
746
747 fn write_visibility(&mut self, vis: &Visibility) {
748 match vis {
749 Visibility::Public => self.write("pub "),
750 Visibility::Crate => self.write("pub(crate) "),
751 Visibility::Super => self.write("pub(super) "),
752 Visibility::Private => {}
753 }
754 }
755}
756
757fn expr_to_string(expr: &crate::ast::Expr) -> String {
763 format!("{:?}", expr).replace('"', "'")
764}
765
766fn type_to_string(ty: &crate::ast::TypeExpr) -> String {
768 format!("{:?}", ty)
769}
770
771fn alter_expr_to_string(alter: &AlterExpr) -> String {
773 match alter {
774 AlterExpr::Named(ident) => ident.name.clone(),
775 AlterExpr::CurrentFronter(_) => "system.current_fronter()".to_string(),
776 AlterExpr::Expr(expr) => expr_to_string(expr),
777 }
778}
779
780fn is_self_pattern(pattern: &crate::ast::Pattern) -> bool {
782 match pattern {
783 crate::ast::Pattern::Ident { name, .. } => name.name == "self",
784 _ => false,
785 }
786}
787
788fn pattern_to_string(pattern: &crate::ast::Pattern) -> String {
790 match pattern {
791 crate::ast::Pattern::Ident { mutable, name, .. } => {
792 if *mutable {
793 format!("mut {}", name.name)
794 } else {
795 name.name.clone()
796 }
797 }
798 crate::ast::Pattern::Tuple(patterns) => {
799 let inner: Vec<_> = patterns.iter().map(pattern_to_string).collect();
800 format!("({})", inner.join(", "))
801 }
802 _ => format!("{:?}", pattern),
803 }
804}
805
806#[cfg(test)]
811mod tests {
812 use super::*;
813 use crate::ast::{Expr, Ident, Literal};
814 use crate::span::Span;
815
816 fn mock_ident(name: &str) -> Ident {
817 Ident {
818 name: name.to_string(),
819 evidentiality: None,
820 affect: None,
821 span: Span::default(),
822 }
823 }
824
825 #[test]
826 fn test_generate_alter_def() {
827 let def = AlterDef {
828 visibility: Visibility::Public,
829 attrs: Vec::new(),
830 name: mock_ident("Abaddon"),
831 category: AlterCategory::Council,
832 generics: None,
833 where_clause: None,
834 body: AlterBody {
835 archetype: Some(Expr::Path(crate::ast::TypePath {
836 segments: vec![crate::ast::PathSegment {
837 ident: mock_ident("Goetia"),
838 generics: None,
839 }],
840 })),
841 preferred_reality: None,
842 abilities: Vec::new(),
843 triggers: Vec::new(),
844 anima: None,
845 states: None,
846 special: Vec::new(),
847 methods: Vec::new(),
848 types: Vec::new(),
849 },
850 span: Span::default(),
851 };
852
853 let mut gen = PluralityCodeGen::new("test");
854 let output = gen.generate_alter_def(&def);
855
856 assert!(output.contains("struct Abaddon"));
857 assert!(output.contains("impl Alter for Abaddon"));
858 assert!(output.contains("AlterCategory::Council"));
859 }
860
861 #[test]
862 fn test_generate_switch_expr() {
863 let expr = SwitchExpr {
864 forced: false,
865 target: AlterExpr::Named(mock_ident("Beleth")),
866 config: SwitchConfig {
867 reason: Some(Expr::Literal(Literal::String("Combat".to_string()))),
868 urgency: Some(Expr::Literal(Literal::Float {
869 value: "0.8".to_string(),
870 suffix: None,
871 })),
872 requires: None,
873 then_block: None,
874 else_block: None,
875 emergency_block: None,
876 bypass_deliberation: false,
877 },
878 span: Span::default(),
879 };
880
881 let mut gen = PluralityCodeGen::new("test");
882 let output = gen.generate_switch_expr(&expr);
883
884 assert!(output.contains("propose_switch"));
885 assert!(output.contains("Beleth"));
886 }
887
888 #[test]
889 fn test_generate_alter_block() {
890 let block = AlterBlock {
891 alter: AlterExpr::Named(mock_ident("Abaddon")),
892 body: crate::ast::Block {
893 stmts: Vec::new(),
894 expr: None,
895 },
896 span: Span::default(),
897 };
898
899 let mut gen = PluralityCodeGen::new("test");
900 let output = gen.generate_alter_block(&block);
901
902 assert!(output.contains("enter_alter"));
903 assert!(output.contains("Abaddon"));
904 }
905}