Skip to content

stateforward/hsm

Repository files navigation

HSM - Hierarchical State Machine Multi-Language Implementation

This is a monorepo containing hierarchical state machine (HSM) implementations across multiple programming languages. Each language implementation is maintained as a separate Git submodule, allowing for independent development while maintaining a unified project structure.

Repository Structure

This repository uses Git submodules to organize language-specific implementations:

Language Implementations

C++ (cpp/)

  • Status: Complete implementation
  • Build System: CMake with comprehensive test suite
  • Features: Full SCXML-compliant hierarchical state machines, event handling, timers, guards, and actions
  • Repository: stateforward/hsm-cpp

Go (go/)

  • Status: Complete implementation with OpenTelemetry observability
  • Features: Hierarchical state machines with comprehensive event system, context propagation, and tracing
  • Repository: stateforward/hsm-go

JavaScript/TypeScript (javascript/)

  • Status: Complete implementation
  • Package Manager: npm with comprehensive test suite
  • Features: ES6+ implementation with async/await support, TypeScript definitions, and Node.js ecosystem integration
  • Repository: stateforward/hsm-javascript

Python (python/)

  • Status: Complete implementation
  • Package Manager: uv with async support
  • Features: asyncio-based implementation with comprehensive test coverage and modern Python practices
  • Repository: stateforward/hsm-python

Rust (rust/)

  • Status: Complete implementation
  • Build System: Cargo with comprehensive benchmarks
  • Features: Memory-safe, zero-cost abstractions with strong type safety and performance optimizations
  • Repository: stateforward/hsm-rust

🚧 Zig (zig/)

  • Status: Work in Progress (WIP)
  • Build System: Custom Zig build system
  • Features: Planned low-level, high-performance implementation leveraging Zig's systems programming capabilities
  • Repository: stateforward/hsm-zig

Getting Started

Cloning the Repository

# Clone the main repository with all submodules
git clone --recursive https://github.com/stateforward/hsm.git
cd hsm

# If you already cloned without --recursive, initialize submodules
git submodule update --init --recursive

Working with Individual Languages

Each language implementation is self-contained and can be used independently:

# C++ implementation
cd cpp && mkdir build && cd build && cmake .. && make

# Go implementation
cd go && go build

# JavaScript implementation
cd javascript && npm install

# Python implementation
cd python && uv sync

# Rust implementation
cd rust && cargo build

# Zig implementation (WIP)
cd zig && zig build

Architecture

All implementations follow the same core concepts:

  • Hierarchical States: Support for nested state machines
  • Events & Transitions: Event-driven state changes with guards and effects
  • Entry/Exit Actions: Behaviors executed when entering/exiting states
  • Timers: Time-based transitions and delayed events
  • SCXML Compliance: Based on W3C SCXML specification where applicable

Code Examples

Simple State Machine (Multiple Languages)

Go

var Model = hsm.Define(
	"TestHSM",
	hsm.State("foo", hsm.Entry(noBehavior),
		hsm.Exit(noBehavior)),
	hsm.State("bar", hsm.Entry(noBehavior),
		hsm.Exit(noBehavior)),
	hsm.Transition(
		hsm.On("foo"),
		hsm.Source("foo"),
		hsm.Target("bar"),
		hsm.Effect(noBehavior),
	),
	hsm.Transition(
		hsm.On("bar"),
		hsm.Source("bar"),
		hsm.Target("foo"),
		hsm.Effect(noBehavior),
	),
	hsm.Initial(hsm.Target("foo"), hsm.Effect(noBehavior)),
)

JavaScript/TypeScript

const model = hsm.define(
    "TestHSM",
    hsm.state("foo",
        hsm.entry(noBehavior),
        hsm.exit(noBehavior)),
    hsm.state("bar",
        hsm.entry(noBehavior),
        hsm.exit(noBehavior)),
    hsm.transition(fooEvent,
        hsm.source("foo"),
        hsm.target("bar"),
        hsm.effect(noBehavior)),
    hsm.transition(barEvent,
        hsm.source("bar"),
        hsm.target("foo"),
        hsm.effect(noBehavior)),
    hsm.initial(
        hsm.target("foo"),
        hsm.effect(noBehavior)
    ))

Python

model = hsm.define(
    "TestHSM",
    hsm.state("foo",
        hsm.entry(noBehavior),
        hsm.exit(noBehavior)
    ),
    hsm.state("bar",
        hsm.entry(noBehavior),
        hsm.exit(noBehavior)
    ),
    hsm.transition(
        hsm.on(foo_event),
        hsm.source("foo"),
        hsm.target("bar"),
        hsm.effect(noBehavior),
    ),
    hsm.transition(
        hsm.on(bar_event),
        hsm.source("bar"),
        hsm.target("foo"),
        hsm.effect(noBehavior),
    ),
    hsm.initial(hsm.target("foo"), hsm.effect(noBehavior)),
)

C++

#include "cthsm.hpp"

// Define the model with compile-time HSM
auto model = cthsm::define(
    "TestHSM",
    cthsm::initial(cthsm::target("foo")),
    cthsm::state(
        "foo",
        cthsm::transition(cthsm::on("bar"), cthsm::target("bar"))
    ),
    cthsm::state(
        "bar",
        cthsm::transition(cthsm::on("foo"), cthsm::target("foo"))
    )
);

// Compile and use it
cthsm::compile<decltype(model)> sm;

std::cout << "Initial state: " << sm.state() << "\n";
sm.dispatch("bar");
std::cout << "After bar event: " << sm.state() << "\n";

Rust

use rust_hsm::*;

let model = define(
    "TestHSM",
    vec![
        state("foo",
            vec![
                entry(|ctx, instance| println!("Entering foo")),
                exit(|ctx, instance| println!("Exiting foo")),
            ]
        ),
        state("bar",
            vec![
                entry(|ctx, instance| println!("Entering bar")),
                exit(|ctx, instance| println!("Exiting bar")),
            ]
        ),
        transition(
            vec![on("bar")],
            source("foo"),
            target("bar"),
            vec![effect(|ctx, instance| println!("Transitioning foo -> bar"))],
        ),
        transition(
            vec![on("foo")],
            source("bar"),
            target("foo"),
            vec![effect(|ctx, instance| println!("Transitioning bar -> foo"))],
        ),
        initial(target("foo")),
    ]
);

Zig

const hsm = @import("hsm");

// Define the state machine model at compile time
const model = comptime hsm.define("TestHSM", .{
    hsm.initial(hsm.target("foo")),
    hsm.state("foo", .{
        hsm.entry(fooEntry),
        hsm.exit(fooExit),
        hsm.transition(.{ hsm.on("bar"), hsm.target("bar"), hsm.effect(fooToBarEffect) })
    }),
    hsm.state("bar", .{
        hsm.entry(barEntry),
        hsm.exit(barExit),
        hsm.transition(.{ hsm.on("foo"), hsm.target("foo"), hsm.effect(barToFooEffect) })
    })
});

// Build and run the state machine
var built_model = try model.build(allocator);
defer built_model.deinit();

var context = hsm.Context.init(allocator);
var instance = hsm.Instance.init();
defer instance.deinit();

var sm = try hsm.start(&context, &instance, &built_model);
defer sm.deinit();

std.log.info("Initial state: {s}", .{sm.state()});
try sm.dispatch(&context, hsm.Event.init(allocator, "bar"));
std.log.info("After bar event: {s}", .{sm.state()});

Contributing

Each language implementation has its own repository and contribution guidelines. Please refer to the individual README files in each submodule for language-specific contribution information.

License

This project is licensed under the MIT License - see the LICENSE file in each submodule for details.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published