Просмотр исходного кода

Progress with Rust: entering default states

Joeri Exelmans 5 лет назад
Родитель
Сommit
b46ba7df54
2 измененных файлов с 61 добавлено и 17 удалено
  1. 6 0
      src/sccd/statechart/cmd/gen_rust.py
  2. 55 17
      src/sccd/statechart/codegen/rust.py

+ 6 - 0
src/sccd/statechart/cmd/gen_rust.py

@@ -5,6 +5,12 @@ from sccd.statechart.parser.xml import *
 
 from sccd.statechart.codegen.rust import compile_to_rust
 
+# Note: Rust code is written to stdout and should be compiled to a library
+
+# Test syntax correctness as follows:
+
+#    python -m sccd.statechart.cmd.gen_rust <path/to/statechart.xml> | tee >(cat 1>&2) | rustc --crate-type=lib -
+
 
 if __name__ == "__main__":
     parser = argparse.ArgumentParser(

+ 55 - 17
src/sccd/statechart/codegen/rust.py

@@ -3,10 +3,7 @@ from sccd.statechart.static.tree import *
 from sccd.util.visit_tree import *
 
 def ident(state: State) -> str:
-    # if bestate.opt.full_name == "/":
-        # return ""
-    # else:
-        return state.opt.full_name.replace('/', '_');
+    return state.opt.full_name.replace('/', '_');
 
 def ident_type(state: State) -> str:
     if state.opt.full_name == "/":
@@ -14,6 +11,9 @@ def ident_type(state: State) -> str:
     else:
         return "State" + ident(state)
 
+def ident_enum_variant(state: State) -> str:
+    return "S" + ident(state)
+
 def ident_field(state: State) -> str:
     return "s" + ident(state)
 
@@ -22,7 +22,7 @@ def compile_to_rust(tree: StateTree):
     # 1. Write types
 
     # 1.1 Write 'current state' types
-    def write_state_type(state: State, children: str):
+    def write_state_type(state: State, children: List[State]):
         def as_struct():
             print("#[allow(non_camel_case_types)]")
             print("struct %s {" % ident_type(state))
@@ -32,9 +32,14 @@ def compile_to_rust(tree: StateTree):
 
         def as_enum():
             print("#[allow(non_camel_case_types)]")
-            print("enum %s {" % ident_type(state))
+            print("enum E%s {" % ident_type(state))
             for child in children:
-                print("  %s(%s)," % (ident_field(child), ident_type(child)))
+                print("  %s(%s)," % (ident_enum_variant(child), ident_type(child)))
+            print("}")
+            print("// Wrap enum in struct")
+            print("#[allow(non_camel_case_types)]")
+            print("struct %s {" % ident_type(state))
+            print("  e: E%s" % ident_type(state))
             print("}")
 
         if isinstance(state, ParallelState):
@@ -77,19 +82,52 @@ def compile_to_rust(tree: StateTree):
 
     # 2. Write "enter default state" functions
 
-    print("pub trait State {")
-    print("  fn enter_default();")
-    print("}")
-    print()
+    # print("pub trait State {")
+    # print("  fn enter_default(&mut self);")
+    # print("}")
+    # print()
+
+    def write_enter_default(state: State, children: List[State]):
+        def begin_default():
+            print("impl Default for %s {" % ident_type(state))
+            print("  fn default() -> %s {" % ident_type(state))
+            print("    %s {" % ident_type(state))
+
+        def end_default():
+            print("    }")
+            print("  }")
+            print("}")
+            print()            
 
-    def write_enter_default(state: State, children: str):
-        print("impl State for %s {" % ident_type(state))
-        print("  fn enter_default() {")
         if isinstance(state, ParallelState):
+            begin_default()
+            for child in children:
+                print("      %s: %s{..Default::default()}," % (ident_field(child), ident_type(child)))
+            end_default()
+        elif isinstance(state, HistoryState):
             pass
-        print("  }")
-        print("}")
-        print()
+        elif isinstance(state, State):
+            begin_default()
+            if state.default_state is not None:
+                print("      e: E%s::%s(%s{..Default::default()})," % (ident_type(state), ident_enum_variant(state.default_state), ident_type(state.default_state)))
+            end_default()
+
+
+        # print("impl State for %s {" % ident_type(state))
+        # print("  fn enter_default(&mut self) {")
+        # if isinstance(state, ParallelState):
+        #     for child in children:
+        #         print("    self.%s.enter_default();" % ident_field(child))
+        # elif isinstance(state, HistoryState):
+        #     pass
+        # elif isinstance(state, State):
+        #     if state.default_state is not None:
+        #         print("    self.e = E%s::%s();" % (ident_type(state), ident_enum_variant(state.default_state)))
+        #         # print("    self.%s.enter_default();" % ident_enum_variant(state.default_state))
+        # print("  }")
+        # print("}")
+        # print()
+        return state
 
     visit_tree(tree.root, lambda s: s.children,
         child_first=[write_enter_default])