ActorSimulationCodegen

Turn an actor_simulation model into a runnable project in another language: C++ (CAF or OMNeT++), Go (Phony), Pony, Rust (Ractor) or Java (VLINGO XOOM). Each generated project comes with build files, a CI workflow, a test suite and, for every target but OMNeT++, callback interfaces, so behaviour can be customised without editing generated code.

Prototype in Elixir where a simulated hour takes a millisecond, then take the same model to production.

Hex.pm Documentation

The family

Package What it is for Add it when
gen_server_virtual_time virtual clock, GenServer/gen_statem wrappers you test code with timers
gen_server_virtual_time_migrate mix virtual_time.migrate rewrites GenServer code you already have servers and want to keep them
actor_simulation actor-system DSL, statistics, sequence diagrams you model parts of a system talking to each other
actor_simulation_codegen (this one) generate runnable projects in six runtimes you want the same model in another language

This package depends on actor_simulation, which brings gen_server_virtual_time with it.

Install

def deps do
  [{:actor_simulation_codegen, "~> 1.1.0"}]
end

Targets

Generator Language Framework Output
CAF C++ C++ Actor Framework Typed actors, CMake build, Conan deps, tests
Phony Go Phony Zero-alloc actors, Go modules, tests
Pony Pony Pony Language Type-safe actors, Corral deps, PonyTest
Ractor Rust Ractor Gen_server-inspired, Cargo, async/await
VLINGO Java VLINGO XOOM Protocol actors, Maven, JUnit 5
OMNeT++ C++ OMNeT++ Discrete-event simulation, NED files, CMake

Each is generated from the same simulation:

simulation = ActorSimulation.new()
|> ActorSimulation.add_actor(:publisher,
    send_pattern: {:periodic, 100, :event},
    targets: [:sub1, :sub2, :sub3])
|> ActorSimulation.add_actor(:sub1)
|> ActorSimulation.add_actor(:sub2)
|> ActorSimulation.add_actor(:sub3)

# C++ with the C++ Actor Framework
{:ok, files} = ActorSimulation.Codegen.CAF.generate(simulation,
  project_name: "PubSubActors",
  enable_callbacks: true)
ActorSimulation.Codegen.CAF.write_to_directory(files, "caf_output/")

# Go with Phony
{:ok, files} = ActorSimulation.Codegen.Phony.generate(simulation,
  project_name: "pubsub",
  enable_callbacks: true)
ActorSimulation.Codegen.Phony.write_to_directory(files, "phony_output/")

# Rust with Ractor
{:ok, files} = ActorSimulation.Codegen.Ractor.generate(simulation,
  project_name: "pubsub",
  enable_callbacks: true)
ActorSimulation.Codegen.Ractor.write_to_directory(files, "ractor_output/")

Then build the output with its own toolchain — each generated project ships a README.md with the exact commands:

Target Build
CAF cmake + conan
OMNeT++ cmake (NED files and a runnable config)
Pony make (Corral for dependencies)
Phony go test ./...
Ractor cargo test
VLINGO mvn compile exec:exec (forked JVM)

Callback interfaces let you change behaviour without touching generated files:

// CAF: publisher_callbacks_impl.cpp
void publisher_callbacks::on_event() {
  log_to_database();
  send_metrics();
}
// Ractor: publisher.rs
impl PublisherCallbacks for MyPublisherCallbacks {
    fn on_event(&self) {
        println!("Publishing event with custom handler");
    }
}

Guides

License

MIT License - See the LICENSE file for details.