31

我只是好奇是否有一种以状态机(类似于 boost::statechart)作为主要语言结构的编程语言。

类比 - c# 有委托,其中 java 使用观察者模式,而 C 有回调。Perl 和 python 具有内置哈希,而 C++ 和 java 需要一个库。

更新:

这应该是 C++、C#、Java、Lisp 意义上的通用编程语言......

我的意思是“成熟的”状态机,在 Harel 形式主义或 UML 状态图或 boost::statechart 级别上具有所有的花里胡哨。

4

14 回答 14

51

Ragel是一种状态机语言。IOW,它不是一种支持状态机的语言,它是一种支持状态机的语言。这显然意味着它不是图灵完备的,但谁需要它呢?

更准确地说,Ragel 是一个状态机编译器,它以类似正则表达式的语言对状态机进行描述,并在 C、C++、Objective-C、D、Java 或 Ruby 中生成该状态机的实现。(想想yacc状态机而不是 LALR(1) 表解析器。)Ragel 的主要目的是解析二进制协议(例如网络协议或磁盘文件格式),但它也可以用于文本。

使用 Ragel 的一个著名例子是用于 Ruby 的 Mongrel 网络服务器:它的 HTTP 内核是用 Ragel 编写的,这使得它非常快速和安全。事实上,HTTP 内核非常好,以至于它在不同的应用程序中被多次重用:Thin、Unicorn 和 Rainbows 也是 Web 服务器,实际上是 Mongrel 的直接竞争对手。Ebb 是一个反向 HTTP 代理。RFuzz 是一个用于 Web 应用程序的模糊测试工具。此外,一些安全工具使用它。

Ragel 还允许将宿主语言中的代码嵌入到状态机中,从而使其成为图灵完备的,并且不仅能够识别而且能够解释协议。

通常,通过协程(例如 Lua)或延续(例如 Scala)或(例如 PHP)或适当的尾调用(例如 Scheme)支持高级用户定义控制流的每种GOTO语言都可以用来轻松实现状态机。(生成器(Python)又名迭代器(C#),基本上是“蹩脚的协程”可能会或可能不会工作,这取决于您对“工作”的定义。)以及任何具有灵活语法(例如 Ruby)或支持元语法抽象的语言(例如 Clojure)可以用来描述状态机。(对非 ASCII 标识符的支持也有帮助,因此您可以为状态机使用实际的箭头。)

这意味着,如果您两者结合起来,并使用一种同时支持尾调用和元语法抽象的语言获得非常好的状态机,无需本地语言支持。Shriram Krishnamurthi 在首届轻量级语言会议上发表了一个名为“The Swine before Perl”的著名演讲,其中他展示了在 Scheme 中的 FSM 实现。(这里有幻灯片录音解释代码的论文)。代码本身是一个 26 行(实际上非​​常短的行)宏,它允许您编写如下代码:

(define my-regex
  (automaton init
             [init : (c → more)]
             [more : (a → more)
                     (d → more)
                     (r → end)]
             [end : accept]))

这是正则表达式对应的状态机规范c(a|d)*r。它不仅是一个规范,而且是一个实现该状态机的可运行程序。

我可以这样称呼它:

(my-regex '(c a d a d d r))

在这种情况下,得到结果#t(这是 Scheme-speak for true)。

于 2009-11-25T07:23:23.993 回答
10

有一种新的 W3C 基于 XML 的状态机语言称为SCXML,它基于 David Harel 的StateChart形式(支持分层和并行状态机)。

Apache Commons 有一个基于 Java 的 SCXML 实现

Commons SCXML 是一种旨在创建和维护 Java SCXML 引擎的实现,该引擎能够执行使用 SCXML 文档定义的状态机,同时抽象出环境接口。

于 2009-11-24T23:47:28.710 回答
5

Plaid 编程语言介绍了“面向类型状态的编程,一种使用类型状态扩展面向对象编程的范式”。

这是文档:http ://www.cs.cmu.edu/~aldrich/plaid/

例如:

state File {
    public final String filename;
}

state OpenFile extends File {
    private CFilePtr filePtr;
    public int read() { ... }
    public void close() [OpenFile>>ClosedFile]
        { ... }
}

state ClosedFile extends File {
    public void open() [ClosedFile>>OpenFile]
        { ... }
}
于 2012-05-14T07:44:38.670 回答
4

SMC是一种简单的领域特定语言的编译器,它将为许多流行语言生成状态机。我已经使用它为各种各样的事物生成可维护的状态机,例如复杂的用户界面和自定义网络协议。

于 2011-03-11T23:54:36.877 回答
3

我刚刚找到了一个:AsmL(抽象状态机语言)
这是CodePlex 上包含更多信息的页面。

有趣的是,它是由微软开发的。

于 2009-11-24T22:59:57.817 回答
3

Erlang 的 OTP 通过 'gen_fsm' 支持状态机构造。我上次看它已经有几年了,所以我有点生疏,但你可以谷歌搜索“Erlang gen_fsm”并找到大量参考资料

于 2009-11-25T00:42:12.250 回答
2

不完全是,但是 Python 有一个状态机模块,它允许您使用装饰器来支持实现 Harel 样式的状态图,包括具有多个状态的上下文、具有和不具有历史记录的嵌套子状态。代码最终看起来像下面这样。模块位于http://wiki.python.org/moin/State%20Machine%20via%20Decorators

 #!/bin/env/python
"""
This example now works. The state pattern module
allows defining states which are their their own context for 
implementing substates.  Substate Medium (class Medium) shows this here.
"""
"""
Example with 5 buttons. Two ,'up','down' cause state to rotate among the
several states.  The other three, bx,by,bz, invoke state dependent behavior.

Switching into a state causes the labels of the three buttons bx,by,bz to
change.  Pressing one of the buttons causes associated text to appear in
corresponding static text box. An 'onEnter' method changes the text.
"""
import wx
import DecoratorStateMachine as dsm

class MyFrame(wx.Frame, dsm.ContextBase):

   xtable = dsm.TransitionTable('pstate')


   def __init__(self):
      MyFrame.xtable.initialize(self)

      wx.Frame.__init__(self, None, -1, "My Frame", size=(470,220))

      family = wx.SWISS
      style = wx.NORMAL
      weight = wx.BOLD
      font = wx.Font(11,family,style,weight, False, "Verdana")
      self.SetFont(font)

      panel = wx.Panel(self, -1)

      b = wx.Button(panel, -1, "Up", pos=(50,20), size=(80,35))
      self.Bind(wx.EVT_BUTTON, self.OnUp, b)
      b.SetDefault()

      b = wx.Button(panel, -1, "Down", pos=(50,60), size=(80,35))
      self.Bind(wx.EVT_BUTTON, self.OnDown, b)

      self.bx = wx.Button(panel, -1, "xxx", pos=(50,100), size=(110,35))
      self.Bind(wx.EVT_BUTTON, self.OnBA, self.bx)
      self.tx = wx.StaticText(panel, -1, "", pos=(50,140), size=(110,35))

      self.by = wx.Button(panel, -1, "yyy", pos=(180,100), size=(110,35))
      self.Bind(wx.EVT_BUTTON, self.OnBB, self.by)
      self.ty = wx.StaticText(panel, -1, "", pos=(180,140), size=(110,35))

      self.bz = wx.Button(panel, -1, "zzz", pos=(310,100), size=(110,35))
      self.Bind(wx.EVT_BUTTON, self.OnBC, self.bz )
      self.tz = wx.StaticText(panel, -1, "", pos=(310,140), size=(110,35))


   @dsm.transition(xtable)
   def OnUp(self, event):
      pass

   @dsm.transition(xtable)
   def OnDown(self, event):
      pass

   @dsm.event(xtable)
   def OnBA(self, event):
      pass

   @dsm.event(xtable)
   def OnBB(self, event):
      pass

   @dsm.event(xtable)
   def OnBC(self, event):
      self.tz.SetLabel("Bossy")


class Off(MyFrame):
   "This is state Off "

   def onEnter(self):
      self.bx.SetLabel("Chase")
      self.by.SetLabel("Onry")
      self.bz.SetLabel("Cow")

   def OnBA(self, event):
      self.tx.SetLabel("Chase the")

   def OnBB(self, event):
      self.ty.SetLabel("Onry")


class Low(MyFrame):
   "This is state Low "
   items = ["Walk", "Green", "Llama"]

    def onEnter(self):
      self.bx.SetLabel(self.items[0])
      self.by.SetLabel(self.items[1])
      self.bz.SetLabel(self.items[2])

   def OnBA(self, event):
      self.tx.SetLabel("Walk the ")

   def OnBB(self, event):
      self.ty.SetLabel(self.items[1])

   def OnBC(self, event):
      self.tz.SetLabel(self.items[2])


class Medium(MyFrame):
   "This is state Medium "
   ytable = dsm.TransitionTable('qstate')

   def onEnter(self):
      if not hasattr(self, 'qstate'):    #unconditionally initialize for no history
         self.ytable.initialize(self)
      self.doEnter()

   @dsm.event(ytable)
   def doEnter(): pass

   @dsm.transitionevent(ytable)
   def OnBA(self, event):
      pass

   @dsm.transitionevent(ytable)
   def OnBB(self, event):
      pass

   @dsm.transitionevent(ytable)
   def OnBC(self, event):
      pass


class High(Low):
   "This is state High "

   items = ["Pet","Tame", "Dog"]

   def OnBA(self, event):
      self.tx.SetLabel("Pet his")

class MedBlue(Medium):
   """State med blu"""

   items = ["Med BLue","Checkered", "Tractor"]

   def onEnter(self):
      self.bx.SetLabel(self.items[0])
      self.by.SetLabel(self.items[1])
      self.bz.SetLabel(self.items[2])

   def doEnter(self):
      self.onEnter()

   def OnBA(self, event):
      self.tx.SetLabel("Med Blue")
   def OnBB(self, event):
      self.ty.SetLabel("Chekered")
   def OnBC(self, event):
      self.tz.SetLabel("Tractor")


class MedRed(Medium):
   """State med red"""

   items = ["Med Red","Striped", "Combine"]

   def onEnter(self):
      self.bx.SetLabel(self.items[0])
      self.by.SetLabel(self.items[1])
      self.bz.SetLabel(self.items[2])

   def doEnter(self):
      self.onEnter()

   def OnBA(self, event):
      self.tx.SetLabel("Med Red")
   def OnBB(self, event):
      self.ty.SetLabel("Striped")
   def OnBC(self, event):
      self.tz.SetLabel("Combine")


MyFrame.xtable.nextStates(Low, (Medium,Off))
MyFrame.xtable.nextStates(Medium, (High,Low))
MyFrame.xtable.nextStates(High, (Off,Medium))
MyFrame.xtable.nextStates(Off, (Low,High))
MyFrame.xtable.initialstate = Off

Medium.ytable.nextStates(MedBlue, (MedBlue, MedRed, MedRed))
Medium.ytable.nextStates(MedRed,  (MedBlue, MedBlue, MedRed))
Medium.ytable.initialstate = MedBlue


if __name__=='__main__':
   app = wx.PySimpleApp()
   frame = MyFrame()
   frame.Show(True)
   app.MainLoop()
于 2010-11-15T18:50:20.013 回答
1

在 C# 中,迭代器(带有“yield return”和“yield break”)是一种直接转换为状态机的语言结构。我实际上从来没有这样使用过它,但我实际上认为它可以在实践中使用。

这里碰巧有一个关于它的stackoverflow问题。最高投票的答案虽然不鼓励它......

于 2009-11-24T23:58:34.797 回答
1

除了 Ragel,还有一种技术上很有趣,但相当晦涩的语言,叫做 SL1。请参阅http://ieeexplore.ieee.org/xpl/freeabs_all.jsp?arnumber=1095580。它是由斯洛文尼亚的 Iskratel 创建的,目的是开发以状态机为基本块的电信系统。

于 2011-03-13T12:06:56.227 回答
1

Shriram Krishnamurthi 有一篇关于使用宏将自动机的嵌入式子语言添加到 Scheme的演讲和论文。不过,我不确定是否有任何方案将他的宏作为标准库包含在内。

于 2012-01-26T03:45:33.210 回答
1

微软研究院最近在 GitHub 上发布了P语言。他们还拥有PSharp框架,该框架提供 C# 扩展库和高级语法以及该语言的编译器。

我期待着尝试一下。

以下是他们的 C# 扩展示例之一的一部分:

internal class Server : Machine
{
    MachineId Client;

    [Start]
    [OnEntry(nameof(InitOnEntry))]
    class Init : MachineState { }

    void InitOnEntry()
    {
        ...
        this.Goto(typeof(Active));
    }

    ...

以下是其高级语法的一部分:

using System;

namespace TheStateMachine
{
  internal machine Client
  {
    private machine Server;
    private start state Init
    {
      entry
      {
        this.Server = (trigger as Config).target;
        jump(Playing);
      }
    }

    private state Playing
    {
      entry
      {
        //execute logic
      }
      on AnotherEvent goto AnotherState;
      on SomeEvent do ProcessSomeLogic;
    }

  ...
于 2016-10-28T04:07:55.610 回答
1

我迟到了将近十年,但我最近偶然发现了一种晦涩难懂的语言,它借鉴了 FSM 的思想,叫做休谟

我不确定它是否仍在积极维护,但您至少可以下载编译器并使用它。信息很难获得,但网上有一些论文和文章显示了这些要点。

于 2018-09-17T16:59:09.253 回答
1

2015 年 9 月,xstate项目启动。它实现了 SCXML,旨在提供JavaScript and TypeScript finite state machines and statecharts for the modern web. 到文档的链接

于 2021-05-31T12:30:27.037 回答
0

这项工作已经进一步发展成为非常好的东西,请参阅https://microsoft.github.io/coyote

于 2020-03-24T16:57:37.957 回答