From abf984bd5d97f749671a3710e02f94f7801a8669 Mon Sep 17 00:00:00 2001 From: Brian Sakal Date: Mon, 8 May 2023 21:07:03 -0400 Subject: [PATCH 1/3] TypeScript, send() --- src/index.ts | 55 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/src/index.ts b/src/index.ts index 97e079e..d764f93 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,12 +1,13 @@ -export interface Machine_T { +type EventShape = [name:string, payload:any]; +export interface Machine_T { states: Array> } -export interface State_T { +export interface State_T { name: S; ons: Array>; } -export interface On_T { - eventName: E; +export interface On_T { + eventName: E[0]; reactions: Array>; }; export interface Do_T { @@ -19,10 +20,50 @@ export interface Goto_T { targetStateName: S; }; -export const Machine = function(...states:Array>) : Machine_T { return {states}; }; -export const State = function(name:S, ...ons:Array>) : State_T{ return {name, ons}; }; -export const On = function(eventName:E, ...reactions:Array>) : On_T{ return {eventName, reactions}; }; +export const Machine = function(...states:Array>) : Machine_T { return {states}; }; +export const State = function(name:S, ...ons:Array>) : State_T{ return {name, ons}; }; +export const On = function(eventName:E[0], ...reactions:Array>) : On_T{ return {eventName, reactions}; }; export const Do = function(fn:DoFn_T) : Do_T{ return {type:'Do', fn}; }; export const Goto = function(targetStateName:S) : Goto_T { return {type:'Goto', targetStateName} }; + + +export interface Interpreter_T { + machine: Machine_T; + state: S; + context: C | {}; +} +export function interpret(machine:Machine_T, options?:{state?:S, context?:C | {}}) : Interpreter_T{ + 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(interpreter : Interpreter_T) : State_T{ + return interpreter.machine.states.find((state)=>state.name===interpreter.state) as unknown as State_T; +} +/** Helper function for `send()` + */ +function getOns(state : State_T, event:E) : Array>{ + 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(interpreter : Interpreter_T, event:E){ + const state = getState(interpreter); + const ons = getOns(state, event); + ons.forEach +} + export const Spawn = function(){}; export const Unspawn = function(){}; \ No newline at end of file From 8806ce48d7c7ae0a39226b7afb623be5c4bcc1a1 Mon Sep 17 00:00:00 2001 From: Brian Sakal Date: Mon, 8 May 2023 21:09:20 -0400 Subject: [PATCH 2/3] TypeScript in example --- src/tests/00-basic.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/00-basic.ts b/src/tests/00-basic.ts index f22f633..bf445e4 100644 --- a/src/tests/00-basic.ts +++ b/src/tests/00-basic.ts @@ -3,10 +3,10 @@ import { Machine, State, On, Do, Goto, Spawn, Unspawn } from '../index'; const beginTimer = ()=>{}; type S = 'green' | 'yellow' | 'red'; -type E = 'entry' | 'timer-finished'; +type E = ['entry',null] | ['timer-finished',null]; const machine = - Machine( + Machine( State('green', On('entry', Do(beginTimer) From e37161d3a00fd183f6be643606b7aa1c69ce7240 Mon Sep 17 00:00:00 2001 From: Brian Sakal Date: Mon, 8 May 2023 21:28:19 -0400 Subject: [PATCH 3/3] begin building Tick --- src/index.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index d764f93..d22695b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,6 +26,11 @@ export const On = function(eventName:E[0], ...reactions: export const Do = function(fn:DoFn_T) : Do_T{ return {type:'Do', fn}; }; export const Goto = function(targetStateName:S) : Goto_T { return {type:'Goto', targetStateName} }; +interface Tick_T { + doFunctions: Array +}; +const Tick = function(doFunctions : Array) : Tick_T{ return {doFunctions}; }; + export interface Interpreter_T { machine: Machine_T; @@ -62,7 +67,21 @@ function getOns(state : State_T, event:E) : Array(interpreter : Interpreter_T, event:E){ const state = getState(interpreter); const ons = getOns(state, event); - ons.forEach + const tick = Tick(ons + .map((on)=>on.reactions) + .flat() + .map((reaction)=>{ + if(reaction.type === 'Do'){ + return reaction.fn; + } + else if(reaction.type === 'Goto'){ + return (ctx,e,self)=>{}; + } + else{ + return (ctx,e,self)=>{}; + } + }) + ); } export const Spawn = function(){};