Browse Source

Simpler Rust code for single-instance "class diagrams"

Joeri Exelmans 4 years ago
parent
commit
5f98ee0c08
3 changed files with 24 additions and 45 deletions
  1. 19 40
      src/sccd/cd/codegen/sccdlib.rs
  2. 2 2
      src/sccd/statechart/codegen/rust.py
  3. 3 3
      src/sccd/test/codegen/rust.py

+ 19 - 40
src/sccd/cd/codegen/sccdlib.rs

@@ -3,7 +3,6 @@ use std::collections::binary_heap::PeekMut;
 use std::cmp::Ordering;
 
 type Timestamp = usize; // unsigned integer, platform's word size
-// type OutputCallback = fn(&str, &str);
 
 pub trait State<OutputCallback> {
   fn enter_actions(output: &mut OutputCallback);
@@ -18,67 +17,54 @@ pub trait SC<EventType, OutputCallback> {
   fn fair_step(&mut self, event: Option<EventType>, output: &mut OutputCallback);
 }
 
-pub enum Target<'a, EventType, OutputCallback> {
-  Narrowcast(&'a mut dyn SC<EventType, OutputCallback>),
-  Broadcast,
-}
-
-pub struct Entry<'a, EventType, OutputCallback> {
+pub struct Entry<EventType> {
   timestamp: Timestamp,
   event: EventType,
-  target: Target<'a, EventType, OutputCallback>,
 }
 
-impl<'a, EventType, OutputCallback> Ord for Entry<'a, EventType, OutputCallback> {
+// In order to implement Ord, also gotta implement PartialOrd, PartialEq and Eq:
+
+impl<EventType> Ord for Entry<EventType> {
   fn cmp(&self, other: &Self) -> Ordering {
     self.timestamp.cmp(&other.timestamp).reverse()
   }
 }
-
-impl<'a, EventType, OutputCallback> PartialOrd for Entry<'a, EventType, OutputCallback> {
+impl<EventType> PartialOrd for Entry<EventType> {
     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
         Some(self.cmp(other))
     }
 }
-
-impl<'a, EventType, OutputCallback> PartialEq for Entry<'a, EventType, OutputCallback> {
+impl<EventType> PartialEq for Entry<EventType> {
     fn eq(&self, other: &Self) -> bool {
         self.timestamp == other.timestamp
     }
 }
-
-impl<'a, EventType, OutputCallback> Eq for Entry<'a, EventType, OutputCallback> {}
+impl<EventType> Eq for Entry<EventType> {}
 
 
-pub struct Controller<'a, EventType, OutputCallback> {
-  queue: BinaryHeap<Entry<'a, EventType, OutputCallback>>,
-  simtime: Timestamp,
+pub struct Controller<EventType, OutputCallback, StatechartType: SC<EventType, OutputCallback>> {
+  statechart: StatechartType,
   output: OutputCallback,
+  queue: BinaryHeap<Entry<EventType>>,
+  simtime: Timestamp,
 }
 
-// impl<'a, EventType> Default for Controller<'a, EventType> {
-//   fn default() -> Self {
-//     Self {
-//       queue: BinaryHeap::new(),
-//       simtime: 0,
-//     }
-//   }
-// }
-
 pub enum Until {
   Timestamp(Timestamp),
   Eternity,
 }
 
-impl<'a, EventType: Copy, OutputCallback: FnMut(&'static str, &'static str)> Controller<'a, EventType, OutputCallback> {
-  fn new(output: OutputCallback) -> Self {
+impl<'a, EventType: Copy, OutputCallback: FnMut(&'a str, &'a str), StatechartType: SC<EventType, OutputCallback>>
+Controller<EventType, OutputCallback, StatechartType> {
+  fn new(statechart: StatechartType, output: OutputCallback) -> Self {
     Self {
+      statechart,
+      output,
       queue: BinaryHeap::new(),
       simtime: 0,
-      output,
     }
   }
-  fn add_input(&mut self, entry: Entry<'a, EventType, OutputCallback>) {
+  fn add_input(&mut self, entry: Entry<EventType>) {
     self.queue.push(entry);
   }
   fn run_until(&mut self, until: Until) {
@@ -97,16 +83,9 @@ impl<'a, EventType: Copy, OutputCallback: FnMut(&'static str, &'static str)> Con
 
           let e = entry.event; // copy
 
-          match &mut entry.target {
-            Target::Narrowcast(sc) => {
-              sc.fair_step(Some(e), &mut self.output);
-            },
-            Target::Broadcast => {
-              println!("broadcast not implemented!")
-            },
-          };
+          self.statechart.fair_step(Some(e), &mut self.output);
 
-          PeekMut::<'_, Entry<'a, EventType, OutputCallback>>::pop(entry);
+          PeekMut::<'_, Entry<EventType>>::pop(entry);
         },
         None => { break 'running; },
       }

+ 2 - 2
src/sccd/statechart/codegen/rust.py

@@ -145,7 +145,7 @@ def compile_statechart(sc: Statechart, globals: Globals, w: IndentingWriter):
         if isinstance(state, HistoryState):
             return None # we got no time for pseudo-states!
 
-        w.writeln("impl<OutputCallback: FnMut(&'static str, &'static str)> State<OutputCallback> for %s {" % ident_type(state))
+        w.writeln("impl<'a, OutputCallback: FnMut(&'a str, &'a str)> State<OutputCallback> for %s {" % ident_type(state))
 
         w.writeln("  fn enter_actions(output: &mut OutputCallback) {")
         w.writeln("    println!(\"enter %s\");" % state.opt.full_name);
@@ -223,7 +223,7 @@ def compile_statechart(sc: Statechart, globals: Globals, w: IndentingWriter):
     w.writeln("}")
     w.writeln()
 
-    w.writeln("impl<OutputCallback: FnMut(&'static str, &'static str)> SC<Event, OutputCallback> for Statechart {")
+    w.writeln("impl<'a, OutputCallback: FnMut(&'a str, &'a str)> SC<Event, OutputCallback> for Statechart {")
     w.writeln("  fn init(&self, output: &mut OutputCallback) {")
     w.writeln("    %s::enter_default(output);" % ident_type(tree.root))
     w.writeln("  }")

+ 3 - 3
src/sccd/test/codegen/rust.py

@@ -29,17 +29,17 @@ def compile_test(variants: List[TestVariant], w: IndentingWriter):
         w.writeln("};")
         w.writeln("let mut sc: Statechart = Default::default();")
         w.writeln("sc.init(&mut output);")
-        w.writeln("let mut controller = Controller::<Event, _>::new(output);")
+        w.writeln("let mut controller = Controller::new(sc, output);")
         for i in v.input:
             if len(i.events) > 1:
                 raise Exception("Multiple simultaneous input events not supported")
             elif len(i.events) == 0:
                 raise Exception("Test declares empty bag of input events - not supported")
 
-            w.writeln("controller.add_input(Entry::<Event, _>{")
+            w.writeln("controller.add_input(Entry{")
             w.writeln("  timestamp: %d," % i.timestamp.opt)
             w.writeln("  event: Event::%s," % i.events[0].name)
-            w.writeln("  target: Target::Narrowcast(&mut sc),")
+            # w.writeln("  target: Target::Narrowcast(&mut sc),")
             w.writeln("});")
 
         w.writeln("controller.run_until(Until::Eternity);")