diff --git a/.changeset/petrinaut-hir-compiler.md b/.changeset/petrinaut-hir-compiler.md new file mode 100644 index 00000000000..e05f5e338d3 --- /dev/null +++ b/.changeset/petrinaut-hir-compiler.md @@ -0,0 +1,10 @@ +--- +"@hashintel/petrinaut": patch +"@hashintel/petrinaut-core": minor +--- + +Compile all user code (dynamics, rates, kernels, metrics) through a new HIR +to programs reading the packed frame buffers directly, replacing Babel. + +Compatibility: code outside the supported TypeScript subset no longer runs — +it is rejected with an error diagnostic pointing at the offending syntax. diff --git a/libs/@hashintel/petrinaut-core/dependency-cruiser.tsconfig.json b/libs/@hashintel/petrinaut-core/dependency-cruiser.tsconfig.json new file mode 100644 index 00000000000..cbff533fc46 --- /dev/null +++ b/libs/@hashintel/petrinaut-core/dependency-cruiser.tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "baseUrl": "../../../..", + "paths": { + "@hashintel/petrinaut-core": [ + "libs/@hashintel/petrinaut-core/src/index.ts" + ], + "@hashintel/petrinaut-core/examples": [ + "libs/@hashintel/petrinaut-core/src/examples/index.ts" + ], + "@hashintel/petrinaut-core/hir": [ + "libs/@hashintel/petrinaut-core/src/hir.ts" + ], + "@hashintel/petrinaut-core/hir-runtime": [ + "libs/@hashintel/petrinaut-core/src/hir-runtime.ts" + ], + "@hashintel/petrinaut-core/workers/lsp": [ + "libs/@hashintel/petrinaut-core/src/workers/lsp.ts" + ], + "@hashintel/petrinaut-core/workers/monte-carlo": [ + "libs/@hashintel/petrinaut-core/src/workers/monte-carlo.ts" + ], + "@hashintel/petrinaut-core/workers/simulation": [ + "libs/@hashintel/petrinaut-core/src/workers/simulation.ts" + ] + } + }, + "include": ["src", "../petrinaut/src"] +} diff --git a/libs/@hashintel/petrinaut-core/docs/architecture/authoring.html b/libs/@hashintel/petrinaut-core/docs/architecture/authoring.html index 5d6d9d47e06..ae048fa3b0a 100644 --- a/libs/@hashintel/petrinaut-core/docs/architecture/authoring.html +++ b/libs/@hashintel/petrinaut-core/docs/architecture/authoring.html @@ -17,10 +17,9 @@

Compilation (Authoring)

- authoring/ — turns user-authored strings (TypeScript modules, - expressions, function bodies) into plain JS functions the engine can call. - Nothing here is a real security boundary: user code runs in the same - realm, hardened against accidents, not attackers. + The HIR pipeline turns user-authored TypeScript into checked, + source-spanned buffer programs. Scenario code retains a separate + same-realm compiler hardened against accidents, not attackers.

@@ -31,8 +30,8 @@

Compilation (Authoring)

Outputs
- Plain JS closures + typed results (InitialMarking for - scenarios, fn(state) for metrics) + Versioned HIR artifacts for runtime code; InitialMarking + for scenarios
Errors
@@ -42,17 +41,16 @@

Compilation (Authoring)

Runs on
- Worker (lambda/kernel/dynamics, at init) · Main thread - (scenario, quick-sim metrics) · MC worker (experiment metrics) + LSP worker (HIR compilation) · simulation workers (buffer programs) · + main thread (scenarios and timeline metric evaluation)

The compilation pipeline (module-style code)

- user-code/compile-user-code.ts handles the three engine - surfaces that are authored as modules (export default Wrapper(fn)): + Dynamics, lambdas, kernels, and metrics all compile through the HIR. The + first three are authored as export default Wrapper(fn) + modules; metrics are authored as function bodies.

@@ -65,34 +63,33 @@

The compilation pipeline (module-style code)

- Babel + Lower to HIR @babel/standalone strips type annotations (browser-safe, - no tsc)Parse the supported TypeScript subset with exact source spans
- Validate + Check + analyze Regex checks: has export default, uses the expected - wrapper name (Lambda / TransitionKernel / - Dynamics)Validate against places, token layouts, parameters, and output + shapes
- Assemble + Emit artifact Injects the Distribution runtime (unless disabled) + a - mock wrapper that just returns the inner fn; rewrites - export default to an assignmentGenerate buffer-native JS with offsets and strides baked in
- new Function(...)() - Same-realm plain JS closure, handed to the engine + Instantiate in runtime + Validate v4 fingerprint, then bind parameters, pool, and ABI + views
@@ -103,7 +100,8 @@

The compilation pipeline (module-style code)

this pipeline: they generate the Color_*, Parameters, Dynamics, TransitionKernel… declarations that Monaco checks against, so - editor diagnostics and runtime behaviour must be kept in sync by hand. + editor diagnostics and runtime artifacts are produced from the same HIR + checks and emitters.

What gets compiled, where it runs

@@ -121,46 +119,40 @@

What gets compiled, where it runs

Transition lambda module, Lambda(fn) - buildSimulationcompileUserCode + compileHirArtifacts in the LSP worker Worker, per enablement check - (input: {PlaceName: TokenRecord[]}, params) → boolean | - rate + (f64, u64, u8, placeBases, indices) → boolean | rate Transition kernel module, TransitionKernel(fn) - buildSimulation + compileHirArtifacts in the LSP worker Worker, per firing - (input, params) → {OutputPlace: token[]} — values may - be Distribution objects, sampled later by the engine + (views, placeBases, indices, outputViews, sink) → void Dynamics module, Dynamics(fn) - buildSimulation (only for colours with a real element) + compileHirArtifacts (colours with a real element) Worker, per step per place - (tokens: TokenRecord[], params) → derivative[] (real - elements only; others zeroed) + (placeBytes, tokenCount) → Float64Array Metric plain function body (no module) - authoring/metric/compile-metric.ts + compileHirArtifacts in the LSP worker Main thread (timeline) · MC worker (experiments) (state: {places: {[name]: {count, tokens}}}) → finite - number(f64, u64, u8, placeCounts, placeOffsets) → finite number — NaN/∞ throw @@ -230,19 +222,16 @@

code mode

Metric compilation and evaluation

- compileMetric(metric) + compileHirArtifacts Wraps the body in new Function("state", body) with - shadowed globals; validates the result is a finite number.Lower, typecheck, and emit a buffer-native metric program.
- buildMetricState(reader, places, types) + createHirMetricEvaluator Reshapes a SimulationFrameReader into - state.places[name] = {count, tokens} (keyed by place - name, tokens decoded).Bind referenced place ordinals and the per-run string pool.
@@ -256,10 +245,10 @@

Metric compilation and evaluation

-

Sandboxing (authoring/sandbox.ts)

+

Scenario sandboxing (authoring/sandbox.ts)