Browse Source

Rust: Make generated in/out event types public

Joeri Exelmans 4 years ago
parent
commit
04d9e9557e

+ 11 - 1
examples/digitalwatch/run.html

@@ -1,5 +1,6 @@
 <html>
 <head>
+  <meta charset="utf-8">
   <title>DWatch</title>
   <style type="text/css">
     body {
@@ -52,7 +53,16 @@
   <p id="log">
   </p>
 
-  <script type="text/javascript">
+  <script type="module">
+    (async () => {
+      const rust = await import("./wasm/pkg/dwatch.js");
+
+      const m = await rust.default();
+
+      m.get_statechart();
+    })();
+
+
     function log(msg) {
       // document.getElementById("log").innerText += msg + '\n';
     }

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

@@ -355,12 +355,12 @@ class StatechartRustGenerator(ActionLangRustGenerator):
         self.w.writeln("// Input Events")
         for event_name in input_event_names:
             self.w.writeln("#[derive(Copy, Clone, Debug)]")
-            self.w.writeln("struct %s {" % ident_event_type(event_name))
+            self.w.writeln("pub struct %s {" % ident_event_type(event_name))
             self.w.writeln("  // TODO: input event parameters")
             self.w.writeln("}")
 
         self.w.writeln("#[derive(Copy, Clone, Debug)]")
-        self.w.writeln("enum InEvent {")
+        self.w.writeln("pub enum InEvent {")
         for event_name in input_event_names:
             self.w.writeln("  %s(%s)," % (ident_event_enum_variant(event_name), ident_event_type(event_name)))
         self.w.writeln("}")
@@ -380,8 +380,8 @@ class StatechartRustGenerator(ActionLangRustGenerator):
         self.w.writeln("}")
 
         if self.internal_queue:
-            # Internal events are treated like input events
-            self.w.writeln("type InternalLifeline = ();")
+            # Treat internal events like input events
+            self.w.writeln("type InternalLifeline = ();") # Unit type
         else:
             if internal_same_round:
                 self.w.writeln("type InternalLifeline = statechart::SameRoundLifeline<Internal>;")
@@ -394,12 +394,12 @@ class StatechartRustGenerator(ActionLangRustGenerator):
         self.w.writeln("// Output Events")
         for event_name in output_event_names:
             self.w.writeln("#[derive(Copy, Clone, Debug, PartialEq, Eq)]")
-            self.w.writeln("struct %s {" % ident_event_type(event_name))
+            self.w.writeln("pub struct %s {" % ident_event_type(event_name))
             self.w.writeln("  // TODO: output event parameters")
             self.w.writeln("}")
 
         self.w.writeln("#[derive(Copy, Clone, Debug, PartialEq, Eq)]")
-        self.w.writeln("enum OutEvent {")
+        self.w.writeln("pub enum OutEvent {")
         for event_name in output_event_names:
             self.w.writeln("  %s(%s)," % (ident_event_enum_variant(event_name), ident_event_type(event_name)))
         self.w.writeln("}")

+ 0 - 1
src/sccd/statechart/parser/xml.py

@@ -162,7 +162,6 @@ def statechart_parser_rules(globals, path, load_external = True, parse_f = parse
                 statechart.internally_raised_events |= bit(event_id)
                 return RaiseInternalEvent(event_id=event_id, name=event_name, params=params)
               else:
-                # output event - no ID in global namespace
                 statechart.event_outport[event_name] = port
                 globals.outports.assign_id(port)
                 globals.out_events.assign_id(event_name)

+ 5 - 5
src/sccd/test/codegen/write_crate.py

@@ -9,7 +9,7 @@ RUST_DIR = os.path.dirname(sccd.__file__) + "/../../rust"
 # Quick and dirty high-level function, taking a statechart / class diagram / test model in XML format and generating from it a Rust crate, which is written to the filesystem as a directory.
 def write_crate(src, target):
     path = os.path.dirname(src)
-
+    basename = os.path.splitext(os.path.basename(src))[0]
 
     globals = Globals()
 
@@ -26,7 +26,7 @@ def write_crate(src, target):
     if not os.path.isdir(target):
         os.mkdir(target)
 
-    with open(target+"/statechartgen.rs", 'w') as file:
+    with open(target+"/%s.rs" % basename, 'w') as file:
         w = IndentingWriter(out=file)
 
         w.writeln("#![allow(non_camel_case_types)]")
@@ -58,7 +58,7 @@ def write_crate(src, target):
         w = IndentingWriter(out=file)
 
         w.writeln("[package]")
-        w.writeln("name = \"statechartgen\"")
+        w.writeln("name = \"%s\"" % basename)
         w.writeln("version = \"0.1.0\"")
         w.writeln("edition = \"2018\"")
         w.writeln()
@@ -71,8 +71,8 @@ def write_crate(src, target):
         else:
             # Everything else becomes a library
             w.writeln("[lib]")
-        w.writeln("name = \"statechartgen\"")
-        w.writeln("path = \"statechartgen.rs\"")
+        w.writeln("name = \"%s\"" % basename)
+        w.writeln("path = \"%s.rs\"" % basename)
         w.writeln()
 
     with open(target+"/.gitignore", 'w') as file:

+ 1 - 0
test_files/features/instate/test_instate_nested.xml

@@ -1,4 +1,5 @@
 <test>
+  <!-- Interestingly, compiling this test with Rust -O3 produces an equally sized binary as test_instate.xml. This means that the anonymous function in the guard of our first transition is being inlined by the compiler. We can conclude that Rust brings zero-cost abstractions to our action language :) -->
   <statechart>
     <root>
       <parallel id="p">