Skip to content

Commit

Permalink
Merge pull request #442 from StoneCypher/SetHooksWithExplicitAction
Browse files Browse the repository at this point in the history
set_hook(...) basics
  • Loading branch information
StoneCypher committed May 4, 2022
2 parents 5e0a801 + 3041204 commit b5389e3
Show file tree
Hide file tree
Showing 38 changed files with 4,305 additions and 113 deletions.
16 changes: 8 additions & 8 deletions benchmark/results/general.chart.html
Expand Up @@ -28,7 +28,7 @@
</head>
<body>
<div class="container">
<canvas id="chart1650401117756" width="16" height="9"></canvas>
<canvas id="chart1651624732492" width="16" height="9"></canvas>
</div>
<script>
const format = (num) => {
Expand All @@ -51,18 +51,18 @@
chunked.map((chunk) => chunk.join('')).join(' ') + fractionStr
)
}
const ctx1650401117756 = document
.getElementById('chart1650401117756')
const ctx1651624732492 = document
.getElementById('chart1651624732492')
.getContext('2d')
const chart1650401117756 = new Chart(ctx1650401117756, {
const chart1651624732492 = new Chart(ctx1651624732492, {
type: 'bar',
data: {
labels: ["Blind cycle a traffic light 500 times by transition","Blind cycle a traffic light 500 times by action"],
labels: ["Blind cycle a traffic light 500 times by transition","Blind cycle a hooked traffic light 500 times by transition","Blind cycle a traffic light 500 times by action","Blind cycle a hooked traffic light 500 times by action"],
datasets: [
{
data: [9970,8899],
backgroundColor: ["hsl(120, 85%, 55%)","hsl(107.11200000000001, 85%, 55%)"],
borderColor: ["hsl(120, 85%, 55%)","hsl(107.11200000000001, 85%, 55%)"],
data: [20799,1784,15032,1486],
backgroundColor: ["hsl(120, 85%, 55%)","hsl(10.296, 85%, 55%)","hsl(86.724, 85%, 55%)","hsl(8.568000000000001, 85%, 55%)"],
borderColor: ["hsl(120, 85%, 55%)","hsl(10.296, 85%, 55%)","hsl(86.724, 85%, 55%)","hsl(8.568000000000001, 85%, 55%)"],
borderWidth: 2,
},
],
Expand Down
28 changes: 20 additions & 8 deletions benchmark/results/general.json
@@ -1,27 +1,39 @@
{
"name": "General performance suite",
"date": "2022-04-19T20:45:17.756Z",
"date": "2022-05-04T00:38:52.492Z",
"version": "1.0.0",
"results": [
{
"name": "Blind cycle a traffic light 500 times by transition",
"ops": 9970,
"margin": 5.46,
"ops": 20799,
"margin": 4.1,
"percentSlower": 0
},
{
"name": "Blind cycle a hooked traffic light 500 times by transition",
"ops": 1784,
"margin": 0.65,
"percentSlower": 91.42
},
{
"name": "Blind cycle a traffic light 500 times by action",
"ops": 8899,
"margin": 2.41,
"percentSlower": 10.74
"ops": 15032,
"margin": 0.94,
"percentSlower": 27.73
},
{
"name": "Blind cycle a hooked traffic light 500 times by action",
"ops": 1486,
"margin": 3.43,
"percentSlower": 92.86
}
],
"fastest": {
"name": "Blind cycle a traffic light 500 times by transition",
"index": 0
},
"slowest": {
"name": "Blind cycle a traffic light 500 times by action",
"index": 1
"name": "Blind cycle a hooked traffic light 500 times by action",
"index": 3
}
}
6 changes: 5 additions & 1 deletion dist/es6/jssm.d.ts
@@ -1,6 +1,6 @@
declare type StateType = string;
import { JssmGenericState, JssmGenericConfig, JssmTransition, JssmTransitionList, // JssmTransitionRule,
JssmMachineInternalState, JssmParseTree, JssmStateDeclaration, JssmArrow, JssmArrowDirection, JssmArrowKind, JssmLayout, FslDirection, FslTheme } from './jssm_types';
JssmMachineInternalState, JssmParseTree, JssmStateDeclaration, JssmArrow, JssmArrowDirection, JssmArrowKind, JssmLayout, FslDirection, FslTheme, HookDescription } from './jssm_types';
import { seq, weighted_rand_select, weighted_sample_select, histograph, weighted_histo_key } from './jssm_util';
import { version } from './version';
declare function arrow_direction(arrow: JssmArrow): JssmArrowDirection;
Expand Down Expand Up @@ -37,6 +37,9 @@ declare class Machine<mDT> {
_arrange_end_declaration: Array<Array<StateType>>;
_theme: FslTheme;
_flow: FslDirection;
_has_hooks: boolean;
_hooks: Map<string, Function>;
_named_hooks: Map<string, Function>;
constructor({ start_states, complete, transitions, machine_author, machine_comment, machine_contributor, machine_definition, machine_language, machine_license, machine_name, machine_version, state_declaration, fsl_version, dot_preamble, arrange_declaration, arrange_start_declaration, arrange_end_declaration, theme, flow, graph_layout }: JssmGenericConfig<mDT>);
_new_state(state_config: JssmGenericState): StateType;
state(): StateType;
Expand Down Expand Up @@ -86,6 +89,7 @@ declare class Machine<mDT> {
is_complete(): boolean;
state_is_complete(whichState: StateType): boolean;
has_completes(): boolean;
set_hook(HookDesc: HookDescription): void;
action(name: StateType, newData?: mDT): boolean;
transition(newState: StateType, newData?: mDT): boolean;
force_transition(newState: StateType, newData?: mDT): boolean;
Expand Down
104 changes: 96 additions & 8 deletions dist/es6/jssm.js
@@ -1,6 +1,6 @@
// whargarbl lots of these return arrays could/should be sets
import { reduce as reduce_to_639 } from 'reduce-to-639-1';
import { seq, weighted_rand_select, weighted_sample_select, histograph, weighted_histo_key, array_box_if_string } from './jssm_util';
import { seq, weighted_rand_select, weighted_sample_select, histograph, weighted_histo_key, array_box_if_string, hook_name, named_hook_name } from './jssm_util';
import { parse } from './jssm-dot'; // TODO FIXME WHARGARBL this could be post-typed
import { version } from './version'; // replaced from package.js in build // TODO FIXME currently broken
/* eslint-disable complexity */
Expand Down Expand Up @@ -345,6 +345,9 @@ class Machine {
this._theme = theme;
this._flow = flow;
this._graph_layout = graph_layout;
this._has_hooks = false;
this._hooks = new Map();
this._named_hooks = new Map();
if (state_declaration) {
state_declaration.map((state_decl) => {
if (this._state_declarations.has(state_decl.state)) { // no repeats
Expand Down Expand Up @@ -694,14 +697,59 @@ class Machine {
has_completes() {
return this.states().some((x) => this.state_is_complete(x));
}
// basic toolable hook call. convenience wrappers will follow, like
// hook(from, to, handler) and exit_hook(from, handler) and etc
set_hook(HookDesc) {
switch (HookDesc.kind) {
case 'hook':
this._hooks.set(hook_name(HookDesc.from, HookDesc.to), HookDesc.handler);
this._has_hooks = true;
break;
case 'named':
this._named_hooks.set(named_hook_name(HookDesc.from, HookDesc.to, HookDesc.action), HookDesc.handler);
this._has_hooks = true;
break;
// case 'entry':
// console.log('TODO: Should add entry hook here');
// throw 'TODO: Should add entry hook here';
// case 'exit':
// console.log('TODO: Should add exit hook here');
// throw 'TODO: Should add exit hook here';
default:
console.log(`Unknown hook type ${HookDesc.kind}, should be impossible`);
throw new RangeError(`Unknown hook type ${HookDesc.kind}, should be impossible`);
}
}
// remove_hook(HookDesc: HookDescription) {
// throw 'TODO: Should remove hook here';
// }
action(name, newData) {
// todo whargarbl implement hooks
// todo whargarbl implement data stuff
// todo major incomplete whargarbl comeback
if (this.valid_action(name, newData)) {
const edge = this.current_action_edge_for(name);
this._state = edge.to;
return true;
if (this._has_hooks) {
let hook_permits = undefined;
const nhn = named_hook_name(this._state, edge.to, name), maybe_hook = this._named_hooks.get(nhn);
if (maybe_hook === undefined) {
hook_permits = true;
}
else {
hook_permits = maybe_hook({ from: this._state, to: edge.to, action: name });
}
if (hook_permits !== false) {
this._state = edge.to;
return true;
}
else {
return false;
}
}
else {
this._state = edge.to;
return true;
}
}
else {
return false;
Expand All @@ -712,8 +760,27 @@ class Machine {
// todo whargarbl implement data stuff
// todo major incomplete whargarbl comeback
if (this.valid_transition(newState, newData)) {
this._state = newState;
return true;
if (this._has_hooks) {
let hook_permits = undefined;
const hn = hook_name(this._state, newState), maybe_hook = this._hooks.get(hn);
if (maybe_hook === undefined) {
hook_permits = true;
}
else {
hook_permits = maybe_hook({ from: this._state, to: newState });
}
if (hook_permits !== false) {
this._state = newState;
return true;
}
else {
return false;
}
}
else {
this._state = newState;
return true;
}
}
else {
return false;
Expand All @@ -725,16 +792,37 @@ class Machine {
// todo whargarbl implement data stuff
// todo major incomplete whargarbl comeback
if (this.valid_force_transition(newState, newData)) {
this._state = newState;
return true;
if (this._has_hooks) {
let hook_permits = undefined;
const hn = hook_name(this._state, newState), maybe_hook = this._hooks.get(hn);
if (maybe_hook === undefined) {
hook_permits = true;
}
else {
hook_permits = maybe_hook({ from: this._state, to: newState, forced: true });
}
if (hook_permits !== false) {
this._state = newState;
return true;
}
else {
return false;
}
}
else {
this._state = newState;
return true;
}
}
else {
return false;
}
}
current_action_for(action) {
const action_base = this._actions.get(action);
return action_base ? action_base.get(this.state()) : undefined;
return action_base
? action_base.get(this.state())
: undefined;
}
current_action_edge_for(action) {
const idx = this.current_action_for(action);
Expand Down
26 changes: 25 additions & 1 deletion dist/es6/jssm_types.d.ts
Expand Up @@ -148,4 +148,28 @@ declare type JssmCompileSeStart<DataType> = {
};
declare type JssmParseTree = Array<JssmCompileSeStart<StateType>>;
declare type JssmParseFunctionType = (string: any) => JssmParseTree;
export { JssmColor, JssmTransition, JssmTransitions, JssmTransitionList, JssmTransitionRule, JssmArrow, JssmArrowKind, JssmArrowDirection, JssmGenericConfig, JssmGenericState, JssmGenericMachine, JssmParseTree, JssmCompileSe, JssmCompileSeStart, JssmCompileRule, JssmPermitted, JssmPermittedOpt, JssmResult, JssmStateDeclaration, JssmStateDeclarationRule, JssmLayout, JssmParseFunctionType, JssmMachineInternalState, FslDirection, FslTheme };
declare type BasicHookDescription = {
kind: 'hook';
from: string;
to: string;
handler: Function;
};
declare type HookDescriptionWithAction = {
kind: 'named';
from: string;
to: string;
action: string;
handler: Function;
};
declare type EntryHook = {
kind: 'entry';
to: string;
handler: Function;
};
declare type ExitHook = {
kind: 'exit';
from: string;
handler: Function;
};
declare type HookDescription = BasicHookDescription | HookDescriptionWithAction | EntryHook | ExitHook;
export { JssmColor, JssmTransition, JssmTransitions, JssmTransitionList, JssmTransitionRule, JssmArrow, JssmArrowKind, JssmArrowDirection, JssmGenericConfig, JssmGenericState, JssmGenericMachine, JssmParseTree, JssmCompileSe, JssmCompileSeStart, JssmCompileRule, JssmPermitted, JssmPermittedOpt, JssmResult, JssmStateDeclaration, JssmStateDeclarationRule, JssmLayout, JssmParseFunctionType, JssmMachineInternalState, FslDirection, FslTheme, HookDescription };
4 changes: 3 additions & 1 deletion dist/es6/jssm_util.d.ts
Expand Up @@ -5,4 +5,6 @@ declare const seq: Function;
declare const histograph: Function;
declare const weighted_sample_select: Function;
declare const weighted_histo_key: Function;
export { seq, arr_uniq_p, histograph, weighted_histo_key, weighted_rand_select, weighted_sample_select, array_box_if_string };
declare const hook_name: (from: string, to: string) => string;
declare const named_hook_name: (from: string, to: string, action: string) => string;
export { seq, arr_uniq_p, histograph, weighted_histo_key, weighted_rand_select, weighted_sample_select, array_box_if_string, hook_name, named_hook_name };
4 changes: 3 additions & 1 deletion dist/es6/jssm_util.js
Expand Up @@ -31,4 +31,6 @@ const weighted_histo_key = (n, opts, prob_prop, extract) => // TODO FIXME no any
histograph(weighted_sample_select(n, opts, prob_prop)
.map((s) => s[extract] // TODO FIXME eslint-disable-line flowtype/no-weak-types
));
export { seq, arr_uniq_p, histograph, weighted_histo_key, weighted_rand_select, weighted_sample_select, array_box_if_string };
const hook_name = (from, to) => JSON.stringify([from, to]);
const named_hook_name = (from, to, action) => JSON.stringify([from, to, action]);
export { seq, arr_uniq_p, histograph, weighted_histo_key, weighted_rand_select, weighted_sample_select, array_box_if_string, hook_name, named_hook_name };
2 changes: 1 addition & 1 deletion dist/es6/version.js
@@ -1,2 +1,2 @@
const version = "5.44.0";
const version = "5.45.0";
export { version };
2 changes: 1 addition & 1 deletion dist/jssm.es5.cjs.js

Large diffs are not rendered by default.

0 comments on commit b5389e3

Please sign in to comment.