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!(
271 "expressiveness: {},",
272 expr_to_string(expressiveness)
273 ));
274 } else {
275 self.writeln("expressiveness: 0.5,");
276 }
277
278 if let Some(susceptibility) = &config.susceptibility {
279 self.writeln(&format!(
280 "susceptibility: {},",
281 expr_to_string(susceptibility)
282 ));
283 } else {
284 self.writeln("susceptibility: 0.5,");
285 }
286
287 self.writeln("..Default::default()");
288 self.indent -= 1;
289 self.writeln("},");
290 } else {
291 self.writeln("anima: AnimaState::default(),");
292 }
293 }
294
295 fn generate_state_machine_init(&mut self, states: &Option<AlterStateMachine>) {
297 if let Some(sm) = states {
298 self.writeln("state_machine: AlterStateMachine {");
299 self.indent += 1;
300 self.writeln("transitions: vec![");
301 self.indent += 1;
302
303 for transition in &sm.transitions {
304 self.writeln("AlterTransitionDef {");
305 self.indent += 1;
306 self.writeln(&format!("from: AlterRuntimeState::{:?},", transition.from));
307 self.writeln(&format!("to: AlterRuntimeState::{:?},", transition.to));
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(
513 "fn check_transform(&self, perception: &PerceptionState) -> Option<RealityLayer> {",
514 );
515 self.indent += 1;
516
517 for transform in &def.transforms {
518 self.writeln(&format!(
519 "if perception.current_layer() == RealityLayer::{} && ({}) {{",
520 transform.from.name,
521 expr_to_string(&transform.condition)
522 ));
523 self.indent += 1;
524 self.writeln(&format!(
525 "return Some(RealityLayer::{});",
526 transform.to.name
527 ));
528 self.indent -= 1;
529 self.writeln("}");
530 }
531
532 self.writeln("None");
533 self.indent -= 1;
534 self.writeln("}");
535 }
536
537 self.indent -= 1;
538 self.writeln("}");
539
540 self.output.clone()
541 }
542
543 pub fn generate_cocon_channel(&mut self, channel: &CoConChannel) -> String {
545 self.output.clear();
546
547 self.writeln(&format!("pub struct {}Channel {{", channel.name.name));
549 self.indent += 1;
550 self.writeln("participants: Vec<AlterId>,");
551 self.writeln("active: bool,");
552 self.indent -= 1;
553 self.writeln("}");
554 self.writeln("");
555
556 self.writeln(&format!("impl {}Channel {{", channel.name.name));
558 self.indent += 1;
559
560 self.writeln("pub fn new() -> Self {");
562 self.indent += 1;
563 self.writeln("Self {");
564 self.indent += 1;
565 self.write("participants: vec![");
566 for (i, p) in channel.participants.iter().enumerate() {
567 if i > 0 {
568 self.write(", ");
569 }
570 self.write(&format!("AlterId::{}", p.name));
571 }
572 self.writeln("],");
573 self.writeln("active: false,");
574 self.indent -= 1;
575 self.writeln("}");
576 self.indent -= 1;
577 self.writeln("}");
578 self.writeln("");
579
580 self.writeln(
582 "pub fn activate(&mut self, system: &PluralSystem) -> Result<(), ChannelError> {",
583 );
584 self.indent += 1;
585 self.writeln("for &p in &self.participants {");
586 self.indent += 1;
587 self.writeln("if !system.is_cocon(p) {");
588 self.indent += 1;
589 self.writeln("return Err(ChannelError::NotCoConscious(p));");
590 self.indent -= 1;
591 self.writeln("}");
592 self.indent -= 1;
593 self.writeln("}");
594 self.writeln("self.active = true;");
595 self.writeln("Ok(())");
596 self.indent -= 1;
597 self.writeln("}");
598
599 self.indent -= 1;
600 self.writeln("}");
601
602 self.output.clone()
603 }
604
605 pub fn generate_trigger_handler(&mut self, handler: &TriggerHandler) -> String {
607 self.output.clear();
608
609 self.writeln(&format!(
611 "pub fn handle_{}(ctx: &mut TriggerContext) -> TriggerResult {{",
612 handler.pattern.trigger_type.name.to_lowercase()
613 ));
614 self.indent += 1;
615
616 if !handler.pattern.fields.is_empty() {
618 self.write(&format!("let {} {{ ", handler.pattern.trigger_type.name));
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!(
677 out,
678 " bypass_deliberation: {},",
679 expr.config.bypass_deliberation
680 )
681 .unwrap();
682 write!(out, " ..Default::default() }})").unwrap();
683
684 if expr.config.then_block.is_some() || expr.config.else_block.is_some() {
686 write!(out, ".handle(|result| match result {{ ").unwrap();
687 if expr.config.then_block.is_some() {
688 write!(out, "SwitchResult::Success => {{ /* then block */ }}, ").unwrap();
689 }
690 if expr.config.else_block.is_some() {
691 write!(out, "SwitchResult::Denied(_) => {{ /* else block */ }}, ").unwrap();
692 }
693 if expr.config.emergency_block.is_some() {
694 write!(
695 out,
696 "SwitchResult::Emergency => {{ /* emergency block */ }}, "
697 )
698 .unwrap();
699 }
700 write!(out, "_ => {{}} }})").unwrap();
701 }
702
703 out
704 }
705
706 pub fn generate_split_expr(&mut self, expr: &SplitExpr) -> String {
708 let mut out = String::new();
709
710 write!(out, "system.process_split(SplitRequest {{").unwrap();
711 write!(out, " parent: {},", alter_expr_to_string(&expr.parent)).unwrap();
712
713 if let Some(purpose) = &expr.config.purpose {
714 write!(out, " purpose: {},", expr_to_string(purpose)).unwrap();
715 }
716
717 if let Some(memories) = &expr.config.memories {
718 write!(out, " memories: {},", expr_to_string(memories)).unwrap();
719 }
720
721 if let Some(traits) = &expr.config.traits {
722 write!(out, " traits: {},", expr_to_string(traits)).unwrap();
723 }
724
725 write!(out, " ..Default::default() }})").unwrap();
726
727 out
728 }
729
730 pub fn generate_alter_block(&mut self, block: &AlterBlock) -> String {
732 let mut out = String::new();
733
734 write!(out, "{{ let _alter_guard = system.enter_alter::<").unwrap();
735 write!(out, "{}", alter_expr_to_string(&block.alter)).unwrap();
736 write!(out, ">();").unwrap();
737 write!(out, " /* block body */ }}").unwrap();
738
739 out
740 }
741
742 fn write(&mut self, s: &str) {
745 self.output.push_str(s);
746 }
747
748 fn writeln(&mut self, s: &str) {
749 for _ in 0..self.indent {
750 self.output.push_str(" ");
751 }
752 self.output.push_str(s);
753 self.output.push('\n');
754 }
755
756 fn write_visibility(&mut self, vis: &Visibility) {
757 match vis {
758 Visibility::Public => self.write("pub "),
759 Visibility::Crate => self.write("pub(crate) "),
760 Visibility::Super => self.write("pub(super) "),
761 Visibility::Private => {}
762 }
763 }
764}
765
766fn expr_to_string(expr: &crate::ast::Expr) -> String {
772 format!("{:?}", expr).replace('"', "'")
773}
774
775fn type_to_string(ty: &crate::ast::TypeExpr) -> String {
777 format!("{:?}", ty)
778}
779
780fn alter_expr_to_string(alter: &AlterExpr) -> String {
782 match alter {
783 AlterExpr::Named(ident) => ident.name.clone(),
784 AlterExpr::CurrentFronter(_) => "system.current_fronter()".to_string(),
785 AlterExpr::Expr(expr) => expr_to_string(expr),
786 }
787}
788
789fn is_self_pattern(pattern: &crate::ast::Pattern) -> bool {
791 match pattern {
792 crate::ast::Pattern::Ident { name, .. } => name.name == "self",
793 _ => false,
794 }
795}
796
797fn pattern_to_string(pattern: &crate::ast::Pattern) -> String {
799 match pattern {
800 crate::ast::Pattern::Ident { mutable, name, .. } => {
801 if *mutable {
802 format!("mut {}", name.name)
803 } else {
804 name.name.clone()
805 }
806 }
807 crate::ast::Pattern::Tuple(patterns) => {
808 let inner: Vec<_> = patterns.iter().map(pattern_to_string).collect();
809 format!("({})", inner.join(", "))
810 }
811 _ => format!("{:?}", pattern),
812 }
813}
814
815#[cfg(test)]
820mod tests {
821 use super::*;
822 use crate::ast::{Expr, Ident, Literal};
823 use crate::span::Span;
824
825 fn mock_ident(name: &str) -> Ident {
826 Ident {
827 name: name.to_string(),
828 evidentiality: None,
829 affect: None,
830 span: Span::default(),
831 }
832 }
833
834 #[test]
835 fn test_generate_alter_def() {
836 let def = AlterDef {
837 visibility: Visibility::Public,
838 attrs: Vec::new(),
839 name: mock_ident("Abaddon"),
840 category: AlterCategory::Council,
841 generics: None,
842 where_clause: None,
843 body: AlterBody {
844 archetype: Some(Expr::Path(crate::ast::TypePath {
845 segments: vec![crate::ast::PathSegment {
846 ident: mock_ident("Goetia"),
847 generics: None,
848 }],
849 })),
850 preferred_reality: None,
851 abilities: Vec::new(),
852 triggers: Vec::new(),
853 anima: None,
854 states: None,
855 special: Vec::new(),
856 methods: Vec::new(),
857 types: Vec::new(),
858 },
859 span: Span::default(),
860 };
861
862 let mut gen = PluralityCodeGen::new("test");
863 let output = gen.generate_alter_def(&def);
864
865 assert!(output.contains("struct Abaddon"));
866 assert!(output.contains("impl Alter for Abaddon"));
867 assert!(output.contains("AlterCategory::Council"));
868 }
869
870 #[test]
871 fn test_generate_switch_expr() {
872 let expr = SwitchExpr {
873 forced: false,
874 target: AlterExpr::Named(mock_ident("Beleth")),
875 config: SwitchConfig {
876 reason: Some(Expr::Literal(Literal::String("Combat".to_string()))),
877 urgency: Some(Expr::Literal(Literal::Float {
878 value: "0.8".to_string(),
879 suffix: None,
880 })),
881 requires: None,
882 then_block: None,
883 else_block: None,
884 emergency_block: None,
885 bypass_deliberation: false,
886 },
887 span: Span::default(),
888 };
889
890 let mut gen = PluralityCodeGen::new("test");
891 let output = gen.generate_switch_expr(&expr);
892
893 assert!(output.contains("propose_switch"));
894 assert!(output.contains("Beleth"));
895 }
896
897 #[test]
898 fn test_generate_alter_block() {
899 let block = AlterBlock {
900 alter: AlterExpr::Named(mock_ident("Abaddon")),
901 body: crate::ast::Block {
902 stmts: Vec::new(),
903 expr: None,
904 },
905 span: Span::default(),
906 };
907
908 let mut gen = PluralityCodeGen::new("test");
909 let output = gen.generate_alter_block(&block);
910
911 assert!(output.contains("enter_alter"));
912 assert!(output.contains("Abaddon"));
913 }
914}