113 lines
4 KiB
TypeScript
113 lines
4 KiB
TypeScript
import { ConcreteState, PseudoState, stateDescription, Transition } from "../statecharts/abstract_syntax";
|
|
import { Action, EventTrigger, Expression } from "../statecharts/label_ast";
|
|
import { RT_Statechart } from "../statecharts/runtime_types";
|
|
|
|
import "./AST.css";
|
|
|
|
export function ShowTransition(props: {transition: Transition}) {
|
|
return <>➝ {stateDescription(props.transition.tgt)}</>;
|
|
}
|
|
|
|
export function ShowExpr(props: {expr: Expression}) {
|
|
if (props.expr.kind === "literal") {
|
|
return <>{props.expr.value}</>;
|
|
}
|
|
else if (props.expr.kind === "ref") {
|
|
return <>{props.expr.variable}</>;
|
|
}
|
|
else if (props.expr.kind === "unaryExpr") {
|
|
return <>{props.expr.operator}<ShowExpr expr={props.expr.expr}/></>;
|
|
}
|
|
else if (props.expr.kind === "binaryExpr") {
|
|
return <><ShowExpr expr={props.expr.lhs}/>{props.expr.operator}<ShowExpr expr={props.expr.rhs}/></>;
|
|
}
|
|
}
|
|
|
|
export function ShowAction(props: {action: Action}) {
|
|
if (props.action.kind === "raise") {
|
|
return <>^<span className="outputEvent">{props.action.event}</span></>;
|
|
}
|
|
else if (props.action.kind === "assignment") {
|
|
return <>{props.action.lhs} = <ShowExpr expr={props.action.rhs}/>;</>;
|
|
}
|
|
}
|
|
|
|
export function ShowAST(props: {root: ConcreteState | PseudoState, transitions: Map<string, Transition[]>, rt: RT_Statechart | undefined, highlightActive: Set<string>}) {
|
|
const description = stateDescription(props.root);
|
|
// const outgoing = props.transitions.get(props.root.uid) || [];
|
|
|
|
return <li>{props.root.kind}: {description}
|
|
{props.root.kind !== "pseudo" && props.root.children.length>0 &&
|
|
<ul>
|
|
{props.root.children.map(child =>
|
|
<ShowAST key={child.uid} root={child} transitions={props.transitions} rt={props.rt} highlightActive={props.highlightActive} />
|
|
)}
|
|
</ul>
|
|
}
|
|
</li>;
|
|
|
|
return <details open={true} className={"stateTree" + (props.highlightActive.has(props.root.uid) ? " active" : "")}>
|
|
<summary>{props.root.kind}: {description}</summary>
|
|
|
|
{/* {props.root.kind !== "pseudo" && props.root.entryActions.length>0 &&
|
|
props.root.entryActions.map(action =>
|
|
<div> entry / <ShowAction action={action}/></div>
|
|
)
|
|
}
|
|
{props.root.kind !== "pseudo" && props.root.exitActions.length>0 &&
|
|
props.root.exitActions.map(action =>
|
|
<div> exit / <ShowAction action={action}/></div>
|
|
)
|
|
} */}
|
|
|
|
{props.root.kind !== "pseudo" && props.root.children.length>0 &&
|
|
props.root.children.map(child =>
|
|
<ShowAST key={child.uid} root={child} transitions={props.transitions} rt={props.rt} highlightActive={props.highlightActive} />
|
|
)
|
|
}
|
|
{/* {outgoing.length>0 &&
|
|
outgoing.map(transition => <> <ShowTransition transition={transition}/><br/></>)
|
|
} */}
|
|
</details>;
|
|
}
|
|
|
|
import BoltIcon from '@mui/icons-material/Bolt';
|
|
|
|
export function ShowInputEvents({inputEvents, onRaise, disabled}: {inputEvents: EventTrigger[], onRaise: (e: string, p: any) => void, disabled: boolean}) {
|
|
return inputEvents.map(({event, paramName}) =>
|
|
<div key={event+'/'+paramName} className="toolbarGroup">
|
|
<button
|
|
className="inputEvent"
|
|
title={`raise this input event`}
|
|
disabled={disabled}
|
|
onClick={() => {
|
|
// @ts-ignore
|
|
const param = document.getElementById(`input-${event}-param`)?.value;
|
|
let paramParsed;
|
|
try {
|
|
if (param) {
|
|
paramParsed = JSON.parse(param); // may throw
|
|
}
|
|
}
|
|
catch (e) {
|
|
alert("invalid json");
|
|
return;
|
|
}
|
|
onRaise(event, paramParsed);
|
|
}}>
|
|
<BoltIcon fontSize="small"/>
|
|
{event}
|
|
</button>
|
|
{paramName &&
|
|
<><input id={`input-${event}-param`} style={{width: 20}} placeholder={paramName}/></>
|
|
}
|
|
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export function ShowOutputEvents(props: {outputEvents: Set<string>}) {
|
|
return [...props.outputEvents].map(eventName => {
|
|
return <><div className="outputEvent">{eventName}</div> </>;
|
|
});
|
|
}
|