jssm 5.78.0 → 5.79.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  declare type StateType = string;
2
2
  import { JssmGenericState, JssmGenericConfig, JssmTransition, JssmTransitionList, // JssmTransitionRule,
3
3
  JssmMachineInternalState, JssmParseTree, JssmStateDeclaration, JssmArrow, JssmArrowDirection, JssmArrowKind, JssmLayout, JssmHistory, JssmSerialization, FslDirection, FslTheme, HookDescription, HookHandler, HookContext, HookResult, HookComplexResult } from './jssm_types';
4
- import { seq, weighted_rand_select, weighted_sample_select, histograph, weighted_histo_key } from './jssm_util';
4
+ import { seq, unique, find_repeated, weighted_rand_select, weighted_sample_select, histograph, weighted_histo_key } from './jssm_util';
5
5
  import { shapes, gviz_shapes, named_colors } from './jssm_constants';
6
6
  import { version } from './version';
7
7
  /*********
@@ -250,9 +250,12 @@ declare class Machine<mDT> {
250
250
  _post_main_transition_hook: HookHandler<mDT> | undefined;
251
251
  _post_forced_transition_hook: HookHandler<mDT> | undefined;
252
252
  _post_any_transition_hook: HookHandler<mDT> | undefined;
253
+ _property_keys: Set<string>;
254
+ _default_properties: Map<string, any>;
255
+ _state_properties: Map<string, any>;
253
256
  _history: JssmHistory<mDT>;
254
257
  _history_length: number;
255
- 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, instance_name, history, data }: JssmGenericConfig<mDT>);
258
+ constructor({ start_states, complete, transitions, machine_author, machine_comment, machine_contributor, machine_definition, machine_language, machine_license, machine_name, machine_version, state_declaration, property_definition, state_property, fsl_version, dot_preamble, arrange_declaration, arrange_start_declaration, arrange_end_declaration, theme, flow, graph_layout, instance_name, history, data }: JssmGenericConfig<mDT>);
256
259
  /********
257
260
  *
258
261
  * Internal method for fabricating states. Not meant for external use.
@@ -294,6 +297,105 @@ declare class Machine<mDT> {
294
297
  *
295
298
  */
296
299
  data(): mDT;
300
+ /*********
301
+ *
302
+ * Get the current value of a given property name.
303
+ *
304
+ * ```typescript
305
+ *
306
+ * ```
307
+ *
308
+ * @param name The relevant property name to look up
309
+ *
310
+ * @returns The value behind the prop name. Because functional props are
311
+ * evaluated as getters, this can be anything.
312
+ *
313
+ */
314
+ prop(name: string): any;
315
+ /*********
316
+ *
317
+ * Get the current value of every prop, as an object. If no current definition
318
+ * exists for a prop - that is, if the prop was defined without a default and
319
+ * the current state also doesn't define the prop - then that prop will be listed
320
+ * in the returned object with a value of `undefined`.
321
+ *
322
+ * ```typescript
323
+ * const traffic_light = sm`
324
+ *
325
+ * property can_go default true;
326
+ * property hesitate default true;
327
+ * property stop_first default false;
328
+ *
329
+ * Off -> Red => Green => Yellow => Red;
330
+ * [Red Yellow Green] ~> [Off FlashingRed];
331
+ * FlashingRed -> Red;
332
+ *
333
+ * state Red: { property stop_first true; property can_go false; };
334
+ * state Off: { property stop_first true; };
335
+ * state FlashingRed: { property stop_first true; };
336
+ * state Green: { property hesitate false; };
337
+ *
338
+ * `;
339
+ *
340
+ * traffic_light.state(); // Off
341
+ * traffic_light.props(); // { can_go: true, hesitate: true, stop_first: true; }
342
+ *
343
+ * traffic_light.go('Red');
344
+ * traffic_light.props(); // { can_go: false, hesitate: true, stop_first: true; }
345
+ *
346
+ * traffic_light.go('Green');
347
+ * traffic_light.props(); // { can_go: true, hesitate: false, stop_first: false; }
348
+ * ```
349
+ *
350
+ */
351
+ props(): object;
352
+ /*********
353
+ *
354
+ * Get the current value of every prop, as an object. Compare
355
+ * {@link prop_map}, which returns a `Map`.
356
+ *
357
+ * ```typescript
358
+ *
359
+ * ```
360
+ *
361
+ */
362
+ /*********
363
+ *
364
+ * Get the current value of every prop, as an object. Compare
365
+ * {@link prop_map}, which returns a `Map`. Akin to {@link strict_prop},
366
+ * this throws if a required prop is missing.
367
+ *
368
+ * ```typescript
369
+ *
370
+ * ```
371
+ *
372
+ */
373
+ /*********
374
+ *
375
+ * Check whether a given string is a known property's name.
376
+ *
377
+ * ```typescript
378
+ * const example = sm`property foo default 1; a->b;`;
379
+ *
380
+ * example.known_prop('foo'); // true
381
+ * example.known_prop('bar'); // false
382
+ * ```
383
+ *
384
+ * @param prop_name The relevant property name to look up
385
+ *
386
+ */
387
+ known_prop(prop_name: string): boolean;
388
+ /*********
389
+ *
390
+ * List all known property names. If you'd also like values, use
391
+ * {@link props} instead. The order of the properties is not defined, and
392
+ * the properties generally will not be sorted.
393
+ *
394
+ * ```typescript
395
+ * ```
396
+ *
397
+ */
398
+ known_props(): string[];
297
399
  /********
298
400
  *
299
401
  * Check whether a given state is final (either has no exits or is marked
@@ -696,15 +798,27 @@ declare class Machine<mDT> {
696
798
  * Instruct the machine to complete an action. Synonym for {@link action}.
697
799
  *
698
800
  * ```typescript
699
- * const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
801
+ * const light = sm`
802
+ * off 'start' -> red;
803
+ * red 'next' -> green 'next' -> yellow 'next' -> red;
804
+ * [red yellow green] 'shutdown' ~> off;
805
+ * `;
700
806
  *
701
- * light.state(); // 'red'
702
- * light.do('next'); // true
703
- * light.state(); // 'green'
807
+ * light.state(); // 'off'
808
+ * light.do('start'); // true
809
+ * light.state(); // 'red'
810
+ * light.do('next'); // true
811
+ * light.state(); // 'green'
812
+ * light.do('next'); // true
813
+ * light.state(); // 'yellow'
814
+ * light.do('dance'); // !! false - no such action
815
+ * light.state(); // 'yellow'
816
+ * light.do('start'); // !! false - yellow does not have the action start
817
+ * light.state(); // 'yellow'
704
818
  * ```
705
819
  *
706
820
  * @typeparam mDT The type of the machine data member; usually omitted
707
- *
821
+ b *
708
822
  * @param actionName The action to engage
709
823
  *
710
824
  * @param newData The data change to insert during the action
@@ -716,11 +830,21 @@ declare class Machine<mDT> {
716
830
  * Instruct the machine to complete a transition. Synonym for {@link go}.
717
831
  *
718
832
  * ```typescript
719
- * const light = sm`red -> green -> yellow -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
833
+ * const light = sm`
834
+ * off 'start' -> red;
835
+ * red 'next' -> green 'next' -> yellow 'next' -> red;
836
+ * [red yellow green] 'shutdown' ~> off;
837
+ * `;
720
838
  *
721
- * light.state(); // 'red'
722
- * light.transition('green'); // true
723
- * light.state(); // 'green'
839
+ * light.state(); // 'off'
840
+ * light.go('red'); // true
841
+ * light.state(); // 'red'
842
+ * light.go('green'); // true
843
+ * light.state(); // 'green'
844
+ * light.go('blue'); // !! false - no such state
845
+ * light.state(); // 'green'
846
+ * light.go('red'); // !! false - green may not go directly to red, only to yellow
847
+ * light.state(); // 'green'
724
848
  * ```
725
849
  *
726
850
  * @typeparam mDT The type of the machine data member; usually omitted
@@ -833,4 +957,4 @@ declare function is_hook_complex_result<mDT>(hr: unknown): hr is HookComplexResu
833
957
  declare function is_hook_rejection<mDT>(hr: HookResult<mDT>): boolean;
834
958
  declare function abstract_hook_step<mDT>(maybe_hook: HookHandler<mDT> | undefined, hook_args: HookContext<mDT>): HookComplexResult<mDT>;
835
959
  declare function deserialize<mDT>(machine_string: string, ser: JssmSerialization<mDT>): Machine<mDT>;
836
- export { version, transfer_state_properties, Machine, deserialize, make, wrap_parse as parse, compile, sm, from, arrow_direction, arrow_left_kind, arrow_right_kind, seq, weighted_rand_select, histograph, weighted_sample_select, weighted_histo_key, shapes, gviz_shapes, named_colors, is_hook_rejection, is_hook_complex_result, abstract_hook_step };
960
+ export { version, transfer_state_properties, Machine, deserialize, make, wrap_parse as parse, compile, sm, from, arrow_direction, arrow_left_kind, arrow_right_kind, seq, unique, find_repeated, weighted_rand_select, histograph, weighted_sample_select, weighted_histo_key, shapes, gviz_shapes, named_colors, is_hook_rejection, is_hook_complex_result, abstract_hook_step };
package/dist/es6/jssm.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // whargarbl lots of these return arrays could/should be sets
2
2
  import { reduce as reduce_to_639 } from 'reduce-to-639-1';
3
3
  import { circular_buffer } from 'circular_buffer_js';
4
- import { seq, weighted_rand_select, weighted_sample_select, histograph, weighted_histo_key, array_box_if_string, hook_name, named_hook_name } from './jssm_util';
4
+ import { seq, unique, find_repeated, weighted_rand_select, weighted_sample_select, histograph, weighted_histo_key, array_box_if_string, name_bind_prop_and_state, hook_name, named_hook_name } from './jssm_util';
5
5
  import { shapes, gviz_shapes, named_colors } from './jssm_constants';
6
6
  import { parse } from './jssm-dot';
7
7
  import { version } from './version'; // replaced from package.js in build
@@ -351,6 +351,16 @@ function compile_rule_handler(rule) {
351
351
  if (rule.key === 'machine_language') {
352
352
  return { agg_as: 'machine_language', val: reduce_to_639(rule.value) };
353
353
  }
354
+ // manually rehandled to make `undefined` as a property safe
355
+ if (rule.key === 'property_definition') {
356
+ if (rule.hasOwnProperty('default_value')) {
357
+ return { agg_as: 'property_definition', val: { name: rule.name, default_value: rule.default_value } };
358
+ }
359
+ else {
360
+ return { agg_as: 'property_definition', val: { name: rule.name } };
361
+ }
362
+ }
363
+ // state properties are in here
354
364
  if (rule.key === 'state_declaration') {
355
365
  if (!rule.name) {
356
366
  throw new JssmError(undefined, 'State declarations must have a name');
@@ -361,6 +371,7 @@ function compile_rule_handler(rule) {
361
371
  'arrange_end_declaration'].includes(rule.key)) {
362
372
  return { agg_as: rule.key, val: [rule.value] };
363
373
  }
374
+ // things that can only exist once and are just a value under their own name
364
375
  const tautologies = [
365
376
  'graph_layout', 'start_states', 'end_states', 'machine_name', 'machine_version',
366
377
  'machine_comment', 'machine_author', 'machine_contributor', 'machine_definition',
@@ -440,6 +451,8 @@ function compile(tree) {
440
451
  machine_license: [],
441
452
  machine_name: [],
442
453
  machine_reference: [],
454
+ property_definition: [],
455
+ state_property: {},
443
456
  theme: [],
444
457
  flow: [],
445
458
  dot_preamble: [],
@@ -452,10 +465,15 @@ function compile(tree) {
452
465
  const rule = compile_rule_handler(tr), agg_as = rule.agg_as, val = rule.val; // TODO FIXME no any
453
466
  results[agg_as] = results[agg_as].concat(val);
454
467
  });
468
+ const property_keys = results['property_definition'].map(pd => pd.name), repeat_props = find_repeated(property_keys);
469
+ if (repeat_props.length) {
470
+ throw new JssmError(undefined, `Cannot repeat property definitions. Saw ${JSON.stringify(repeat_props)}`);
471
+ }
455
472
  const assembled_transitions = [].concat(...results['transition']);
456
473
  const result_cfg = {
457
474
  start_states: results.start_states.length ? results.start_states : [assembled_transitions[0].from],
458
- transitions: assembled_transitions
475
+ transitions: assembled_transitions,
476
+ state_property: []
459
477
  };
460
478
  const oneOnlyKeys = [
461
479
  'graph_layout', 'machine_name', 'machine_version', 'machine_comment',
@@ -473,11 +491,28 @@ function compile(tree) {
473
491
  }
474
492
  });
475
493
  ['arrange_declaration', 'arrange_start_declaration', 'arrange_end_declaration',
476
- 'machine_author', 'machine_contributor', 'machine_reference', 'state_declaration'].map((multiKey) => {
494
+ 'machine_author', 'machine_contributor', 'machine_reference',
495
+ 'state_declaration', 'property_definition'].map((multiKey) => {
477
496
  if (results[multiKey].length) {
478
497
  result_cfg[multiKey] = results[multiKey];
479
498
  }
480
499
  });
500
+ // re-walk state declarations, already wrapped up, to get state properties,
501
+ // which go out in a different datastructure
502
+ results.state_declaration.forEach(sd => {
503
+ sd.declarations.forEach(decl => {
504
+ if (decl.key === 'state_property') {
505
+ const label = name_bind_prop_and_state(decl.name, sd.state);
506
+ console.log(`Bind ${sd.state}:${decl.name} as ${label}`);
507
+ if (result_cfg.state_property.findIndex(c => c.name === label) !== -1) {
508
+ throw new JssmError(undefined, `A state may only bind a property once (${sd.state} re-binds ${decl.name})`);
509
+ }
510
+ else {
511
+ result_cfg.state_property.push({ name: label, default_value: decl.value });
512
+ }
513
+ }
514
+ });
515
+ });
481
516
  return result_cfg;
482
517
  }
483
518
  /*********
@@ -527,6 +562,9 @@ function transfer_state_properties(state_decl) {
527
562
  case 'border-color':
528
563
  state_decl.borderColor = d.value;
529
564
  break;
565
+ case 'state_property':
566
+ state_decl.property = { name: d.name, value: d.value };
567
+ break;
530
568
  default: throw new JssmError(undefined, `Unknown state property: '${JSON.stringify(d)}'`);
531
569
  }
532
570
  });
@@ -535,7 +573,7 @@ function transfer_state_properties(state_decl) {
535
573
  // TODO add a lotta docblock here
536
574
  class Machine {
537
575
  // whargarbl this badly needs to be broken up, monolith master
538
- 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 = undefined, arrange_declaration = [], arrange_start_declaration = [], arrange_end_declaration = [], theme = 'default', flow = 'down', graph_layout = 'dot', instance_name, history, data }) {
576
+ constructor({ start_states, complete = [], transitions, machine_author, machine_comment, machine_contributor, machine_definition, machine_language, machine_license, machine_name, machine_version, state_declaration, property_definition, state_property, fsl_version, dot_preamble = undefined, arrange_declaration = [], arrange_start_declaration = [], arrange_end_declaration = [], theme = 'default', flow = 'down', graph_layout = 'dot', instance_name, history, data }) {
539
577
  this._instance_name = instance_name;
540
578
  this._state = start_states[0];
541
579
  this._states = new Map();
@@ -600,6 +638,9 @@ class Machine {
600
638
  this._post_forced_transition_hook = undefined;
601
639
  this._post_any_transition_hook = undefined;
602
640
  this._data = data;
641
+ this._property_keys = new Set();
642
+ this._default_properties = new Map();
643
+ this._state_properties = new Map();
603
644
  this._history_length = history || 0;
604
645
  this._history = new circular_buffer(this._history_length);
605
646
  if (state_declaration) {
@@ -697,6 +738,19 @@ class Machine {
697
738
  */
698
739
  }
699
740
  });
741
+ if (Array.isArray(property_definition)) {
742
+ property_definition.forEach(pr => {
743
+ this._property_keys.add(pr.name);
744
+ if (pr.hasOwnProperty('default_value')) {
745
+ this._default_properties.set(pr.name, pr.default_value);
746
+ }
747
+ });
748
+ }
749
+ if (Array.isArray(state_property)) {
750
+ state_property.forEach(sp => {
751
+ this._state_properties.set(sp.name, sp.default_value);
752
+ });
753
+ }
700
754
  }
701
755
  /********
702
756
  *
@@ -763,6 +817,136 @@ class Machine {
763
817
  return true; // todo whargarbl
764
818
  }
765
819
  */
820
+ // NEEDS_DOCS
821
+ /*********
822
+ *
823
+ * Get the current value of a given property name.
824
+ *
825
+ * ```typescript
826
+ *
827
+ * ```
828
+ *
829
+ * @param name The relevant property name to look up
830
+ *
831
+ * @returns The value behind the prop name. Because functional props are
832
+ * evaluated as getters, this can be anything.
833
+ *
834
+ */
835
+ prop(name) {
836
+ const bound_name = name_bind_prop_and_state(name, this.state());
837
+ if (this._state_properties.has(bound_name)) {
838
+ return this._state_properties.get(bound_name);
839
+ }
840
+ else if (this._default_properties.has(name)) {
841
+ return this._default_properties.get(name);
842
+ }
843
+ else {
844
+ return undefined;
845
+ }
846
+ }
847
+ // NEEDS_DOCS
848
+ // COMEBACK add prop_map, sparse_props and strict_props to doc text when implemented
849
+ /*********
850
+ *
851
+ * Get the current value of every prop, as an object. If no current definition
852
+ * exists for a prop - that is, if the prop was defined without a default and
853
+ * the current state also doesn't define the prop - then that prop will be listed
854
+ * in the returned object with a value of `undefined`.
855
+ *
856
+ * ```typescript
857
+ * const traffic_light = sm`
858
+ *
859
+ * property can_go default true;
860
+ * property hesitate default true;
861
+ * property stop_first default false;
862
+ *
863
+ * Off -> Red => Green => Yellow => Red;
864
+ * [Red Yellow Green] ~> [Off FlashingRed];
865
+ * FlashingRed -> Red;
866
+ *
867
+ * state Red: { property stop_first true; property can_go false; };
868
+ * state Off: { property stop_first true; };
869
+ * state FlashingRed: { property stop_first true; };
870
+ * state Green: { property hesitate false; };
871
+ *
872
+ * `;
873
+ *
874
+ * traffic_light.state(); // Off
875
+ * traffic_light.props(); // { can_go: true, hesitate: true, stop_first: true; }
876
+ *
877
+ * traffic_light.go('Red');
878
+ * traffic_light.props(); // { can_go: false, hesitate: true, stop_first: true; }
879
+ *
880
+ * traffic_light.go('Green');
881
+ * traffic_light.props(); // { can_go: true, hesitate: false, stop_first: false; }
882
+ * ```
883
+ *
884
+ */
885
+ props() {
886
+ const ret = {};
887
+ this.known_props().forEach(p => ret[p] = this.prop(p));
888
+ return ret;
889
+ }
890
+ // NEEDS_DOCS
891
+ // TODO COMEBACK
892
+ /*********
893
+ *
894
+ * Get the current value of every prop, as an object. Compare
895
+ * {@link prop_map}, which returns a `Map`.
896
+ *
897
+ * ```typescript
898
+ *
899
+ * ```
900
+ *
901
+ */
902
+ // sparse_props(name: string): object {
903
+ // }
904
+ // NEEDS_DOCS
905
+ // TODO COMEBACK
906
+ /*********
907
+ *
908
+ * Get the current value of every prop, as an object. Compare
909
+ * {@link prop_map}, which returns a `Map`. Akin to {@link strict_prop},
910
+ * this throws if a required prop is missing.
911
+ *
912
+ * ```typescript
913
+ *
914
+ * ```
915
+ *
916
+ */
917
+ // strict_props(name: string): object {
918
+ // }
919
+ /*********
920
+ *
921
+ * Check whether a given string is a known property's name.
922
+ *
923
+ * ```typescript
924
+ * const example = sm`property foo default 1; a->b;`;
925
+ *
926
+ * example.known_prop('foo'); // true
927
+ * example.known_prop('bar'); // false
928
+ * ```
929
+ *
930
+ * @param prop_name The relevant property name to look up
931
+ *
932
+ */
933
+ known_prop(prop_name) {
934
+ return this._property_keys.has(prop_name);
935
+ }
936
+ // NEEDS_DOCS
937
+ /*********
938
+ *
939
+ * List all known property names. If you'd also like values, use
940
+ * {@link props} instead. The order of the properties is not defined, and
941
+ * the properties generally will not be sorted.
942
+ *
943
+ * ```typescript
944
+ * ```
945
+ *
946
+ */
947
+ known_props() {
948
+ return [...this._property_keys];
949
+ }
766
950
  /********
767
951
  *
768
952
  * Check whether a given state is final (either has no exits or is marked
@@ -881,11 +1065,6 @@ class Machine {
881
1065
  states: this._states
882
1066
  };
883
1067
  }
884
- /*
885
- load_machine_state(): boolean {
886
- return false; // todo whargarbl
887
- }
888
- */
889
1068
  /*********
890
1069
  *
891
1070
  * List all the states known by the machine. Please note that the order of
@@ -1768,15 +1947,27 @@ class Machine {
1768
1947
  * Instruct the machine to complete an action. Synonym for {@link action}.
1769
1948
  *
1770
1949
  * ```typescript
1771
- * const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
1950
+ * const light = sm`
1951
+ * off 'start' -> red;
1952
+ * red 'next' -> green 'next' -> yellow 'next' -> red;
1953
+ * [red yellow green] 'shutdown' ~> off;
1954
+ * `;
1772
1955
  *
1773
- * light.state(); // 'red'
1774
- * light.do('next'); // true
1775
- * light.state(); // 'green'
1956
+ * light.state(); // 'off'
1957
+ * light.do('start'); // true
1958
+ * light.state(); // 'red'
1959
+ * light.do('next'); // true
1960
+ * light.state(); // 'green'
1961
+ * light.do('next'); // true
1962
+ * light.state(); // 'yellow'
1963
+ * light.do('dance'); // !! false - no such action
1964
+ * light.state(); // 'yellow'
1965
+ * light.do('start'); // !! false - yellow does not have the action start
1966
+ * light.state(); // 'yellow'
1776
1967
  * ```
1777
1968
  *
1778
1969
  * @typeparam mDT The type of the machine data member; usually omitted
1779
- *
1970
+ b *
1780
1971
  * @param actionName The action to engage
1781
1972
  *
1782
1973
  * @param newData The data change to insert during the action
@@ -1790,11 +1981,21 @@ class Machine {
1790
1981
  * Instruct the machine to complete a transition. Synonym for {@link go}.
1791
1982
  *
1792
1983
  * ```typescript
1793
- * const light = sm`red -> green -> yellow -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;
1984
+ * const light = sm`
1985
+ * off 'start' -> red;
1986
+ * red 'next' -> green 'next' -> yellow 'next' -> red;
1987
+ * [red yellow green] 'shutdown' ~> off;
1988
+ * `;
1794
1989
  *
1795
- * light.state(); // 'red'
1796
- * light.transition('green'); // true
1797
- * light.state(); // 'green'
1990
+ * light.state(); // 'off'
1991
+ * light.go('red'); // true
1992
+ * light.state(); // 'red'
1993
+ * light.go('green'); // true
1994
+ * light.state(); // 'green'
1995
+ * light.go('blue'); // !! false - no such state
1996
+ * light.state(); // 'green'
1997
+ * light.go('red'); // !! false - green may not go directly to red, only to yellow
1998
+ * light.state(); // 'green'
1798
1999
  * ```
1799
2000
  *
1800
2001
  * @typeparam mDT The type of the machine data member; usually omitted
@@ -2015,4 +2216,4 @@ function deserialize(machine_string, ser) {
2015
2216
  }
2016
2217
  export { version, transfer_state_properties, Machine, deserialize, make, wrap_parse as parse, compile, sm, from, arrow_direction, arrow_left_kind, arrow_right_kind,
2017
2218
  // WHARGARBL TODO these should be exported to a utility library
2018
- seq, weighted_rand_select, histograph, weighted_sample_select, weighted_histo_key, shapes, gviz_shapes, named_colors, is_hook_rejection, is_hook_complex_result, abstract_hook_step };
2219
+ seq, unique, find_repeated, weighted_rand_select, histograph, weighted_sample_select, weighted_histo_key, shapes, gviz_shapes, named_colors, is_hook_rejection, is_hook_complex_result, abstract_hook_step };
@@ -35,6 +35,10 @@ declare type JssmSerialization<DataType> = {
35
35
  history_capacity: number;
36
36
  data: DataType;
37
37
  };
38
+ declare type JssmPropertyDefinition = {
39
+ name: string;
40
+ default_value?: any;
41
+ };
38
42
  declare type JssmTransitionPermitter<DataType> = (OldState: StateType, NewState: StateType, OldData: DataType, NewData: DataType) => boolean;
39
43
  declare type JssmTransitionPermitterMaybeArray<DataType> = JssmTransitionPermitter<DataType> | Array<JssmTransitionPermitter<DataType>>;
40
44
  declare type JssmTransition<DataType> = {
@@ -48,7 +52,7 @@ declare type JssmTransition<DataType> = {
48
52
  forced_only: boolean;
49
53
  main_path: boolean;
50
54
  };
51
- declare type JssmTransitions<DataType> = Array<JssmTransition<DataType>>;
55
+ declare type JssmTransitions<DataType> = JssmTransition<DataType>[];
52
56
  declare type JssmTransitionList = {
53
57
  entrances: Array<StateType>;
54
58
  exits: Array<StateType>;
@@ -93,6 +97,7 @@ declare type JssmGenericMachine<DataType> = {
93
97
  declare type JssmStateDeclarationRule = {
94
98
  key: string;
95
99
  value: any;
100
+ name?: string;
96
101
  };
97
102
  declare type JssmStateDeclaration = {
98
103
  declarations: Array<JssmStateDeclarationRule>;
@@ -104,6 +109,10 @@ declare type JssmStateDeclaration = {
104
109
  backgroundColor?: JssmColor;
105
110
  borderColor?: JssmColor;
106
111
  state: StateType;
112
+ property?: {
113
+ name: string;
114
+ value: unknown;
115
+ };
107
116
  };
108
117
  declare type JssmGenericConfig<DataType> = {
109
118
  graph_layout?: JssmLayout;
@@ -125,7 +134,9 @@ declare type JssmGenericConfig<DataType> = {
125
134
  dot_preamble?: string;
126
135
  start_states: Array<StateType>;
127
136
  end_states?: Array<StateType>;
128
- state_declaration?: Array<Object>;
137
+ state_declaration?: Object[];
138
+ property_definition?: JssmPropertyDefinition[];
139
+ state_property?: JssmPropertyDefinition[];
129
140
  arrange_declaration?: Array<Array<StateType>>;
130
141
  arrange_start_declaration?: Array<Array<StateType>>;
131
142
  arrange_end_declaration?: Array<Array<StateType>>;
@@ -160,6 +171,8 @@ declare type JssmCompileSeStart<DataType> = {
160
171
  key: string;
161
172
  value?: string | number;
162
173
  name?: string;
174
+ state?: string;
175
+ default_value?: any;
163
176
  };
164
177
  declare type JssmParseTree = Array<JssmCompileSeStart<StateType>>;
165
178
  declare type JssmParseFunctionType = (string: any) => JssmParseTree;
@@ -275,4 +288,4 @@ declare type JssmErrorExtendedInfo = {
275
288
  requested_state?: StateType | undefined;
276
289
  };
277
290
  declare type JssmHistory<mDT> = circular_buffer<[StateType, mDT]>;
278
- export { JssmColor, JssmShape, JssmTransition, JssmTransitions, JssmTransitionList, JssmTransitionRule, JssmArrow, JssmArrowKind, JssmArrowDirection, JssmGenericConfig, JssmGenericState, JssmGenericMachine, JssmParseTree, JssmCompileSe, JssmCompileSeStart, JssmCompileRule, JssmPermitted, JssmPermittedOpt, JssmResult, JssmStateDeclaration, JssmStateDeclarationRule, JssmLayout, JssmHistory, JssmSerialization, JssmParseFunctionType, JssmMachineInternalState, JssmErrorExtendedInfo, FslDirection, FslTheme, HookDescription, HookHandler, HookContext, HookResult, HookComplexResult };
291
+ export { JssmColor, JssmShape, JssmTransition, JssmTransitions, JssmTransitionList, JssmTransitionRule, JssmArrow, JssmArrowKind, JssmArrowDirection, JssmGenericConfig, JssmGenericState, JssmGenericMachine, JssmParseTree, JssmCompileSe, JssmCompileSeStart, JssmCompileRule, JssmPermitted, JssmPermittedOpt, JssmResult, JssmStateDeclaration, JssmStateDeclarationRule, JssmLayout, JssmHistory, JssmSerialization, JssmPropertyDefinition, JssmParseFunctionType, JssmMachineInternalState, JssmErrorExtendedInfo, FslDirection, FslTheme, HookDescription, HookHandler, HookContext, HookResult, HookComplexResult };
@@ -35,6 +35,13 @@ declare function seq(n: number): number[];
35
35
  declare const histograph: Function;
36
36
  declare const weighted_sample_select: Function;
37
37
  declare const weighted_histo_key: Function;
38
+ /*******
39
+ *
40
+ * Internal method generating names for edges for the hook lookup map. Not
41
+ * meant for external use.
42
+ *
43
+ */
44
+ declare function name_bind_prop_and_state(prop: string, state: string): string;
38
45
  /*******
39
46
  *
40
47
  * Internal method generating names for edges for the hook lookup map. Not
@@ -57,4 +64,40 @@ declare const named_hook_name: (from: string, to: string, action: string) => str
57
64
  *
58
65
  */
59
66
  declare const make_mulberry_rand: (a?: number | undefined) => () => number;
60
- export { seq, arr_uniq_p, histograph, weighted_histo_key, weighted_rand_select, weighted_sample_select, array_box_if_string, hook_name, named_hook_name, make_mulberry_rand };
67
+ /*******
68
+ *
69
+ * Reduces an array to its unique contents. Compares with `===` and makes no
70
+ * effort to deep-compare contents; two matching arrays or objects contained
71
+ * will be treated as distinct, according to javascript rules. This also means
72
+ * that `NaNs` will be ***dropped***, because they do not self-compare.
73
+ *
74
+ * ```typescript
75
+ * unique( [] ); // []
76
+ * unique( [0,0] ); // [0]
77
+ * unique( [0,1,2, 0,1,2, 0,1,2] ); // [0,1,2]
78
+ * unique( [ [1], [1] ] ); // [ [1], [1] ] because arrays don't match
79
+ * unique( [0,NaN,2] ); // [0,2]
80
+ * ```
81
+ *
82
+ */
83
+ declare const unique: <T>(arr?: T[]) => T[];
84
+ /*******
85
+ *
86
+ * Lists all repeated items in an array along with their counts. Subject to
87
+ * matching rules of Map. `NaN` is manually removed because of conflict rules
88
+ * around {@link unique}. Because these are compared with `===` and because
89
+ * arrays and objects never match that way unless they're the same object,
90
+ * arrays and objects are never considered repeats.
91
+ *
92
+ * ```typescript
93
+ * find_repeated<string>([ ]); // []
94
+ * find_repeated<string>([ "one" ]); // []
95
+ * find_repeated<string>([ "one", "two" ]); // []
96
+ * find_repeated<string>([ "one", "one" ]); // [ ["one", 2] ]
97
+ * find_repeated<string>([ "one", "two", "one" ]); // [ ["one", 2] ]
98
+ * find_repeated<number>([ 0, NaN, 0, NaN ]); // [ [0, 2] ]
99
+ * ```
100
+ *
101
+ */
102
+ declare function find_repeated<T>(arr: T[]): [T, number][];
103
+ export { seq, unique, find_repeated, arr_uniq_p, histograph, weighted_histo_key, weighted_rand_select, weighted_sample_select, array_box_if_string, name_bind_prop_and_state, hook_name, named_hook_name, make_mulberry_rand };