libpetri 2.5.0 → 2.7.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.
- package/dist/{chunk-FN773SSE.js → chunk-ATT7U5H5.js} +1 -1
- package/dist/chunk-ATT7U5H5.js.map +1 -0
- package/dist/{chunk-H62Z76FY.js → chunk-ETNHEAS6.js} +130 -18
- package/dist/chunk-ETNHEAS6.js.map +1 -0
- package/dist/{chunk-2GAZLDH3.js → chunk-ULX3OG6H.js} +2 -2
- package/dist/debug/index.d.ts +2 -2
- package/dist/debug/index.js +2 -2
- package/dist/doclet/index.d.ts +1 -1
- package/dist/doclet/index.js +3 -3
- package/dist/dot-exporter-TYC6FUAD.js +8 -0
- package/dist/{event-store-z30VMn0T.d.ts → event-store-8XkpYUeU.d.ts} +1 -1
- package/dist/export/index.d.ts +1 -1
- package/dist/export/index.js +2 -2
- package/dist/index.d.ts +29 -4
- package/dist/index.js +138 -26
- package/dist/index.js.map +1 -1
- package/dist/{petri-net-DXdpd0r5.d.ts → petri-net-D73-PO6d.d.ts} +41 -3
- package/dist/verification/index.d.ts +39 -34
- package/dist/verification/index.js +7 -17
- package/dist/verification/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-FN773SSE.js.map +0 -1
- package/dist/chunk-H62Z76FY.js.map +0 -1
- package/dist/dot-exporter-7YDFCBKC.js +0 -8
- /package/dist/{chunk-2GAZLDH3.js.map → chunk-ULX3OG6H.js.map} +0 -0
- /package/dist/{dot-exporter-7YDFCBKC.js.map → dot-exporter-TYC6FUAD.js.map} +0 -0
package/dist/export/index.d.ts
CHANGED
package/dist/export/index.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { P as PetriNet, S as SubnetDef, a as Place, T as Token, b as Transition, E as EnvironmentPlace, c as TransitionContext, O as Out } from './petri-net-
|
|
2
|
-
export { A as Arc, d as ArcInhibitor, e as ArcInput, f as ArcOutput, g as ArcRead, h as ArcReset, C as Channel, i as ComposeBindings, F as FusionSet, j as FusionSetBuilder, I as In, k as InAll, l as InAtLeast, m as InExactly, n as InOne, o as Instance, p as Interface, q as InterfaceBuilder, L as LogFn, M as MAX_DURATION_MS, r as OutAnd, s as OutForwardInput, t as OutPlace, u as OutTimeout, v as OutXor, w as OutputEntry, x as PetriNetBuilder, y as Port, z as PortDirection, B as SubnetDefBuilder, D as SubnetInstance, G as Timing, H as TimingDeadline, J as TimingDelayed, K as TimingExact, N as TimingImmediate, Q as TimingWindow, R as TokenInput, U as TokenOutput, V as TransitionAction, W as TransitionBuilder, X as VerificationHarness, Y as VerificationResult, Z as all, _ as allPlaces, $ as and, a0 as andPlaces, a1 as arcPlace, a2 as atLeast, a3 as consumptionCount, a4 as deadline, a5 as delayed, a6 as earliest, a7 as enumerateBranches, a8 as environmentPlace, a9 as exact, aa as exactly, ab as fork, ac as forwardInput, ad as hasDeadline, ae as hasGuard, af as immediate, ag as inhibitorArc, ah as inputArc, ai as isUnit, aj as latest, ak as matchesGuard, al as one, am as outPlace, an as outputArc, ao as passthrough, ap as place, aq as produce, ar as readArc, as as requiredCount, at as resetArc, au as timeout, av as timeoutPlace, aw as tokenAt, ax as tokenOf, ay as transform, az as transformAsync, aA as transformFrom, aB as unitToken, aC as window, aD as withTimeout, aE as xor, aF as xorPlaces } from './petri-net-
|
|
3
|
-
import { E as EventStore } from './event-store-
|
|
4
|
-
export { A as ActionTimedOut, a as ExecutionCompleted, b as ExecutionStarted, I as InMemoryEventStore, L as LogMessage, M as MarkingSnapshot, N as NetEvent, T as TokenAdded, c as TokenRemoved, d as TransitionClockRestarted, e as TransitionCompleted, f as TransitionEnabled, g as TransitionFailed, h as TransitionStarted, i as TransitionTimedOut, j as eventTransitionName, k as eventsOfType, l as failures, m as filterEvents, n as inMemoryEventStore, o as isFailureEvent, p as noopEventStore, t as transitionEvents } from './event-store-
|
|
1
|
+
import { P as PetriNet, S as SubnetDef, a as Place, T as Token, b as Transition, E as EnvironmentPlace, c as TransitionContext, O as Out } from './petri-net-D73-PO6d.js';
|
|
2
|
+
export { A as Arc, d as ArcInhibitor, e as ArcInput, f as ArcOutput, g as ArcRead, h as ArcReset, C as Channel, i as ComposeBindings, F as FusionSet, j as FusionSetBuilder, I as In, k as InAll, l as InAtLeast, m as InExactly, n as InOne, o as Instance, p as Interface, q as InterfaceBuilder, L as LogFn, M as MAX_DURATION_MS, r as OutAnd, s as OutForwardInput, t as OutPlace, u as OutTimeout, v as OutXor, w as OutputEntry, x as PetriNetBuilder, y as Port, z as PortDirection, B as SubnetDefBuilder, D as SubnetInstance, G as Timing, H as TimingDeadline, J as TimingDelayed, K as TimingExact, N as TimingImmediate, Q as TimingWindow, R as TokenInput, U as TokenOutput, V as TransitionAction, W as TransitionBuilder, X as VerificationHarness, Y as VerificationResult, Z as all, _ as allPlaces, $ as and, a0 as andPlaces, a1 as arcPlace, a2 as atLeast, a3 as consumptionCount, a4 as deadline, a5 as delayed, a6 as earliest, a7 as enumerateBranches, a8 as environmentPlace, a9 as exact, aa as exactly, ab as fork, ac as forwardInput, ad as hasDeadline, ae as hasGuard, af as immediate, ag as inhibitorArc, ah as inputArc, ai as isUnit, aj as latest, ak as matchesGuard, al as one, am as outPlace, an as outputArc, ao as passthrough, ap as place, aq as produce, ar as readArc, as as requiredCount, at as resetArc, au as timeout, av as timeoutPlace, aw as tokenAt, ax as tokenOf, ay as transform, az as transformAsync, aA as transformFrom, aB as unitToken, aC as window, aD as withTimeout, aE as xor, aF as xorPlaces } from './petri-net-D73-PO6d.js';
|
|
3
|
+
import { E as EventStore } from './event-store-8XkpYUeU.js';
|
|
4
|
+
export { A as ActionTimedOut, a as ExecutionCompleted, b as ExecutionStarted, I as InMemoryEventStore, L as LogMessage, M as MarkingSnapshot, N as NetEvent, T as TokenAdded, c as TokenRemoved, d as TransitionClockRestarted, e as TransitionCompleted, f as TransitionEnabled, g as TransitionFailed, h as TransitionStarted, i as TransitionTimedOut, j as eventTransitionName, k as eventsOfType, l as failures, m as filterEvents, n as inMemoryEventStore, o as isFailureEvent, p as noopEventStore, t as transitionEvents } from './event-store-8XkpYUeU.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Discriminated sum-type abstraction over Petri nets, distinguishing **closed**
|
|
@@ -221,6 +221,13 @@ interface BitmapNetExecutorOptions {
|
|
|
221
221
|
environmentPlaces?: Set<EnvironmentPlace<any>>;
|
|
222
222
|
/** Provides execution context data for each transition firing. */
|
|
223
223
|
executionContextProvider?: (transitionName: string, consumed: Token<any>[]) => Map<string, unknown>;
|
|
224
|
+
/**
|
|
225
|
+
* Grace band (ms) beyond a hard deadline (`deadline()` / `window()`) before a transition is
|
|
226
|
+
* force-disabled with a `transition-timed-out` event (TIME-013). Defaults to {@link DEADLINE_TOLERANCE_MS}
|
|
227
|
+
* (5ms); `0` gives strict enforcement. Must be non-negative. Does not affect `exact()` transitions,
|
|
228
|
+
* which are enforced softly (TIME-006).
|
|
229
|
+
*/
|
|
230
|
+
deadlineToleranceMs?: number;
|
|
224
231
|
}
|
|
225
232
|
/**
|
|
226
233
|
* Async bitmap-based executor for Coloured Time Petri Nets.
|
|
@@ -262,6 +269,10 @@ declare class BitmapNetExecutor implements PetriNetExecutor {
|
|
|
262
269
|
private readonly enabledFlags;
|
|
263
270
|
/** Precomputed: 1 if transition has a finite deadline, 0 otherwise. */
|
|
264
271
|
private readonly hasDeadlineFlags;
|
|
272
|
+
/** Precomputed: 1 for exact() transitions — enforced softly, never force-disabled (TIME-006). */
|
|
273
|
+
private readonly isExactFlags;
|
|
274
|
+
/** Grace band (ms) before a hard deadline force-disables (TIME-013). */
|
|
275
|
+
private readonly deadlineToleranceMs;
|
|
265
276
|
private enabledTransitionCount;
|
|
266
277
|
private readonly inFlight;
|
|
267
278
|
private readonly inFlightPromises;
|
|
@@ -394,6 +405,12 @@ declare class PrecompiledNet {
|
|
|
394
405
|
readonly earliestMs: Float64Array;
|
|
395
406
|
readonly latestMs: Float64Array;
|
|
396
407
|
readonly hasDeadline: Uint8Array;
|
|
408
|
+
/**
|
|
409
|
+
* 1 for `exact()` transitions. Exact transitions fire at the first opportunity at/after their
|
|
410
|
+
* target time (delayed-style liveness) and are never force-disabled by deadline enforcement —
|
|
411
|
+
* their upper bound is observed, not enforced. See TIME-006.
|
|
412
|
+
*/
|
|
413
|
+
readonly isExact: Uint8Array;
|
|
397
414
|
readonly priorities: Int32Array;
|
|
398
415
|
readonly transitionToPriorityIndex: Uint32Array;
|
|
399
416
|
readonly priorityLevels: readonly number[];
|
|
@@ -456,6 +473,13 @@ interface PrecompiledNetExecutorOptions {
|
|
|
456
473
|
skipOutputValidation?: boolean;
|
|
457
474
|
/** Reuse a precompiled program (avoids recompilation). */
|
|
458
475
|
program?: PrecompiledNet;
|
|
476
|
+
/**
|
|
477
|
+
* Grace band (ms) beyond a hard deadline (`deadline()` / `window()`) before a transition is
|
|
478
|
+
* force-disabled with a `transition-timed-out` event (TIME-013). Defaults to {@link DEADLINE_TOLERANCE_MS}
|
|
479
|
+
* (5ms); `0` gives strict enforcement. Must be non-negative. Does not affect `exact()` transitions,
|
|
480
|
+
* which are enforced softly (TIME-006).
|
|
481
|
+
*/
|
|
482
|
+
deadlineToleranceMs?: number;
|
|
459
483
|
}
|
|
460
484
|
/**
|
|
461
485
|
* High-performance executor using `PrecompiledNet`.
|
|
@@ -470,6 +494,7 @@ declare class PrecompiledNetExecutor implements PetriNetExecutor {
|
|
|
470
494
|
private readonly hasEnvironmentPlaces;
|
|
471
495
|
private readonly executionContextProvider?;
|
|
472
496
|
private readonly skipOutputValidation;
|
|
497
|
+
private readonly deadlineToleranceMs;
|
|
473
498
|
private readonly startMs;
|
|
474
499
|
private readonly eventStoreEnabled;
|
|
475
500
|
/** Per-place token arrays, indexed by pid. */
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
timeoutPlace,
|
|
13
13
|
xor,
|
|
14
14
|
xorPlaces
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-ETNHEAS6.js";
|
|
16
16
|
import {
|
|
17
17
|
eventTransitionName,
|
|
18
18
|
isFailureEvent
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
immediate,
|
|
28
28
|
latest,
|
|
29
29
|
window
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-ATT7U5H5.js";
|
|
31
31
|
|
|
32
32
|
// src/core/token.ts
|
|
33
33
|
var UNIT_TOKEN = Object.freeze({
|
|
@@ -203,6 +203,7 @@ function withTimeout(action, timeoutMs, timeoutPlace2, timeoutValue) {
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
// src/core/transition-context.ts
|
|
206
|
+
var EMPTY_ALIAS = /* @__PURE__ */ new Map();
|
|
206
207
|
var TransitionContext = class {
|
|
207
208
|
rawInput;
|
|
208
209
|
_rawOutput;
|
|
@@ -215,7 +216,8 @@ var TransitionContext = class {
|
|
|
215
216
|
_transitionName;
|
|
216
217
|
executionCtx;
|
|
217
218
|
_logFn;
|
|
218
|
-
|
|
219
|
+
placeAlias;
|
|
220
|
+
constructor(transitionName, rawInput, rawOutput, inputPlaces, readPlaces, outputPlaces, executionContext, logFn, placeAlias) {
|
|
219
221
|
this._transitionName = transitionName;
|
|
220
222
|
this.rawInput = rawInput;
|
|
221
223
|
this._rawOutput = rawOutput;
|
|
@@ -233,28 +235,45 @@ var TransitionContext = class {
|
|
|
233
235
|
this.allowedOutputs = ao;
|
|
234
236
|
this.executionCtx = executionContext ?? /* @__PURE__ */ new Map();
|
|
235
237
|
this._logFn = logFn;
|
|
238
|
+
this.placeAlias = placeAlias ?? EMPTY_ALIAS;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Resolves a place key through the transition's declared→actual place
|
|
242
|
+
* correspondence (per **MOD-031**). For a hand-written or directly-composed
|
|
243
|
+
* transition the correspondence is the identity, so this returns `place`
|
|
244
|
+
* unchanged; after instancing / port binding it maps a *declared* place
|
|
245
|
+
* constant the action hardcodes to the *actual* composed place. The result
|
|
246
|
+
* feeds both the declared-set check and the token-store access (both keyed by
|
|
247
|
+
* `place.name`), so `inputPlaces()`/`outputPlaces()` discovery is unaffected.
|
|
248
|
+
*/
|
|
249
|
+
resolve(place2) {
|
|
250
|
+
const actual = this.placeAlias.get(place2.name);
|
|
251
|
+
return actual !== void 0 ? actual : place2;
|
|
236
252
|
}
|
|
237
253
|
// ==================== Input Access (consumed) ====================
|
|
238
254
|
/** Get single consumed input value. Throws if place not declared or multiple tokens. */
|
|
239
255
|
input(place2) {
|
|
240
|
-
this.
|
|
241
|
-
|
|
256
|
+
const actual = this.resolve(place2);
|
|
257
|
+
this.requireInput(actual);
|
|
258
|
+
const values = this.rawInput.values(actual);
|
|
242
259
|
if (values.length !== 1) {
|
|
243
260
|
throw new Error(
|
|
244
|
-
`Place '${
|
|
261
|
+
`Place '${actual.name}' consumed ${values.length} tokens, use inputs() for batched access`
|
|
245
262
|
);
|
|
246
263
|
}
|
|
247
264
|
return values[0];
|
|
248
265
|
}
|
|
249
266
|
/** Get all consumed input values for a place. */
|
|
250
267
|
inputs(place2) {
|
|
251
|
-
this.
|
|
252
|
-
|
|
268
|
+
const actual = this.resolve(place2);
|
|
269
|
+
this.requireInput(actual);
|
|
270
|
+
return this.rawInput.values(actual);
|
|
253
271
|
}
|
|
254
272
|
/** Get consumed input token with metadata. */
|
|
255
273
|
inputToken(place2) {
|
|
256
|
-
this.
|
|
257
|
-
|
|
274
|
+
const actual = this.resolve(place2);
|
|
275
|
+
this.requireInput(actual);
|
|
276
|
+
return this.rawInput.get(actual);
|
|
258
277
|
}
|
|
259
278
|
/** Returns declared input places (consumed). */
|
|
260
279
|
inputPlaces() {
|
|
@@ -270,13 +289,15 @@ var TransitionContext = class {
|
|
|
270
289
|
// ==================== Read Access (not consumed) ====================
|
|
271
290
|
/** Get read-only context value. Throws if place not declared as read. */
|
|
272
291
|
read(place2) {
|
|
273
|
-
this.
|
|
274
|
-
|
|
292
|
+
const actual = this.resolve(place2);
|
|
293
|
+
this.requireRead(actual);
|
|
294
|
+
return this.rawInput.value(actual);
|
|
275
295
|
}
|
|
276
296
|
/** Get all read-only context values for a place. */
|
|
277
297
|
reads(place2) {
|
|
278
|
-
this.
|
|
279
|
-
|
|
298
|
+
const actual = this.resolve(place2);
|
|
299
|
+
this.requireRead(actual);
|
|
300
|
+
return this.rawInput.values(actual);
|
|
280
301
|
}
|
|
281
302
|
/** Returns declared read places (context, not consumed). */
|
|
282
303
|
readPlaces() {
|
|
@@ -303,9 +324,10 @@ var TransitionContext = class {
|
|
|
303
324
|
* @throws if place not declared as output.
|
|
304
325
|
*/
|
|
305
326
|
output(place2, ...values) {
|
|
306
|
-
this.
|
|
327
|
+
const actual = this.resolve(place2);
|
|
328
|
+
this.requireOutput(actual);
|
|
307
329
|
for (const value of values) {
|
|
308
|
-
this._rawOutput.add(
|
|
330
|
+
this._rawOutput.add(actual, value);
|
|
309
331
|
}
|
|
310
332
|
return this;
|
|
311
333
|
}
|
|
@@ -318,9 +340,10 @@ var TransitionContext = class {
|
|
|
318
340
|
* @throws if place not declared as output.
|
|
319
341
|
*/
|
|
320
342
|
outputToken(place2, ...tokens) {
|
|
321
|
-
this.
|
|
343
|
+
const actual = this.resolve(place2);
|
|
344
|
+
this.requireOutput(actual);
|
|
322
345
|
for (const token of tokens) {
|
|
323
|
-
this._rawOutput.addToken(
|
|
346
|
+
this._rawOutput.addToken(actual, token);
|
|
324
347
|
}
|
|
325
348
|
return this;
|
|
326
349
|
}
|
|
@@ -437,6 +460,7 @@ var TokenOutput = class {
|
|
|
437
460
|
|
|
438
461
|
// src/core/transition.ts
|
|
439
462
|
var TRANSITION_KEY = /* @__PURE__ */ Symbol("Transition.internal");
|
|
463
|
+
var EMPTY_PLACE_ALIAS = /* @__PURE__ */ new Map();
|
|
440
464
|
var Transition = class {
|
|
441
465
|
name;
|
|
442
466
|
inputSpecs;
|
|
@@ -448,11 +472,23 @@ var Transition = class {
|
|
|
448
472
|
actionTimeout;
|
|
449
473
|
action;
|
|
450
474
|
priority;
|
|
475
|
+
/**
|
|
476
|
+
* Per-transition **declared → actual** place correspondence (per
|
|
477
|
+
* **MOD-031**), keyed by the author-original declared place **name** →
|
|
478
|
+
* actual composed place. Empty for a hand-written or directly-composed
|
|
479
|
+
* ([MOD-025]) transition (identity). Populated by the subnet rewriter after
|
|
480
|
+
* instantiation ([MOD-010]) / port binding ([MOD-020]) so an action that
|
|
481
|
+
* hardcodes a declared place constant resolves to the composed place via
|
|
482
|
+
* {@link import('./transition-context.js').TransitionContext}. Consumed only
|
|
483
|
+
* by the action-facing context I/O — never by enablement, firing, the
|
|
484
|
+
* verifier, the exporter, or events (so [MOD-023] is unaffected).
|
|
485
|
+
*/
|
|
486
|
+
placeAlias;
|
|
451
487
|
_inputPlaces;
|
|
452
488
|
_readPlaces;
|
|
453
489
|
_outputPlaces;
|
|
454
490
|
/** @internal Use {@link Transition.builder} to create instances. */
|
|
455
|
-
constructor(key, name, inputSpecs, outputSpec, inhibitors, reads, resets, timing, action, priority) {
|
|
491
|
+
constructor(key, name, inputSpecs, outputSpec, inhibitors, reads, resets, timing, action, priority, placeAlias = EMPTY_PLACE_ALIAS) {
|
|
456
492
|
if (key !== TRANSITION_KEY) throw new Error("Use Transition.builder() to create instances");
|
|
457
493
|
this.name = name;
|
|
458
494
|
this.inputSpecs = inputSpecs;
|
|
@@ -464,6 +500,7 @@ var Transition = class {
|
|
|
464
500
|
this.actionTimeout = findTimeout(outputSpec);
|
|
465
501
|
this.action = action;
|
|
466
502
|
this.priority = priority;
|
|
503
|
+
this.placeAlias = placeAlias.size === 0 ? EMPTY_PLACE_ALIAS : placeAlias;
|
|
467
504
|
const inputPlaces = /* @__PURE__ */ new Set();
|
|
468
505
|
for (const spec of inputSpecs) {
|
|
469
506
|
inputPlaces.add(spec.place);
|
|
@@ -515,6 +552,7 @@ var TransitionBuilder = class {
|
|
|
515
552
|
_timing = immediate();
|
|
516
553
|
_action = passthrough();
|
|
517
554
|
_priority = 0;
|
|
555
|
+
_placeAlias = EMPTY_PLACE_ALIAS;
|
|
518
556
|
constructor(name) {
|
|
519
557
|
this._name = name;
|
|
520
558
|
}
|
|
@@ -579,6 +617,16 @@ var TransitionBuilder = class {
|
|
|
579
617
|
this._priority = priority;
|
|
580
618
|
return this;
|
|
581
619
|
}
|
|
620
|
+
/**
|
|
621
|
+
* Sets the per-transition declared→actual place correspondence (per
|
|
622
|
+
* **MOD-031**). Populated by the subnet rewriter during the compose-time
|
|
623
|
+
* rewrite; not normally called by hand-written nets, whose correspondence is
|
|
624
|
+
* the identity (empty map).
|
|
625
|
+
*/
|
|
626
|
+
placeAlias(alias) {
|
|
627
|
+
this._placeAlias = alias;
|
|
628
|
+
return this;
|
|
629
|
+
}
|
|
582
630
|
build() {
|
|
583
631
|
if (this._outputSpec !== null) {
|
|
584
632
|
const inputPlaceNames = new Set(this._inputSpecs.map((s) => s.place.name));
|
|
@@ -600,7 +648,8 @@ var TransitionBuilder = class {
|
|
|
600
648
|
[...this._resets],
|
|
601
649
|
this._timing,
|
|
602
650
|
this._action,
|
|
603
|
-
this._priority
|
|
651
|
+
this._priority,
|
|
652
|
+
this._placeAlias
|
|
604
653
|
);
|
|
605
654
|
}
|
|
606
655
|
};
|
|
@@ -895,6 +944,10 @@ function substitutePlaces(t, remap) {
|
|
|
895
944
|
}
|
|
896
945
|
function rebuildWithName(t, name, remap) {
|
|
897
946
|
const builder = Transition.builder(name).timing(t.timing).priority(t.priority).action(t.action);
|
|
947
|
+
const alias = buildPlaceAlias(t, remap);
|
|
948
|
+
if (alias.size > 0) {
|
|
949
|
+
builder.placeAlias(alias);
|
|
950
|
+
}
|
|
898
951
|
if (t.inputSpecs.length > 0) {
|
|
899
952
|
const rewrittenInputs = new Array(t.inputSpecs.length);
|
|
900
953
|
for (let i = 0; i < t.inputSpecs.length; i++) {
|
|
@@ -916,6 +969,39 @@ function rebuildWithName(t, name, remap) {
|
|
|
916
969
|
}
|
|
917
970
|
return builder.build();
|
|
918
971
|
}
|
|
972
|
+
function buildPlaceAlias(t, remap) {
|
|
973
|
+
const prev = t.placeAlias;
|
|
974
|
+
if (remap.size === 0 && prev.size === 0) {
|
|
975
|
+
return EMPTY_ALIAS2;
|
|
976
|
+
}
|
|
977
|
+
const alias = /* @__PURE__ */ new Map();
|
|
978
|
+
if (prev.size > 0) {
|
|
979
|
+
for (const [declaredName, prevActual] of prev) {
|
|
980
|
+
const replaced = remap.get(prevActual.name);
|
|
981
|
+
const finalActual = replaced !== void 0 ? replaced : prevActual;
|
|
982
|
+
if (finalActual.name !== declaredName) {
|
|
983
|
+
alias.set(declaredName, finalActual);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
return alias;
|
|
987
|
+
}
|
|
988
|
+
const record = (p) => {
|
|
989
|
+
if (alias.has(p.name)) return;
|
|
990
|
+
const replaced = remap.get(p.name);
|
|
991
|
+
if (replaced !== void 0 && replaced.name !== p.name) {
|
|
992
|
+
alias.set(p.name, replaced);
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
for (const spec of t.inputSpecs) record(spec.place);
|
|
996
|
+
for (const rd of t.reads) record(rd.place);
|
|
997
|
+
for (const inh of t.inhibitors) record(inh.place);
|
|
998
|
+
for (const rs of t.resets) record(rs.place);
|
|
999
|
+
if (t.outputSpec !== null) {
|
|
1000
|
+
for (const p of allPlaces(t.outputSpec)) record(p);
|
|
1001
|
+
}
|
|
1002
|
+
return alias;
|
|
1003
|
+
}
|
|
1004
|
+
var EMPTY_ALIAS2 = /* @__PURE__ */ new Map();
|
|
919
1005
|
function rewriteIn(spec, remap) {
|
|
920
1006
|
switch (spec.type) {
|
|
921
1007
|
case "one":
|
|
@@ -2529,6 +2615,7 @@ var OutViolationError = class extends Error {
|
|
|
2529
2615
|
};
|
|
2530
2616
|
|
|
2531
2617
|
// src/runtime/executor-support.ts
|
|
2618
|
+
var DEADLINE_TOLERANCE_MS = 5;
|
|
2532
2619
|
function validateOutSpec(tName, spec, producedPlaceNames) {
|
|
2533
2620
|
switch (spec.type) {
|
|
2534
2621
|
case "place":
|
|
@@ -2589,7 +2676,6 @@ function produceTimeoutOutput(context, timeoutChild) {
|
|
|
2589
2676
|
}
|
|
2590
2677
|
|
|
2591
2678
|
// src/runtime/bitmap-net-executor.ts
|
|
2592
|
-
var DEADLINE_TOLERANCE_MS = 5;
|
|
2593
2679
|
var BitmapNetExecutor = class {
|
|
2594
2680
|
compiled;
|
|
2595
2681
|
marking;
|
|
@@ -2614,6 +2700,10 @@ var BitmapNetExecutor = class {
|
|
|
2614
2700
|
enabledFlags;
|
|
2615
2701
|
/** Precomputed: 1 if transition has a finite deadline, 0 otherwise. */
|
|
2616
2702
|
hasDeadlineFlags;
|
|
2703
|
+
/** Precomputed: 1 for exact() transitions — enforced softly, never force-disabled (TIME-006). */
|
|
2704
|
+
isExactFlags;
|
|
2705
|
+
/** Grace band (ms) before a hard deadline force-disables (TIME-013). */
|
|
2706
|
+
deadlineToleranceMs;
|
|
2617
2707
|
enabledTransitionCount = 0;
|
|
2618
2708
|
// In-flight tracking
|
|
2619
2709
|
inFlight = /* @__PURE__ */ new Map();
|
|
@@ -2641,6 +2731,10 @@ var BitmapNetExecutor = class {
|
|
|
2641
2731
|
);
|
|
2642
2732
|
this.hasEnvironmentPlaces = this.environmentPlaces.size > 0;
|
|
2643
2733
|
this.executionContextProvider = options.executionContextProvider;
|
|
2734
|
+
this.deadlineToleranceMs = options.deadlineToleranceMs ?? DEADLINE_TOLERANCE_MS;
|
|
2735
|
+
if (this.deadlineToleranceMs < 0) {
|
|
2736
|
+
throw new Error(`Deadline tolerance must be non-negative: ${this.deadlineToleranceMs}`);
|
|
2737
|
+
}
|
|
2644
2738
|
this.startMs = performance.now();
|
|
2645
2739
|
const wordCount = this.compiled.wordCount;
|
|
2646
2740
|
this.markedPlaces = new Uint32Array(wordCount);
|
|
@@ -2654,6 +2748,7 @@ var BitmapNetExecutor = class {
|
|
|
2654
2748
|
this.inFlightFlags = new Uint8Array(this.compiled.transitionCount);
|
|
2655
2749
|
this.enabledFlags = new Uint8Array(this.compiled.transitionCount);
|
|
2656
2750
|
this.hasDeadlineFlags = new Uint8Array(this.compiled.transitionCount);
|
|
2751
|
+
this.isExactFlags = new Uint8Array(this.compiled.transitionCount);
|
|
2657
2752
|
let anyDeadlines = false;
|
|
2658
2753
|
let allImm = true;
|
|
2659
2754
|
let samePrio = true;
|
|
@@ -2664,6 +2759,7 @@ var BitmapNetExecutor = class {
|
|
|
2664
2759
|
this.hasDeadlineFlags[tid] = 1;
|
|
2665
2760
|
anyDeadlines = true;
|
|
2666
2761
|
}
|
|
2762
|
+
if (t.timing.type === "exact") this.isExactFlags[tid] = 1;
|
|
2667
2763
|
if (t.timing.type !== "immediate") allImm = false;
|
|
2668
2764
|
if (t.priority !== firstPriority) samePrio = false;
|
|
2669
2765
|
}
|
|
@@ -2843,11 +2939,12 @@ var BitmapNetExecutor = class {
|
|
|
2843
2939
|
enforceDeadlines(nowMs) {
|
|
2844
2940
|
for (let tid = 0; tid < this.compiled.transitionCount; tid++) {
|
|
2845
2941
|
if (!this.hasDeadlineFlags[tid]) continue;
|
|
2942
|
+
if (this.isExactFlags[tid]) continue;
|
|
2846
2943
|
if (!this.enabledFlags[tid] || this.inFlightFlags[tid]) continue;
|
|
2847
2944
|
const t = this.compiled.transition(tid);
|
|
2848
2945
|
const elapsed = nowMs - this.enabledAtMs[tid];
|
|
2849
2946
|
const latestMs = latest(t.timing);
|
|
2850
|
-
if (elapsed > latestMs +
|
|
2947
|
+
if (elapsed > latestMs + this.deadlineToleranceMs) {
|
|
2851
2948
|
this.enabledFlags[tid] = 0;
|
|
2852
2949
|
this.enabledTransitionCount--;
|
|
2853
2950
|
this.emitEvent({
|
|
@@ -3033,7 +3130,8 @@ var BitmapNetExecutor = class {
|
|
|
3033
3130
|
t.readPlaces(),
|
|
3034
3131
|
t.outputPlaces(),
|
|
3035
3132
|
execCtx,
|
|
3036
|
-
logFn
|
|
3133
|
+
logFn,
|
|
3134
|
+
t.placeAlias
|
|
3037
3135
|
);
|
|
3038
3136
|
let actionPromise = t.action(context);
|
|
3039
3137
|
if (t.hasActionTimeout()) {
|
|
@@ -3364,6 +3462,12 @@ var PrecompiledNet = class _PrecompiledNet {
|
|
|
3364
3462
|
earliestMs;
|
|
3365
3463
|
latestMs;
|
|
3366
3464
|
hasDeadline;
|
|
3465
|
+
/**
|
|
3466
|
+
* 1 for `exact()` transitions. Exact transitions fire at the first opportunity at/after their
|
|
3467
|
+
* target time (delayed-style liveness) and are never force-disabled by deadline enforcement —
|
|
3468
|
+
* their upper bound is observed, not enforced. See TIME-006.
|
|
3469
|
+
*/
|
|
3470
|
+
isExact;
|
|
3367
3471
|
// ==================== Priority (CONC-023) ====================
|
|
3368
3472
|
priorities;
|
|
3369
3473
|
transitionToPriorityIndex;
|
|
@@ -3484,6 +3588,7 @@ var PrecompiledNet = class _PrecompiledNet {
|
|
|
3484
3588
|
this.earliestMs = new Float64Array(tc);
|
|
3485
3589
|
this.latestMs = new Float64Array(tc);
|
|
3486
3590
|
this.hasDeadline = new Uint8Array(tc);
|
|
3591
|
+
this.isExact = new Uint8Array(tc);
|
|
3487
3592
|
let anyDeadlines = false;
|
|
3488
3593
|
let allImm = true;
|
|
3489
3594
|
for (let tid = 0; tid < tc; tid++) {
|
|
@@ -3494,6 +3599,7 @@ var PrecompiledNet = class _PrecompiledNet {
|
|
|
3494
3599
|
this.hasDeadline[tid] = 1;
|
|
3495
3600
|
anyDeadlines = true;
|
|
3496
3601
|
}
|
|
3602
|
+
if (t.timing.type === "exact") this.isExact[tid] = 1;
|
|
3497
3603
|
if (t.timing.type !== "immediate") allImm = false;
|
|
3498
3604
|
}
|
|
3499
3605
|
this.anyDeadlines = anyDeadlines;
|
|
@@ -3661,7 +3767,6 @@ function simpleOutputPlace(spec, compiled) {
|
|
|
3661
3767
|
}
|
|
3662
3768
|
|
|
3663
3769
|
// src/runtime/precompiled-net-executor.ts
|
|
3664
|
-
var DEADLINE_TOLERANCE_MS2 = 5;
|
|
3665
3770
|
var PrecompiledNetExecutor = class {
|
|
3666
3771
|
program;
|
|
3667
3772
|
eventStore;
|
|
@@ -3669,6 +3774,7 @@ var PrecompiledNetExecutor = class {
|
|
|
3669
3774
|
hasEnvironmentPlaces;
|
|
3670
3775
|
executionContextProvider;
|
|
3671
3776
|
skipOutputValidation;
|
|
3777
|
+
deadlineToleranceMs;
|
|
3672
3778
|
startMs;
|
|
3673
3779
|
eventStoreEnabled;
|
|
3674
3780
|
// ==================== Token Storage ====================
|
|
@@ -3722,6 +3828,10 @@ var PrecompiledNetExecutor = class {
|
|
|
3722
3828
|
this.hasEnvironmentPlaces = this.environmentPlaces.size > 0;
|
|
3723
3829
|
this.executionContextProvider = options.executionContextProvider;
|
|
3724
3830
|
this.skipOutputValidation = options.skipOutputValidation ?? false;
|
|
3831
|
+
this.deadlineToleranceMs = options.deadlineToleranceMs ?? DEADLINE_TOLERANCE_MS;
|
|
3832
|
+
if (this.deadlineToleranceMs < 0) {
|
|
3833
|
+
throw new Error(`Deadline tolerance must be non-negative: ${this.deadlineToleranceMs}`);
|
|
3834
|
+
}
|
|
3725
3835
|
this.startMs = performance.now();
|
|
3726
3836
|
this.eventStoreEnabled = this.eventStore.isEnabled();
|
|
3727
3837
|
const prog = this.program;
|
|
@@ -3936,10 +4046,11 @@ var PrecompiledNetExecutor = class {
|
|
|
3936
4046
|
const tc = prog.transitionCount;
|
|
3937
4047
|
for (let tid = 0; tid < tc; tid++) {
|
|
3938
4048
|
if (!prog.hasDeadline[tid]) continue;
|
|
4049
|
+
if (prog.isExact[tid]) continue;
|
|
3939
4050
|
if (!this.enabledFlags[tid] || this.inFlightFlags[tid]) continue;
|
|
3940
4051
|
const elapsed = nowMs - this.enabledAtMs[tid];
|
|
3941
4052
|
const latestMs = prog.latestMs[tid];
|
|
3942
|
-
if (elapsed > latestMs +
|
|
4053
|
+
if (elapsed > latestMs + this.deadlineToleranceMs) {
|
|
3943
4054
|
this.enabledFlags[tid] = 0;
|
|
3944
4055
|
this.enabledTransitionCount--;
|
|
3945
4056
|
this.enabledAtMs[tid] = -Infinity;
|
|
@@ -4191,7 +4302,8 @@ var PrecompiledNetExecutor = class {
|
|
|
4191
4302
|
t.readPlaces(),
|
|
4192
4303
|
t.outputPlaces(),
|
|
4193
4304
|
execCtx,
|
|
4194
|
-
logFn
|
|
4305
|
+
logFn,
|
|
4306
|
+
t.placeAlias
|
|
4195
4307
|
);
|
|
4196
4308
|
let actionPromise = t.action(context);
|
|
4197
4309
|
if (t.hasActionTimeout()) {
|