Skip to content

UML-like State Machine (including composites, concurrent regions, etc) for Lua

License

Notifications You must be signed in to change notification settings

brice-morin/LuaSM

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LuaSM

UML-like State Machine (including composites, concurrent regions, etc) for Lua

Hello World

require "luasm"
------Test------
-- Create a State A
local A = luasm.AtomicState:new{name = "A"}
function A:executeOnEntry() --on entry/exit actions are defined like this
  print("hello")
end
function A:executeOnExit()
	print("bye")
end

-- Create a State B
local B = luasm.AtomicState:new{name = "B"} -- on entry/exit are optional

-- Create a Transition between A and B
local T = luasm.Transition:new{name = "T", source = A, target = B, eventType = luasm.NullEvent}:init()
function T:execute(event) --actions on transitions are defined like this
		print("executing transition") 
end

local R = luasm.Region:new{name = "R", initial = A, states = {A, B}}
local CS = luasm.CompositeState:new{name = "CS", regions = {R}} --root state machine

local Comp = luasm.Component:new{name = "Cpt", behavior = CS}:init():start()

Define some properties in the component

Let's say you want your component to define a property count:

local Comp = luasm.Component:new{name = "Cpt", behavior = CS, count = 0}:init():start()

You can then access this property from a state:

function A:executeOnEntry()
  local component = self.component
  print("hello " .. component.count)
  component.count = component.count + 1
end

Or from a transition:

function T:execute(event)
    local component = self.source.component
		print("executing transition " .. component.count) 
end

Communication among components

State machines are wrapped into lightweight components. Component can communicate through message passing.

First, define a message (or event) type:

local E1 = luasm.Event:new{name = "t"} --Message type (basically just a name)

To create/instantiate a message:

local e1 = E1:create({p1 = "zzz", p2 = true, p3 = 42}) -- parameters can be passed in table (with arbitrary names)

To programmatically send a message to a component (e.g. in your "main", for testing purpose):

Comp:receive("p", e1)

For a component to send a message to another one, we should first add a connector/callback:

---Comp2 will be notified whenever Comp emits/sends a message on port p
Comp.connectors = {
	p = { 
		Comp2 = function(event) if not Comp2.terminated then Comp2:receive("p", event) else Comp.connectors.p.Comp2 = nil end end
	}
}
---note: it is a good idea to check that Comp2 is not "terminated" before sending something to it

Now in the implementation of Comp (in a state or transition):

...
component:send("p", e1) --sends message e1 (of type E1, see above) on port p
...

Now in the implementation of Comp2, we can define a transition that will react to that event

local T = luasm.Transition:new{name = "T", source = B, target = A, eventType = E1, port = "p"}:init()
function T:execute(event) 
	print "received!" 
end

About

UML-like State Machine (including composites, concurrent regions, etc) for Lua

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages