C++ State Machine generator for Xstate
This package allows to convert TypeScript language State Machine developed using Xstate into C++ generated SM, no coding required.
- Project location: https://github.com/shuvalov-mdb/xstate-cpp-generator
- NPM TypeScript package location: https://www.npmjs.com/package/xstate-cpp-generator
- Copyright Andrew Shuvalov, MIT License
Features
- Design and test the State Machine in Xstate and then convert to C++ without any changes
- Use the online vizualizer to debug the State Machine
- SM basic features supported: States, Events, Transitions
- SM extra features supported: Actions
- Generated C++ is fully synchronized, safe to use in multi-threaded environemnt without any changes
- No external dependencies except STL. No boost dependency.
- Callback model:
- Entry, Exit and Trasition Actions are code generated as static methods in the template object used to declare the State Machine and can be implemented by the user
- Every state and transtion callbacks are generated as virtual methods that can be overloaded by subclassing
- Arbitrary user-defined data structure (called Context) can be stored in the SM
- Any event can have an arbitrary user-defined payload attached. The event payload is propagated to related callbacks
Resources
- Quick start is right below
- Tutorial
Install and Quick Start Tutorial
-g
option):
1. Install the xstate-cpp-generator TypeScript package, locally (or globally with npm install xstate-cpp-generator
engineer.ts
with few lines to trigger C++ generation at the end:
2. Create a simple Xstate model file (this example is located at https://github.com/shuvalov-mdb/xstate-cpp-generator/tree/master/demo-project)
const CppGen = require('xstate-cpp-generator');const path = require('path'); import { Machine } from 'xstate'; const engineerMachine = Machine({ id: 'engineer', initial: 'sleeping', states: { sleeping: { entry: 'startWakeupTimer', exit: 'morningRoutine', on: { 'TIMER': { target: 'working', actions: ['startHungryTimer', 'startTiredTimer'] }, } }, working: { entry: ['checkEmail', 'startHungryTimer', 'checkIfItsWeekend' ], on: { 'HUNGRY': { target: 'eating', actions: ['checkEmail']}, 'TIRED': { target: 'sleeping' }, 'ENOUGH': { target: 'weekend' } }, }, eating: { entry: 'startShortTimer', exit: [ 'checkEmail', 'startHungryTimer' ], on: { 'TIMER': { target: 'working', actions: ['startHungryTimer'] }, 'TIRED': { target: 'sleeping' } } }, weekend: { type: 'final', } }}); CppGen.generateCpp({ xstateMachine: engineerMachine, destinationPath: "", namespace: "engineer_demo", pathForIncludes: "", tsScriptName: path.basename(__filename) });
To visualize this State Machine copy-paste the 'Machine' method call to the online vizualizer.
3. Generate C++
Install all required dependencies:
npm install
And run the C++ generator:
ts-node engineer.ts
You should see new generated files:
engineer_sm.h engineer_sm.cpp engineer_test.cpp
The engineer_test.cpp
is an automatically generated Unit Test for the model. Create a simple SConscript
file to compile it:
env = Environment()
LIBS =''
common_libs = ['gtest_main', 'gtest', 'pthread']
env.Append( LIBS = common_libs )
env.Append(CCFLAGS=['-fsanitize=address,undefined',
'-fno-omit-frame-pointer'],
LINKFLAGS='-fsanitize=address,undefined')
env.Program('engineer_test', ['engineer_sm.cpp', 'engineer_test.cpp'],
LIBS, LIBPATH='/opt/gtest/lib:/usr/local/lib', CXXFLAGS="-std=c++17")
and run it with:
scons
./engineer_test
Release Notes
V 1.0.3
- Full support of entry, exit and transition Actions
- Multi-threading bugfixes
V 1.0.4
- Converted
onEnteredState()
from move sematics&&
to shared_ptr - Started Tutorial