#有限状态机 #fsm #状态机 # #已检查 #静态地

fsm-macro

用Rust编写的静态检查有限状态机

1个不稳定版本

0.1.0 2023年4月17日

#712 in 过程宏

自定义许可证

12KB
191

Rust-FSM

用Rust编写的静态检查有限状态机。

动机

因为可以。并且我想练习在Rust中创建过程宏。这可以很有趣...

用法

要创建状态机,请使用 fsm 宏。

fsm!{

  initial = init_state
  state_1
  state_2
  ...
  end = end_state_1, end_state_2,...

  state_n -> state_m: transition_k
  ...
}

// --snip--

// Initialize the finite state machine
let mut fsm = FSM::new();

// run transition and save new struct
fsm = fsm.transition_k();
let f = |from: &str, to: &str, event: &str| {
    println!("from: {from}, to: {to}, event: {event}");
    // other actions to be performed
}

// You can pass a callback function to be called with the transition
fsm = fsm.transition_l_fn(f);

// Call the end function. Confirm that the FSM reached a final state.
fsm.end();

// or pass a closure
f_end = |state: %str| {
      println!("done!");
      // maybe do something else as well...
}

fsm.end_fn(f_end);

它是如何工作的

宏为所有状态创建类型和一个FSM结构体。FSM结构体是用户应该使用的。状态类型允许它定义和限制可以调用哪些转换/函数。

生成的示例代码

type struct state_1;
...

type struct FSM<T> {
  ...
  pub history: Vec<Transition>,
}

type struct Transition{
  pub from: String,
  pub to: String,
  pub event: string,
}

impl FSM {

  pub fn new() -> FSM<initial_state> {
    return FSM{
      // initialization here
    }
  }

}

impl FSM<state_1> {
  pub fn transition_k(self) -> FSM<state_2> {
    return FSM {
      // initialization here as well
    }
  }

  pub fn transition_k_fn(self, f: Fn(&str, &str, &str)) -> FSM<state_2> {
    f("state_1", "state_2", "transition_k");
    return self.transition_k();
  }
}

...

impl FSM<end_state> {

  ...
  // note that it destroys the object.
  // Do what you want with it before calling this function
  pub fn end() {}

  pub fn end_fn(f: Fn(&str)) {
    f("end_state");
  }
}

问题

  1. 净化
  • 生成的代码放置在宏调用相同的模块中。理想情况下,它应该创建一个新的模块并将新的结构体放在那里。
  1. 宏和LSP
  • 宏的LSP支持不是很好。不一定提供智能提示,可能不会警告关于坏代码。

要添加的功能

  • 提供将FSM打印为图形格式的函数
    • 目前可能将继续使用dot
  • 检查不可达状态
    • 应该给出某种警告...
  • 允许同一行有多个转换标签
    • 例如:A -> B: a,b,c,...

依赖项

~1.3–9.5MB
~85K SLoC