TypeScript, send()

main
Brian Sakal 2 years ago
parent dc5c854497
commit abf984bd5d

@ -1,12 +1,13 @@
export interface Machine_T<S,E> { type EventShape = [name:string, payload:any];
export interface Machine_T<S,E extends EventShape> {
states: Array<State_T<S,E>> states: Array<State_T<S,E>>
} }
export interface State_T<S,E> { export interface State_T<S,E extends EventShape> {
name: S; name: S;
ons: Array<On_T<S,E>>; ons: Array<On_T<S,E>>;
} }
export interface On_T<S,E> { export interface On_T<S,E extends EventShape> {
eventName: E; eventName: E[0];
reactions: Array<Do_T | Goto_T<S>>; reactions: Array<Do_T | Goto_T<S>>;
}; };
export interface Do_T { export interface Do_T {
@ -19,10 +20,50 @@ export interface Goto_T<S> {
targetStateName: S; targetStateName: S;
}; };
export const Machine = function<S,E>(...states:Array<State_T<S,E>>) : Machine_T<S,E> { return {states}; }; export const Machine = function<S,E extends EventShape>(...states:Array<State_T<S,E>>) : Machine_T<S,E> { return {states}; };
export const State = function<S,E>(name:S, ...ons:Array<On_T<S,E>>) : State_T<S,E>{ return {name, ons}; }; export const State = function<S,E extends EventShape>(name:S, ...ons:Array<On_T<S,E>>) : State_T<S,E>{ return {name, ons}; };
export const On = function<S,E>(eventName:E, ...reactions:Array<Do_T | Goto_T<S>>) : On_T<S,E>{ return {eventName, reactions}; }; export const On = function<S,E extends EventShape>(eventName:E[0], ...reactions:Array<Do_T | Goto_T<S>>) : On_T<S,E>{ return {eventName, reactions}; };
export const Do = function(fn:DoFn_T) : Do_T{ return {type:'Do', fn}; }; export const Do = function(fn:DoFn_T) : Do_T{ return {type:'Do', fn}; };
export const Goto = function<S>(targetStateName:S) : Goto_T<S> { return {type:'Goto', targetStateName} }; export const Goto = function<S>(targetStateName:S) : Goto_T<S> { return {type:'Goto', targetStateName} };
export interface Interpreter_T<S,E extends EventShape,C> {
machine: Machine_T<S,E>;
state: S;
context: C | {};
}
export function interpret<S,E extends EventShape,C>(machine:Machine_T<S,E>, options?:{state?:S, context?:C | {}}) : Interpreter_T<S,E,C>{
let {state, context} = options || {};
if(typeof state === 'undefined'){ state = machine.states[0].name; }
if(typeof context === 'undefined'){ context = {}; }
return {machine, state, context};
}
/** Helper function for `send()`
*/
function getState<S,E extends EventShape,C>(interpreter : Interpreter_T<S,E,C>) : State_T<S,E>{
return interpreter.machine.states.find((state)=>state.name===interpreter.state) as unknown as State_T<S,E>;
}
/** Helper function for `send()`
*/
function getOns<S,E extends EventShape>(state : State_T<S,E>, event:E) : Array<On_T<S,E>>{
return state.ons.filter((on)=>on.eventName===event[0]);
}
/** Inject an Event into the Interpreter's "tick queue".
*
* An event can be signify something "new" happening, such that its reactions should run on the next Tick;
* or it can signify a milestone "within" the current Tick, such that a Tick can be thought of as having
* "sub-Ticks".
*
* This distinction is significant for proper ordering of reaction execution, and also for determining
* whether to run a reaction at all. If an Event is received, and is specified to be applied on a past
* Tick, it is discarded.
*/
export function send<S,E extends EventShape,C>(interpreter : Interpreter_T<S,E,C>, event:E){
const state = getState(interpreter);
const ons = getOns(state, event);
ons.forEach
}
export const Spawn = function(){}; export const Spawn = function(){};
export const Unspawn = function(){}; export const Unspawn = function(){};
Loading…
Cancel
Save