plant has its own timed/reactive behavior - typically another statechart

This commit is contained in:
Joeri Exelmans 2025-10-28 14:47:42 +01:00
parent b50f52496a
commit 3e5dca437b
19 changed files with 401 additions and 241 deletions

View file

@ -1,12 +1,51 @@
import { ReactElement } from "react";
import { Statechart } from "@/statecharts/abstract_syntax";
import { EventTrigger } from "@/statecharts/label_ast";
import { RaisedEvent } from "@/statecharts/runtime_types";
import { ReactElement } from "react";
import { Conns, TimedReactive } from "@/statecharts/timed_reactive";
export type PlantRenderProps<StateType> = {
state: StateType,
speed: number,
raiseInput: (e: RaisedEvent) => void,
raiseOutput: (e: RaisedEvent) => void,
};
export type Plant<StateType> = {
inputEvents: EventTrigger[];
outputEvents: EventTrigger[];
initial: StateType;
reduce: (inputEvent: RaisedEvent, state: StateType) => StateType;
render: (state: StateType, raise: (event: RaisedEvent) => void, timescale: number) => ReactElement;
execution: TimedReactive<StateType>;
render: (props: PlantRenderProps<StateType>) => ReactElement;
}
// Automatically connect Statechart and Plant inputs/outputs if their event names match.
export function autoConnect(ast: Statechart, scName: string, plant: Plant<any>, plantName: string) {
const outputs = {
[scName]: {},
[plantName]: {},
}
for (const o of ast.outputEvents) {
const plantInputEvent = plant.inputEvents.find(e => e.event === o)
if (plantInputEvent) {
// @ts-ignore
outputs[scName][o] = {kind: "model", model: plantName, eventName: plantInputEvent.event};
}
}
for (const o of plant.outputEvents) {
const scInputEvent = ast.inputEvents.find(e => e.event === o.event);
if (scInputEvent) {
// @ts-ignore
outputs[plantName][o.event] = {kind: "model", model: scName, eventName: scInputEvent.event};
}
}
return outputs;
}
export function exposePlantInputs(plant: Plant<any>, plantName: string, tfm = (s: string) => s) {
const inputs = {};
for (const i of plant.inputEvents) {
// @ts-ignore
inputs[tfm(i.event)] = {kind: "model", model: plantName, eventName: i.event};
}
return inputs
}