@turing-machine-js/machine 7.0.0-alpha.5 → 7.0.0-alpha.7

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,9 +1,63 @@
1
- import State from './State';
1
+ import State, { type DebugConfig } from './State';
2
2
  import TapeBlock from './TapeBlock';
3
3
  type RunParameter = {
4
4
  initialState: State;
5
5
  stepsLimit?: number;
6
6
  };
7
+ /**
8
+ * Descriptor attached to a `DebugSession` `pause` event. Lives ONLY on the
9
+ * pause-event payload (`PausedMachineState`) — never on a raw `runStepByStep`
10
+ * yield, which is a minimal `MachineState` with no debug concern.
11
+ *
12
+ * - `side` — exactly one of `'before'` / `'after'`. DebugSession dispatches the
13
+ * two timings as separate `pause` events, so a single descriptor is always
14
+ * one-sided (the v6 "both timings on one yield" set no longer exists, because
15
+ * detection moved out of the generator).
16
+ * - `cause` — pause origin:
17
+ * - `'breakpoint'` — a `state.debug[when]` filter or `haltState.debug === true` matched.
18
+ * - `'step'` — a step-mode endpoint fired (stepIn / stepOver / stepOut).
19
+ * - `'manual'` — a `DebugSession.pause()` call fired.
20
+ *
21
+ * Precedence when an iter satisfies more than one trigger: `breakpoint > step >
22
+ * manual`. `'step'` / `'manual'` only ever fire on the `'before'` side.
23
+ */
24
+ export type PauseInfo = {
25
+ side: 'before' | 'after';
26
+ cause: 'breakpoint' | 'step' | 'manual';
27
+ };
28
+ /**
29
+ * @internal — directive returned from a DebugSession's internal pause coordination
30
+ * to drive step-mode bookkeeping. NOT part of the public API; exported only for
31
+ * sibling-module use inside `packages/machine/src/classes/DebugSession.ts`.
32
+ */
33
+ export type ResumeDirective = 'continue' | 'step-in' | 'step-over' | 'step-out';
34
+ /**
35
+ * @internal — package-private accessor key for `MachineState` instances yielded
36
+ * by `runStepByStep`. Calling `machineState[MACHINE_STATE_INTERNAL]()` returns a
37
+ * frozen snapshot of the engine's halt-stack at yield time (BEFORE this iter's
38
+ * applyCommand / pop / push). Consumed by `DebugSession` for step-over /
39
+ * step-out endpoint detection without exposing the stack to public API.
40
+ *
41
+ * Re-exported from this module so the sibling `DebugSession` module can import
42
+ * it; intentionally NOT re-exported from the package's public `index.ts` —
43
+ * downstream consumers shouldn't reach for the stack. Same pattern as
44
+ * `STATE_INTERNAL` (#180).
45
+ */
46
+ export declare const MACHINE_STATE_INTERNAL: unique symbol;
47
+ export type MachineStateInternal = {
48
+ /** Frozen pre-iter halt-stack snapshot. Consumers must not mutate. */
49
+ stack: readonly State[];
50
+ /** The interned symbol the engine matched for this iter (the result of
51
+ * `state.getSymbol(tapeBlock)`). DebugSession uses it to evaluate
52
+ * `state.debug` filters without re-reading the tape. */
53
+ matchedSymbol: symbol;
54
+ /** Whether this iter's transition leads to halt — computed on the RAW
55
+ * next-state (before any halt-pop redirect to a continuation). The yielded
56
+ * `MachineState.nextState` shows the post-pop continuation, so consumers
57
+ * can't recover halt-imminence from it; DebugSession reads this flag to
58
+ * honor `haltState.debug` on subroutine-return (halt-pop) iters. */
59
+ haltImminent: boolean;
60
+ };
7
61
  export type MachineState = {
8
62
  step: number;
9
63
  state: State;
@@ -11,21 +65,6 @@ export type MachineState = {
11
65
  nextSymbols: string[];
12
66
  movements: symbol[];
13
67
  nextState: State;
14
- /**
15
- * Set only when this iteration is a debug break point.
16
- * Field is OMITTED entirely when no break fires (no `debugBreak: undefined`).
17
- * At least one of `before` / `after` is `true` when the field is present.
18
- *
19
- * Both flags refer to THIS iter — `before` means the iter's `state.debug.before`
20
- * matched, `after` means the iter's `state.debug.after` matched. `run()`
21
- * dispatches the two timings as separate `onPause` calls (before-call has
22
- * `debugBreak: {before: true}` only; after-call has `debugBreak: {after: true}`
23
- * only) so consumers can distinguish without ambiguity.
24
- */
25
- debugBreak?: {
26
- before?: true;
27
- after?: true;
28
- };
29
68
  /**
30
69
  * The transition the engine picked for this iter (#205). Always present
31
70
  * — `runStepByStep` resolves it at the very start of every iter via
@@ -50,67 +89,43 @@ export type MachineState = {
50
89
  matchKinds: ('wildcard' | 'literal')[];
51
90
  };
52
91
  };
92
+ /**
93
+ * The payload of a `DebugSession` `pause` event: a `MachineState` plus the
94
+ * one-sided `pause` descriptor. Raw `runStepByStep` yields are plain
95
+ * `MachineState` (no `pause` field) — only DebugSession produces this shape.
96
+ */
97
+ export type PausedMachineState = MachineState & {
98
+ pause: PauseInfo;
99
+ };
100
+ /**
101
+ * @internal — true iff `filter` matches `symbol` per the DebugConfig semantics.
102
+ * undefined / [] -> never; true -> always; symbol[] -> exact membership.
103
+ * Exported for sibling-module use in `DebugSession` (which now owns breakpoint
104
+ * detection); NOT re-exported from the package's public `index.ts`.
105
+ */
106
+ export declare function matchFilter(filter: DebugConfig['before'], symbol: symbol): boolean;
53
107
  export default class TuringMachine {
54
108
  #private;
55
109
  constructor({ tapeBlock, }?: {
56
110
  tapeBlock?: TapeBlock;
57
111
  });
58
112
  get tapeBlock(): TapeBlock;
59
- run({ initialState, stepsLimit, onStep, onPause, onIter, debug, }: RunParameter & {
60
- /**
61
- * Sync, ~free hook fired on every iteration. Use for logging/tracing
62
- * the hot loop runs this without a microtask boundary, so it must not
63
- * be async.
64
- *
65
- * For per-iter throttle / coordination ("wait between iters" UIs):
66
- * use `onIter` (v6.4.0+, awaited at end-of-iter).
67
- */
68
- onStep?: (machineState: MachineState) => void;
69
- /**
70
- * Async hook fired when `state.debug[when]` matches at the current
71
- * iteration. The promise is awaited inline, so the consumer can suspend
72
- * execution by deferring its resolution. Use for pause-capable inspection
73
- * (debugger UIs, conditional breakpoints in tests).
74
- *
75
- * Renamed from `onDebugBreak` in v5.0.0. In v6.0.0 the dispatch order
76
- * was changed so that `before` and `after` for the SAME iter fire on the
77
- * same yield (per-iter lifecycle: before → step → after); previously the
78
- * `after` of iter K fired on iter K+1's tick with a substituted source
79
- * view. The `m.debugBreak` payload field keeps its name (it describes the
80
- * engine's reason for pausing).
81
- */
82
- onPause?: (machineState: MachineState) => void | Promise<void>;
83
- /**
84
- * Awaited hook fired ONCE at the end of every iteration (v6.4.0+), AFTER
85
- * any `onPause(after, K)` dispatch on the same yield. Use for per-iter
86
- * coordination that needs to suspend the run loop — throttling between
87
- * iters (interactive debugger UIs), prev-state bookkeeping that must
88
- * observe iter K's final state once all `onPause` hooks have read their
89
- * own snapshots, yield-to-other-work in batched runs.
90
- *
91
- * Three-hook contract recap:
92
- * - `onStep`: sync, microtask-free — tracing/logging during the iter
93
- * - `onPause`: awaited, conditional on `state.debug[when]` match — user
94
- * breakpoints with iter-correct payload
95
- * - `onIter`: awaited, unconditional — once per iter, at end-of-iter
96
- *
97
- * `onIter` is unaffected by the `debug` master switch — it fires on
98
- * every iter regardless. Sync consumers should prefer `onStep` to avoid
99
- * the per-iter microtask boundary `onIter` carries.
100
- */
101
- onIter?: (machineState: MachineState) => void | Promise<void>;
102
- /**
103
- * Master switch for `onPause` dispatch. When `false`, suppresses all
104
- * pause-fires (before and after) regardless of `state.debug` assignments.
105
- * `onStep` is unaffected. Defaults to `true`.
106
- *
107
- * The `m.debugBreak` field is still populated on yields by the underlying
108
- * generator (it's a property of the iteration, not of the consumer); only
109
- * `run()`'s hook dispatch is gated. Direct `runStepByStep` consumers see
110
- * the metadata regardless.
111
- */
112
- debug?: boolean;
113
- }): Promise<void>;
113
+ /**
114
+ * Run the machine to halt. Pure execution — synchronous, no observation
115
+ * callbacks, no debug overhead. For breakpoint-driven interactive debugging
116
+ * use `DebugSession`; for per-iter tracing use `runStepByStep`'s generator
117
+ * directly.
118
+ *
119
+ * Breakpoint metadata (`state.debug` / `haltState.debug` matches) is still
120
+ * resolved and attached to each yielded MachineState by the underlying
121
+ * generator — `run()` simply doesn't dispatch on it. A consumer that wants
122
+ * to dispatch on it constructs a `DebugSession` instead.
123
+ *
124
+ * Symmetric reversal of v4's `run` `async run` change: v4 made the method
125
+ * async to support awaited `onPause`; with callbacks moved to `DebugSession`
126
+ * there's no async work left, so the method returns `void` again.
127
+ */
128
+ run({ initialState, stepsLimit }: RunParameter): void;
114
129
  runStepByStep({ initialState, stepsLimit }: RunParameter): Generator<MachineState>;
115
130
  }
116
131
  export {};