Skip to content

Commit b5389e3

Browse files
authored
Merge pull request #442 from StoneCypher/SetHooksWithExplicitAction
set_hook(...) basics
2 parents 5e0a801 + 3041204 commit b5389e3

38 files changed

+4305
-113
lines changed

benchmark/results/general.chart.html

+8-8
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
</head>
2929
<body>
3030
<div class="container">
31-
<canvas id="chart1650401117756" width="16" height="9"></canvas>
31+
<canvas id="chart1651624732492" width="16" height="9"></canvas>
3232
</div>
3333
<script>
3434
const format = (num) => {
@@ -51,18 +51,18 @@
5151
chunked.map((chunk) => chunk.join('')).join(' ') + fractionStr
5252
)
5353
}
54-
const ctx1650401117756 = document
55-
.getElementById('chart1650401117756')
54+
const ctx1651624732492 = document
55+
.getElementById('chart1651624732492')
5656
.getContext('2d')
57-
const chart1650401117756 = new Chart(ctx1650401117756, {
57+
const chart1651624732492 = new Chart(ctx1651624732492, {
5858
type: 'bar',
5959
data: {
60-
labels: ["Blind cycle a traffic light 500 times by transition","Blind cycle a traffic light 500 times by action"],
60+
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"],
6161
datasets: [
6262
{
63-
data: [9970,8899],
64-
backgroundColor: ["hsl(120, 85%, 55%)","hsl(107.11200000000001, 85%, 55%)"],
65-
borderColor: ["hsl(120, 85%, 55%)","hsl(107.11200000000001, 85%, 55%)"],
63+
data: [20799,1784,15032,1486],
64+
backgroundColor: ["hsl(120, 85%, 55%)","hsl(10.296, 85%, 55%)","hsl(86.724, 85%, 55%)","hsl(8.568000000000001, 85%, 55%)"],
65+
borderColor: ["hsl(120, 85%, 55%)","hsl(10.296, 85%, 55%)","hsl(86.724, 85%, 55%)","hsl(8.568000000000001, 85%, 55%)"],
6666
borderWidth: 2,
6767
},
6868
],

benchmark/results/general.json

+20-8
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,39 @@
11
{
22
"name": "General performance suite",
3-
"date": "2022-04-19T20:45:17.756Z",
3+
"date": "2022-05-04T00:38:52.492Z",
44
"version": "1.0.0",
55
"results": [
66
{
77
"name": "Blind cycle a traffic light 500 times by transition",
8-
"ops": 9970,
9-
"margin": 5.46,
8+
"ops": 20799,
9+
"margin": 4.1,
1010
"percentSlower": 0
1111
},
12+
{
13+
"name": "Blind cycle a hooked traffic light 500 times by transition",
14+
"ops": 1784,
15+
"margin": 0.65,
16+
"percentSlower": 91.42
17+
},
1218
{
1319
"name": "Blind cycle a traffic light 500 times by action",
14-
"ops": 8899,
15-
"margin": 2.41,
16-
"percentSlower": 10.74
20+
"ops": 15032,
21+
"margin": 0.94,
22+
"percentSlower": 27.73
23+
},
24+
{
25+
"name": "Blind cycle a hooked traffic light 500 times by action",
26+
"ops": 1486,
27+
"margin": 3.43,
28+
"percentSlower": 92.86
1729
}
1830
],
1931
"fastest": {
2032
"name": "Blind cycle a traffic light 500 times by transition",
2133
"index": 0
2234
},
2335
"slowest": {
24-
"name": "Blind cycle a traffic light 500 times by action",
25-
"index": 1
36+
"name": "Blind cycle a hooked traffic light 500 times by action",
37+
"index": 3
2638
}
2739
}

dist/es6/jssm.d.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
declare type StateType = string;
22
import { JssmGenericState, JssmGenericConfig, JssmTransition, JssmTransitionList, // JssmTransitionRule,
3-
JssmMachineInternalState, JssmParseTree, JssmStateDeclaration, JssmArrow, JssmArrowDirection, JssmArrowKind, JssmLayout, FslDirection, FslTheme } from './jssm_types';
3+
JssmMachineInternalState, JssmParseTree, JssmStateDeclaration, JssmArrow, JssmArrowDirection, JssmArrowKind, JssmLayout, FslDirection, FslTheme, HookDescription } from './jssm_types';
44
import { seq, weighted_rand_select, weighted_sample_select, histograph, weighted_histo_key } from './jssm_util';
55
import { version } from './version';
66
declare function arrow_direction(arrow: JssmArrow): JssmArrowDirection;
@@ -37,6 +37,9 @@ declare class Machine<mDT> {
3737
_arrange_end_declaration: Array<Array<StateType>>;
3838
_theme: FslTheme;
3939
_flow: FslDirection;
40+
_has_hooks: boolean;
41+
_hooks: Map<string, Function>;
42+
_named_hooks: Map<string, Function>;
4043
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>);
4144
_new_state(state_config: JssmGenericState): StateType;
4245
state(): StateType;
@@ -86,6 +89,7 @@ declare class Machine<mDT> {
8689
is_complete(): boolean;
8790
state_is_complete(whichState: StateType): boolean;
8891
has_completes(): boolean;
92+
set_hook(HookDesc: HookDescription): void;
8993
action(name: StateType, newData?: mDT): boolean;
9094
transition(newState: StateType, newData?: mDT): boolean;
9195
force_transition(newState: StateType, newData?: mDT): boolean;

dist/es6/jssm.js

+96-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// whargarbl lots of these return arrays could/should be sets
22
import { reduce as reduce_to_639 } from 'reduce-to-639-1';
3-
import { seq, weighted_rand_select, weighted_sample_select, histograph, weighted_histo_key, array_box_if_string } from './jssm_util';
3+
import { seq, weighted_rand_select, weighted_sample_select, histograph, weighted_histo_key, array_box_if_string, hook_name, named_hook_name } from './jssm_util';
44
import { parse } from './jssm-dot'; // TODO FIXME WHARGARBL this could be post-typed
55
import { version } from './version'; // replaced from package.js in build // TODO FIXME currently broken
66
/* eslint-disable complexity */
@@ -345,6 +345,9 @@ class Machine {
345345
this._theme = theme;
346346
this._flow = flow;
347347
this._graph_layout = graph_layout;
348+
this._has_hooks = false;
349+
this._hooks = new Map();
350+
this._named_hooks = new Map();
348351
if (state_declaration) {
349352
state_declaration.map((state_decl) => {
350353
if (this._state_declarations.has(state_decl.state)) { // no repeats
@@ -694,14 +697,59 @@ class Machine {
694697
has_completes() {
695698
return this.states().some((x) => this.state_is_complete(x));
696699
}
700+
// basic toolable hook call. convenience wrappers will follow, like
701+
// hook(from, to, handler) and exit_hook(from, handler) and etc
702+
set_hook(HookDesc) {
703+
switch (HookDesc.kind) {
704+
case 'hook':
705+
this._hooks.set(hook_name(HookDesc.from, HookDesc.to), HookDesc.handler);
706+
this._has_hooks = true;
707+
break;
708+
case 'named':
709+
this._named_hooks.set(named_hook_name(HookDesc.from, HookDesc.to, HookDesc.action), HookDesc.handler);
710+
this._has_hooks = true;
711+
break;
712+
// case 'entry':
713+
// console.log('TODO: Should add entry hook here');
714+
// throw 'TODO: Should add entry hook here';
715+
// case 'exit':
716+
// console.log('TODO: Should add exit hook here');
717+
// throw 'TODO: Should add exit hook here';
718+
default:
719+
console.log(`Unknown hook type ${HookDesc.kind}, should be impossible`);
720+
throw new RangeError(`Unknown hook type ${HookDesc.kind}, should be impossible`);
721+
}
722+
}
723+
// remove_hook(HookDesc: HookDescription) {
724+
// throw 'TODO: Should remove hook here';
725+
// }
697726
action(name, newData) {
698727
// todo whargarbl implement hooks
699728
// todo whargarbl implement data stuff
700729
// todo major incomplete whargarbl comeback
701730
if (this.valid_action(name, newData)) {
702731
const edge = this.current_action_edge_for(name);
703-
this._state = edge.to;
704-
return true;
732+
if (this._has_hooks) {
733+
let hook_permits = undefined;
734+
const nhn = named_hook_name(this._state, edge.to, name), maybe_hook = this._named_hooks.get(nhn);
735+
if (maybe_hook === undefined) {
736+
hook_permits = true;
737+
}
738+
else {
739+
hook_permits = maybe_hook({ from: this._state, to: edge.to, action: name });
740+
}
741+
if (hook_permits !== false) {
742+
this._state = edge.to;
743+
return true;
744+
}
745+
else {
746+
return false;
747+
}
748+
}
749+
else {
750+
this._state = edge.to;
751+
return true;
752+
}
705753
}
706754
else {
707755
return false;
@@ -712,8 +760,27 @@ class Machine {
712760
// todo whargarbl implement data stuff
713761
// todo major incomplete whargarbl comeback
714762
if (this.valid_transition(newState, newData)) {
715-
this._state = newState;
716-
return true;
763+
if (this._has_hooks) {
764+
let hook_permits = undefined;
765+
const hn = hook_name(this._state, newState), maybe_hook = this._hooks.get(hn);
766+
if (maybe_hook === undefined) {
767+
hook_permits = true;
768+
}
769+
else {
770+
hook_permits = maybe_hook({ from: this._state, to: newState });
771+
}
772+
if (hook_permits !== false) {
773+
this._state = newState;
774+
return true;
775+
}
776+
else {
777+
return false;
778+
}
779+
}
780+
else {
781+
this._state = newState;
782+
return true;
783+
}
717784
}
718785
else {
719786
return false;
@@ -725,16 +792,37 @@ class Machine {
725792
// todo whargarbl implement data stuff
726793
// todo major incomplete whargarbl comeback
727794
if (this.valid_force_transition(newState, newData)) {
728-
this._state = newState;
729-
return true;
795+
if (this._has_hooks) {
796+
let hook_permits = undefined;
797+
const hn = hook_name(this._state, newState), maybe_hook = this._hooks.get(hn);
798+
if (maybe_hook === undefined) {
799+
hook_permits = true;
800+
}
801+
else {
802+
hook_permits = maybe_hook({ from: this._state, to: newState, forced: true });
803+
}
804+
if (hook_permits !== false) {
805+
this._state = newState;
806+
return true;
807+
}
808+
else {
809+
return false;
810+
}
811+
}
812+
else {
813+
this._state = newState;
814+
return true;
815+
}
730816
}
731817
else {
732818
return false;
733819
}
734820
}
735821
current_action_for(action) {
736822
const action_base = this._actions.get(action);
737-
return action_base ? action_base.get(this.state()) : undefined;
823+
return action_base
824+
? action_base.get(this.state())
825+
: undefined;
738826
}
739827
current_action_edge_for(action) {
740828
const idx = this.current_action_for(action);

dist/es6/jssm_types.d.ts

+25-1
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,28 @@ declare type JssmCompileSeStart<DataType> = {
148148
};
149149
declare type JssmParseTree = Array<JssmCompileSeStart<StateType>>;
150150
declare type JssmParseFunctionType = (string: any) => JssmParseTree;
151-
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 };
151+
declare type BasicHookDescription = {
152+
kind: 'hook';
153+
from: string;
154+
to: string;
155+
handler: Function;
156+
};
157+
declare type HookDescriptionWithAction = {
158+
kind: 'named';
159+
from: string;
160+
to: string;
161+
action: string;
162+
handler: Function;
163+
};
164+
declare type EntryHook = {
165+
kind: 'entry';
166+
to: string;
167+
handler: Function;
168+
};
169+
declare type ExitHook = {
170+
kind: 'exit';
171+
from: string;
172+
handler: Function;
173+
};
174+
declare type HookDescription = BasicHookDescription | HookDescriptionWithAction | EntryHook | ExitHook;
175+
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 };

dist/es6/jssm_util.d.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ declare const seq: Function;
55
declare const histograph: Function;
66
declare const weighted_sample_select: Function;
77
declare const weighted_histo_key: Function;
8-
export { seq, arr_uniq_p, histograph, weighted_histo_key, weighted_rand_select, weighted_sample_select, array_box_if_string };
8+
declare const hook_name: (from: string, to: string) => string;
9+
declare const named_hook_name: (from: string, to: string, action: string) => string;
10+
export { seq, arr_uniq_p, histograph, weighted_histo_key, weighted_rand_select, weighted_sample_select, array_box_if_string, hook_name, named_hook_name };

dist/es6/jssm_util.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,6 @@ const weighted_histo_key = (n, opts, prob_prop, extract) => // TODO FIXME no any
3131
histograph(weighted_sample_select(n, opts, prob_prop)
3232
.map((s) => s[extract] // TODO FIXME eslint-disable-line flowtype/no-weak-types
3333
));
34-
export { seq, arr_uniq_p, histograph, weighted_histo_key, weighted_rand_select, weighted_sample_select, array_box_if_string };
34+
const hook_name = (from, to) => JSON.stringify([from, to]);
35+
const named_hook_name = (from, to, action) => JSON.stringify([from, to, action]);
36+
export { seq, arr_uniq_p, histograph, weighted_histo_key, weighted_rand_select, weighted_sample_select, array_box_if_string, hook_name, named_hook_name };

dist/es6/version.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
const version = "5.44.0";
1+
const version = "5.45.0";
22
export { version };

dist/jssm.es5.cjs.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)