Существует ли язык программирования со встроенной конструкцией государственной машины?

Мне просто интересно, есть ли язык программирования, который имеет государственные машины (похожие на boost::statechart) в качестве основной конструкции языка.

аналогии-c# имеет делегаты, где java использует шаблон наблюдателя, а C имеет обратные вызовы. Perl и python имеют встроенные хэши, в то время как C++ и java нужна библиотека.

обновление:

Это должен быть общий язык программирования в смысле C++, C#, Java, Lisp ...

Я имею в виду "зрелые" государственные машины со всеми наворотами на уровне формализма Harel или UML-диаграмм состояния или boost:: statechart.

12 ответов


Рагель является государственным машинным языком. IOW, это не язык, который и поддерживает государственные машины, это язык, который только поддержка государственной машины. Что, очевидно, означает, что он не является полным Тьюринга, но кому это нужно?

точнее, Ragel-это компилятор машины состояния, который принимает описание машины состояния на языке, подобном регулярному выражению, и генерирует реализацию этой машины состояния на C, C++, Objective-C, D, Java или Ruby. (Подумай!--2--> но для государственных машин вместо парсеров таблицы LALR(1).) Основной целью Ragel является синтаксический анализ двоичных протоколов (таких как сетевые протоколы или форматы файлов на диске), но он также может быть использован для текста.

одним из известных примеров использования Ragel является веб-сервер Mongrel для Ruby: его http-ядро написано в Ragel, что делает его очень быстро и безопасно. Ядро HTTP настолько хорошо на самом деле, что оно было повторно использовано количество раз в разных приложениях: тонкий, Единорог и Радуга также являются веб-серверами и фактически прямыми конкурентами дворняги. Ebb-это обратный HTTP-прокси. RFuzz-это инструмент тестирования fuzz для веб-приложений. Кроме того, некоторые инструменты безопасности используют его.

Ragel также позволяет встраивать код на хост-языке в государственную машину, тем самым делая его полным и способным не только узнать, но и интерпретировать протоколов.

In общие каждый язык с поддержкой расширенного пользовательского потока управления через сорутинги (например, Lua) или продолжения (например, Scala) или GOTO (например, PHP) или правильные хвостовые вызовы (например, схема) могут быть использованы для легко реализовать государственной машины. (Генераторы (Python) aka итераторы (C#), которые в основном являются "дрянными сорутинами", могут работать или не работать, в зависимости от вашего определения "работы".) И любой язык, который имеет гибкий синтаксис (например, Ruby) или поддерживает метасинтактическая абстракция (например, Clojure) может использоваться для описания государственной машины. (Поддержка идентификаторов, отличных от ASCII, также помогает, так что вы можете использовать фактические стрелки для своего государственного компьютера.)

это означает, что если вы комбината два, и используйте язык, который поддерживает и хвост называет и метасинтактическая абстракция, вы получаете очень хорошие государственные машины,без требуется поддержка родного языка. Шрирам Кришнамурти дал теперь (в)знаменитый доклад под названием "Свинья перед Perl" на инаугурационной конференции легких языков, в котором он продемонстрировал реализацию FSM в схеме. (Вот горки, an запись звука и бумага, объясняющая код). Сам код представляет собой макрос 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 (что является схемой-говорят за true).


есть новый W3C XML-язык на основе состояния машины под названием SCXML, основанный на Дэвиде Хареле StateChart формализм (который поддерживает иерархические и параллельные состояния машины).

Apache Commons имеет реализация на основе Java SCXML:

Commons SCXML-это реализация, направленная на создание и поддержание движка Java SCXML, способного выполнять машину состояния, определенную с помощью документа SCXML, в то время как абстрагирование интерфейсов среды.


SMC - компилятор для простого доменного языка, который будет генерировать государственные машины для многих популярных языков. Я использовал его для создания обслуживаемых государственных машин для самых разных вещей, таких как сложные пользовательские интерфейсы и пользовательские сетевые протоколы.


OTP Erlang поддерживает конструкции государственной машины через "gen_fsm". Прошло несколько лет с тех пор, как я последний раз смотрел на него, поэтому я немного ржавый, но вы можете Google для "Erlang gen_fsm" и найти множество справочных материалов


не совсем, но есть модуль state machine для Python, который позволяет использовать декораторы для поддержки реализации Harel style statecharts, включая контексты с несколькими состояниями, вложенность подстанций с историей и без нее. Код выглядит примерно так, как показано ниже. Модуль находится на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()

язык программирования Plaid вводит " Typestate-Oriented Programming, парадигму, которая расширяет объектно-ориентированное программирование с помощью typestates."

вот док: http://www.cs.cmu.edu/~Олдрич/плед/

например:

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]
        { ... }
}

Я только что нашел один:AsmL (Абстрактный Государственный Машинный Язык).
Вот это страница с дополнительной информацией на сайте CodePlex.

достаточно интересно, он разработан Microsoft.


в C# итераторы (с "yield return" и "yield break") - это языковая конструкция, которая непосредственно переводится на государственные машины. Я никогда не использовал его как таковой, но я действительно думаю, что он может быть использован на практике.

там случается быть stackoverflow вопрос об этом здесь. Однако самый высокий голосовой ответ обескураживает его ...


помимо Ragel существует технически интересный, но довольно неясный язык под названием SL1. См.http://ieeexplore.ieee.org/xpl/freeabs_all.jsp?arnumber=1095580. Он был создан компанией Iskratel в Словении с целью разработки телекоммуникационных систем, где основными блоками являются государственные машины.


У Шрирама Кришнамурти есть доклад и статья о использование макросов для добавления встроенного подъязыка для автоматов для схемы. Я не уверен, что какие-либо схемы включают его макросы в качестве стандартной библиотеки.


Microsoft Research недавно выпустила P язык на GitHub. У них также есть PSharp framework, который предоставляет библиотеку расширений 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;
    }

  ...

Я почти на десять лет опоздал на вечеринку, но недавно наткнулся на неясный язык, который заимствует идеи из FSMs под названием Юм

Я не уверен, что он все еще активно поддерживается, но вы можете по крайней мере загрузить компилятор и поиграть с ним. Информацию трудно найти, но есть несколько статей и статей в интернете, которые показывают самое главное.