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