@typecad/cuttlefish 1.0.0-alpha.6 → 1.0.0-alpha.8

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.
Files changed (187) hide show
  1. package/dist/api/config.d.ts +32 -0
  2. package/dist/api/index.d.ts +1 -1
  3. package/dist/api/schema/types.d.ts +15 -0
  4. package/dist/api/shared/async-runtime-static.d.ts +12 -1
  5. package/dist/api/shared/async-runtime-static.js +69 -24
  6. package/dist/api/shared/async-symbol-detector.d.ts +11 -0
  7. package/dist/api/shared/async-symbol-detector.js +140 -0
  8. package/dist/api/shared/async-types.d.ts +24 -0
  9. package/dist/api/shared/coop-scheduler.d.ts +60 -0
  10. package/dist/api/shared/coop-scheduler.js +149 -0
  11. package/dist/api/shared/display-adapter.d.ts +4 -3
  12. package/dist/api/shared/display-adapter.js +15 -118
  13. package/dist/api/shared/display-adapters/sdl.js +38 -31
  14. package/dist/api/shared/display-profile.d.ts +47 -25
  15. package/dist/api/shared/display-profile.js +31 -164
  16. package/dist/api/shared/framework-manifest-registry.d.ts +9 -0
  17. package/dist/api/shared/framework-manifest-registry.js +27 -0
  18. package/dist/api/shared/framework-manifest.d.ts +581 -0
  19. package/dist/api/shared/framework-manifest.js +182 -0
  20. package/dist/api/shared/glcdfont.d.ts +12 -0
  21. package/dist/api/shared/glcdfont.js +124 -0
  22. package/dist/api/shared/graphics-strategy.d.ts +37 -0
  23. package/dist/api/shared/hal-op-ir.d.ts +755 -1
  24. package/dist/api/shared/hal-op-ir.js +129 -1
  25. package/dist/api/shared/index.d.ts +20 -2
  26. package/dist/api/shared/index.js +25 -1
  27. package/dist/api/shared/ir-core.d.ts +4 -0
  28. package/dist/api/shared/ir-declarations.d.ts +6 -0
  29. package/dist/api/shared/native-display-op-resolver.d.ts +10 -0
  30. package/dist/api/shared/native-display-op-resolver.js +64 -0
  31. package/dist/api/shared/platform-strategy.d.ts +113 -2
  32. package/dist/api/shared/polyfill-helper-registry.js +18 -1
  33. package/dist/api/shared/promise-runtime.d.ts +1 -1
  34. package/dist/api/shared/promise-runtime.js +95 -13
  35. package/dist/api/shared/toolchain-types.d.ts +17 -0
  36. package/dist/api/shared/validate-framework-manifest.d.ts +28 -0
  37. package/dist/api/shared/validate-framework-manifest.js +494 -0
  38. package/dist/api/shared/worker-runtime-polyfill.d.ts +22 -0
  39. package/dist/api/shared/worker-runtime-polyfill.js +34 -0
  40. package/dist/api/shared/worker-runtime.d.ts +69 -0
  41. package/dist/api/shared/worker-runtime.js +163 -0
  42. package/dist/cli.js +186 -82
  43. package/dist/config-loader.d.ts +7 -2
  44. package/dist/config-loader.js +23 -3
  45. package/dist/config-schema.d.ts +112 -70
  46. package/dist/config-schema.js +14 -0
  47. package/dist/contract/board-generator.d.ts +17 -0
  48. package/dist/contract/board-generator.js +57 -0
  49. package/dist/contract/contract-parser.d.ts +217 -0
  50. package/dist/contract/contract-parser.js +224 -0
  51. package/dist/contract/index.d.ts +22 -0
  52. package/dist/contract/index.js +68 -0
  53. package/dist/create/board-codegen.js +4 -4
  54. package/dist/create/board-generators.js +4 -5
  55. package/dist/create/board-spec.d.ts +72 -75
  56. package/dist/create/board-spec.js +0 -1
  57. package/dist/create/init-scaffold.d.ts +9 -2
  58. package/dist/create/init-scaffold.js +0 -14
  59. package/dist/create/init-templates.d.ts +2 -0
  60. package/dist/create/init-templates.js +74 -8
  61. package/dist/create/init-wizard.js +31 -7
  62. package/dist/debug/preprocessor.js +178 -39
  63. package/dist/debug/types.d.ts +23 -0
  64. package/dist/diagnostics/mermaid-builder.d.ts +1 -1
  65. package/dist/diagnostics/mermaid-builder.js +34 -24
  66. package/dist/emit/compliance/arxml-writer.d.ts +11 -0
  67. package/dist/emit/compliance/arxml-writer.js +34 -0
  68. package/dist/emit/compliance/compliance-context.d.ts +57 -0
  69. package/dist/emit/compliance/compliance-context.js +113 -0
  70. package/dist/emit/compliance/deviation-ledger.d.ts +27 -0
  71. package/dist/emit/compliance/deviation-ledger.js +47 -0
  72. package/dist/emit/compliance/deviation-writer.d.ts +30 -0
  73. package/dist/emit/compliance/deviation-writer.js +37 -0
  74. package/dist/emit/compliance/index.d.ts +7 -0
  75. package/dist/emit/compliance/index.js +6 -0
  76. package/dist/emit/compliance/rule-engine.d.ts +13 -0
  77. package/dist/emit/compliance/rule-engine.js +101 -0
  78. package/dist/emit/compliance/rules.d.ts +16 -0
  79. package/dist/emit/compliance/rules.js +191 -0
  80. package/dist/emit/compliance/types.d.ts +59 -0
  81. package/dist/emit/compliance/types.js +8 -0
  82. package/dist/emit/cpp-emitter.js +4 -3
  83. package/dist/emit/emitters/class-emitter.js +6 -1
  84. package/dist/emit/emitters/emitter-context.d.ts +28 -1
  85. package/dist/emit/emitters/function-emitter-impl.js +153 -53
  86. package/dist/emit/emitters/line-appender.js +19 -0
  87. package/dist/emit/emitters/line-marker.d.ts +38 -0
  88. package/dist/emit/emitters/line-marker.js +39 -0
  89. package/dist/emit/emitters/output-finalizer.d.ts +6 -0
  90. package/dist/emit/emitters/output-finalizer.js +101 -12
  91. package/dist/emit/emitters/setup.d.ts +17 -0
  92. package/dist/emit/emitters/setup.js +257 -36
  93. package/dist/emit/emitters/top-level-prep.js +8 -0
  94. package/dist/emit/emitters/type-decl-emitter.js +28 -3
  95. package/dist/emit/emitters/ui-emitter.js +33 -9
  96. package/dist/emit/expression-renderer.d.ts +1 -1
  97. package/dist/emit/expression-renderer.js +91 -6
  98. package/dist/emit/route-hal-op.js +18 -5
  99. package/dist/emit/snprintf-helpers.js +15 -4
  100. package/dist/emit/statement-renderer.d.ts +10 -0
  101. package/dist/emit/statement-renderer.js +34 -5
  102. package/dist/emit/utils/async-state-machine.js +221 -125
  103. package/dist/emit/utils/hal-op-cpp-type.d.ts +6 -0
  104. package/dist/emit/utils/hal-op-cpp-type.js +40 -0
  105. package/dist/framework-package.js +2 -0
  106. package/dist/framework-registry.d.ts +17 -0
  107. package/dist/ir/adc-range-validation.js +14 -1
  108. package/dist/ir/build-ir-state.d.ts +1 -0
  109. package/dist/ir/build-ir-state.js +14 -0
  110. package/dist/ir/build-ir.js +9 -5
  111. package/dist/ir/call-graph.js +16 -0
  112. package/dist/ir/expression-to-ir.js +164 -0
  113. package/dist/ir/feature-registry.js +7 -25
  114. package/dist/ir/function-builder.js +22 -0
  115. package/dist/ir/hal/hal-emitter.d.ts +5 -2
  116. package/dist/ir/hal/hal-emitter.js +50 -18
  117. package/dist/ir/hal/hal-parser.d.ts +6 -0
  118. package/dist/ir/hal/hal-parser.js +81 -0
  119. package/dist/ir/hal/hal-plugins.js +723 -1
  120. package/dist/ir/identifier-collector.js +35 -0
  121. package/dist/ir/interrupt-analysis.d.ts +5 -1
  122. package/dist/ir/interrupt-analysis.js +8 -16
  123. package/dist/ir/network-validation.d.ts +4 -0
  124. package/dist/ir/network-validation.js +184 -0
  125. package/dist/ir/ownership-analysis.js +20 -1
  126. package/dist/ir/pin-capability-validation.js +37 -0
  127. package/dist/ir/pin-mode-validation.d.ts +2 -2
  128. package/dist/ir/pin-mode-validation.js +49 -18
  129. package/dist/ir/program-analysis.d.ts +65 -0
  130. package/dist/ir/program-analysis.js +318 -2
  131. package/dist/ir/render-expr.js +11 -0
  132. package/dist/ir/timing-validation.d.ts +6 -1
  133. package/dist/ir/timing-validation.js +60 -13
  134. package/dist/ir/transformers/call-statement.js +105 -0
  135. package/dist/ir/transformers/expressions.js +62 -0
  136. package/dist/ir/transformers/hal-call-resolver.js +21 -0
  137. package/dist/ir/transformers/hal-emit-helpers.js +1 -1
  138. package/dist/ir/transformers/namespace-methods.js +17 -12
  139. package/dist/ir/transformers/ui-reactive.js +2 -2
  140. package/dist/ir/transformers/variables.js +92 -3
  141. package/dist/ir/type-resolution.js +18 -0
  142. package/dist/ir/ui-element-auto-wire.js +7 -5
  143. package/dist/ir/utils/map-statements.d.ts +4 -0
  144. package/dist/ir/utils/map-statements.js +79 -0
  145. package/dist/ir/validation-orchestrator.js +9 -2
  146. package/dist/ir/worker-analysis.d.ts +10 -0
  147. package/dist/ir/worker-analysis.js +261 -0
  148. package/dist/libdef/c-to-decl.d.ts +27 -0
  149. package/dist/libdef/c-to-decl.js +397 -0
  150. package/dist/libdef/component-decls.d.ts +2 -0
  151. package/dist/libdef/component-decls.js +6 -0
  152. package/dist/libdef/component-discovery.d.ts +43 -0
  153. package/dist/libdef/component-discovery.js +83 -0
  154. package/dist/libdef/cpp-to-decl.d.ts +9 -0
  155. package/dist/libdef/cpp-to-decl.js +72 -0
  156. package/dist/libdef/registry.js +5 -2
  157. package/dist/lint-cache.d.ts +59 -0
  158. package/dist/lint-cache.js +257 -0
  159. package/dist/orchestrator/graph-builder.js +14 -9
  160. package/dist/platform/coop-scheduler-runtime.d.ts +19 -0
  161. package/dist/platform/coop-scheduler-runtime.js +41 -0
  162. package/dist/platform/generic-strategy.d.ts +15 -3
  163. package/dist/platform/generic-strategy.js +49 -4
  164. package/dist/safety/safety-bridge.d.ts +11 -0
  165. package/dist/safety/safety-bridge.js +48 -0
  166. package/dist/safety/sidecar-bridge.d.ts +5 -0
  167. package/dist/safety/sidecar-bridge.js +22 -0
  168. package/dist/safety-hook.d.ts +79 -0
  169. package/dist/safety-hook.js +35 -0
  170. package/dist/testing.d.ts +7 -1
  171. package/dist/testing.js +8 -1
  172. package/dist/transpile.d.ts +3 -0
  173. package/dist/transpile.js +175 -41
  174. package/dist/types.d.ts +13 -2
  175. package/dist/ui-hook.d.ts +17 -3
  176. package/dist/utils/cli.js +78 -4
  177. package/dist/utils/fs.d.ts +13 -0
  178. package/dist/utils/fs.js +50 -0
  179. package/package.json +24 -5
  180. package/dist/api/shared/display-adapters/eink-mono.d.ts +0 -2
  181. package/dist/api/shared/display-adapters/eink-mono.js +0 -53
  182. package/dist/api/shared/display-adapters/ssd1309.d.ts +0 -2
  183. package/dist/api/shared/display-adapters/ssd1309.js +0 -136
  184. package/dist/api/shared/display-adapters/st7796.d.ts +0 -2
  185. package/dist/api/shared/display-adapters/st7796.js +0 -132
  186. package/dist/licenses.d.ts +0 -185
  187. package/dist/licenses.js +0 -963
@@ -0,0 +1,41 @@
1
+ import { generateCoopScheduler } from "../api/shared/index.js";
2
+ /**
3
+ * Build a RuntimePolyfillIR for the no-STL cooperative scheduler, when the
4
+ * program has async/timer work AND the strategy has opted into priority/time-
5
+ * budget scheduling via AsyncRuntimeConfig.
6
+ *
7
+ * The polyfill carries only the scheduler namespace + CoopSched_run() alias.
8
+ * Per-program work-unit registration + dispatch lines are emitted separately
9
+ * by each strategy's asyncLoopInjection() via buildCoopSchedInjection().
10
+ *
11
+ * Why a polyfill and not shimLines(): polyfills are dead-code-eliminated
12
+ * (filterPolyfillHelpers) and feature-gated centrally, matching how
13
+ * async_runtime / timer_methods are handled. The scheduler is STL-free, so it
14
+ * links on minimal-libc targets (Zephyr) where the std::function Promise
15
+ * runtime does not.
16
+ */
17
+ export function buildCoopSchedulerPolyfill(_program, config, currentTimeExpr = "millis()") {
18
+ if (!config.enablePriority && !config.enableTimeBudget)
19
+ return null;
20
+ return {
21
+ kind: "polyfill",
22
+ id: "coop_scheduler",
23
+ domain: "embedded",
24
+ // STL-free: only needs a 32-bit unsigned time source (millis() /
25
+ // k_uptime_get_32()) and fixed-width types, both available everywhere.
26
+ requiredIncludes: [],
27
+ forwardDeclarations: [],
28
+ helperStructs: [
29
+ generateCoopScheduler({
30
+ capacity: 8,
31
+ priorities: config.schedulerPriorities ?? 2,
32
+ enableTimeBudget: config.enableTimeBudget ?? false,
33
+ timeBudgetMs: config.timeBudgetMs ?? 5,
34
+ currentTimeExpr,
35
+ }),
36
+ ],
37
+ helperFunctions: [],
38
+ shimMacros: [],
39
+ dependencies: [],
40
+ };
41
+ }
@@ -17,7 +17,9 @@ export declare class GenericStrategy implements PlatformStrategy {
17
17
  overrideBaseName(originalBaseName: string, _outDirBaseName: string, _isEntryFile: boolean, _isNpmPackage: boolean): string;
18
18
  effectiveEmitMode(requestedMode: string, _isNpmPackage: boolean): string;
19
19
  normalizeCppType(typeName: string): string;
20
- defaultNumericType(): string;
20
+ defaultNumericType(compliance?: {
21
+ isBanned(ruleId: string): boolean;
22
+ }): string;
21
23
  mapReturnType(_functionName: string, returnType: string): string;
22
24
  isStringLikeType(cppType: string): boolean;
23
25
  isPointerType(cppType: string): boolean;
@@ -54,8 +56,8 @@ export declare class GenericStrategy implements PlatformStrategy {
54
56
  structFieldInitializer(_fieldValue: ExpressionIR, _compiletimeVarNames: Set<string>, _renderExpr: (e: ExpressionIR) => string): string | undefined;
55
57
  getAsyncRuntimeConfig(): AsyncRuntimeConfig;
56
58
  generateNativePolyfills(program: ProgramIR, ctx?: PlatformContext): RuntimePolyfillIR[];
57
- asyncLoopInjection(_taskVarNames: string[], config: AsyncRuntimeConfig): string[];
58
- asyncLoopInjection(_taskVarNames: string[], hasPromiseRuntime: boolean): string[];
59
+ asyncLoopInjection(taskVarNames: string[], config: AsyncRuntimeConfig): string[];
60
+ asyncLoopInjection(taskVarNames: string[], hasPromiseRuntime: boolean): string[];
59
61
  asyncDriverFunctionName(): string;
60
62
  shouldSkipTypeAlias(_cppType: string): boolean;
61
63
  emitDiagnostics(_emitMode: string): Diagnostic[];
@@ -68,6 +70,7 @@ export declare class GenericStrategy implements PlatformStrategy {
68
70
  close: string;
69
71
  } | undefined;
70
72
  getStdLibSupport(_architecture?: string): StdLibSupport;
73
+ debugMode(_target?: string): 'gdb' | 'printf';
71
74
  generateDebugInitCode(): string[];
72
75
  generateDebugBreakpointCode(params: {
73
76
  fileName: string;
@@ -98,4 +101,13 @@ export declare class GenericStrategy implements PlatformStrategy {
98
101
  supportedDisplayDrivers(): ReadonlySet<string>;
99
102
  colorFormat(): "rgb565" | "rgb666" | "rgb888" | "mono";
100
103
  graphicsCapacity(): GraphicsCapacity;
104
+ readDigitalPin(_pin: string): string;
105
+ readAnalogPin(_pin: string): string;
106
+ writeDigitalPin(_pin: string, _val: string): string;
107
+ setPinMode(_pin: string, _mode: string): string;
108
+ delayMs(_ms: string): string;
109
+ delayMicroseconds(_us: string): string;
110
+ halCallNames(): ReadonlySet<string>;
111
+ isHalCall(_name: string): boolean;
112
+ analogReadCallNames(): ReadonlySet<string>;
101
113
  }
@@ -42,10 +42,14 @@ export class GenericStrategy {
42
42
  // ── Type normalisation ──────────────────────────────────────────────────
43
43
  normalizeCppType(typeName) {
44
44
  if (typeName === "auto")
45
- return "int";
45
+ return this.defaultNumericType();
46
46
  return typeName;
47
47
  }
48
- defaultNumericType() { return "int"; }
48
+ defaultNumericType(compliance) {
49
+ // A3-9-1: fixed-width integers under AUTOSAR. Legacy 'int' spelling
50
+ // preserved when autosar is off so default output is byte-identical.
51
+ return compliance?.isBanned("A3-9-1") ? "int32_t" : "int";
52
+ }
49
53
  mapReturnType(_functionName, returnType) {
50
54
  return this.normalizeCppType(returnType);
51
55
  }
@@ -185,17 +189,23 @@ export class GenericStrategy {
185
189
  helpers.push(asyncRuntime);
186
190
  return helpers;
187
191
  }
188
- asyncLoopInjection(_taskVarNames, configOrBool) {
192
+ asyncLoopInjection(taskVarNames, configOrBool) {
189
193
  let hasPromiseRuntime;
190
- if (typeof configOrBool === 'boolean') {
194
+ if (typeof configOrBool === "boolean") {
191
195
  hasPromiseRuntime = configOrBool;
192
196
  }
193
197
  else {
194
198
  hasPromiseRuntime = configOrBool.hasPromiseRuntime;
195
199
  }
200
+ // Drive every async state-machine task once per driver-function iteration.
201
+ // Task globals auto-start on their first .run() (STATE_0 runs
202
+ // unconditionally); the state machine no-ops in its terminal/cyclic state.
196
203
  const lines = [];
197
204
  if (hasPromiseRuntime)
198
205
  lines.push(" cuttlefish_pump_microtasks();");
206
+ for (const n of taskVarNames) {
207
+ lines.push(` ${n}.run();`);
208
+ }
199
209
  return lines;
200
210
  }
201
211
  asyncDriverFunctionName() { return "main"; }
@@ -213,6 +223,9 @@ export class GenericStrategy {
213
223
  enumApiGuard(_enumName) { return undefined; }
214
224
  getStdLibSupport(_architecture) { return DEFAULT_STDLIB_SUPPORT; }
215
225
  // ── Debug code generation ─────────────────────────────────────────────────
226
+ debugMode(_target) {
227
+ return 'printf';
228
+ }
216
229
  generateDebugInitCode() {
217
230
  return [
218
231
  '// === DEBUG: Initialize ===',
@@ -286,4 +299,36 @@ export class GenericStrategy {
286
299
  nodeStorage: "flash",
287
300
  };
288
301
  }
302
+ // ── HAL (generic fallback) ──────────────────────────────────────────────
303
+ // The generic/host target has no GPIO or timing hardware. These return
304
+ // documented no-op stubs so emit stays deterministic rather than throwing
305
+ // mid-codegen. Host tests that exercise pin-polling paths use a mock
306
+ // PlatformStrategy (see tests/packages/cuttlefish/async-runtime-static.test.ts).
307
+ readDigitalPin(_pin) {
308
+ return "/* gpio unavailable on generic target */ 0";
309
+ }
310
+ readAnalogPin(_pin) {
311
+ return "/* adc unavailable on generic target */ 0";
312
+ }
313
+ writeDigitalPin(_pin, _val) {
314
+ return "/* gpio unavailable on generic target */";
315
+ }
316
+ setPinMode(_pin, _mode) {
317
+ return "/* gpio unavailable on generic target */";
318
+ }
319
+ delayMs(_ms) {
320
+ return "/* delay unavailable on generic target */";
321
+ }
322
+ delayMicroseconds(_us) {
323
+ return "/* delay unavailable on generic target */";
324
+ }
325
+ halCallNames() {
326
+ return new Set();
327
+ }
328
+ isHalCall(_name) {
329
+ return false;
330
+ }
331
+ analogReadCallNames() {
332
+ return new Set();
333
+ }
289
334
  }
@@ -0,0 +1,11 @@
1
+ /** Dynamically load @typecad/safety/engine and register the hook.
2
+ * Called by transpile.ts at the start of each transpile run.
3
+ * Safe to call when @typecad/safety is absent (hook stays null). */
4
+ export declare function loadSafetyEngine(): Promise<void>;
5
+ /** Reset the safety bridge: forget a load was attempted and clear the hook.
6
+ * Mirrors resetUIEngine() so each transpile run / test starts clean. */
7
+ export declare function resetSafetyEngine(): void;
8
+ /** Test-only: force the bridge into the "no @typecad/safety" state — mark the
9
+ * load as already attempted and leave the hook null, exactly as if the
10
+ * dynamic import had failed because the package is not installed. */
11
+ export declare function __simulateSafetyAbsentForTest(): void;
@@ -0,0 +1,48 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Safety bridge — loads the safety engine from @typecad/safety and registers it.
3
+ //
4
+ // transpile.ts calls loadSafetyEngine() at the start of transpileFile(). If
5
+ // @typecad/safety is not installed, the import fails gracefully and the hook
6
+ // stays null — cuttlefish works as a pure TS→C++ transpiler with no safety
7
+ // support.
8
+ // ---------------------------------------------------------------------------
9
+ import { setSafetyHook } from "../safety-hook.js";
10
+ let loaded = false;
11
+ /** Dynamically load @typecad/safety/engine and register the hook.
12
+ * Called by transpile.ts at the start of each transpile run.
13
+ * Safe to call when @typecad/safety is absent (hook stays null). */
14
+ export async function loadSafetyEngine() {
15
+ if (loaded)
16
+ return;
17
+ loaded = true;
18
+ try {
19
+ // Dynamic import — @typecad/safety is optional. The module specifier is
20
+ // routed through a variable (rather than a string literal) so tsc types
21
+ // the result as `any` and never resolves @typecad/safety's declaration
22
+ // files while type-checking this file. A literal specifier would make tsc
23
+ // load safety's dist/engine-index.d.ts, which imports back
24
+ // @typecad/cuttlefish/safety-hook-types — a self-referencing package path
25
+ // that resolves into this package's own dist/ output and causes TS5055
26
+ // ("would overwrite input file") on every rebuild where dist/ exists.
27
+ const safetyEnginePath = "@typecad/safety/engine";
28
+ const engine = await import(safetyEnginePath);
29
+ const hook = engine.registerSafetyEngine();
30
+ setSafetyHook(hook);
31
+ }
32
+ catch {
33
+ // @typecad/safety is not installed — cuttlefish works without safety.
34
+ }
35
+ }
36
+ /** Reset the safety bridge: forget a load was attempted and clear the hook.
37
+ * Mirrors resetUIEngine() so each transpile run / test starts clean. */
38
+ export function resetSafetyEngine() {
39
+ loaded = false;
40
+ setSafetyHook(null);
41
+ }
42
+ /** Test-only: force the bridge into the "no @typecad/safety" state — mark the
43
+ * load as already attempted and leave the hook null, exactly as if the
44
+ * dynamic import had failed because the package is not installed. */
45
+ export function __simulateSafetyAbsentForTest() {
46
+ loaded = true;
47
+ setSafetyHook(null);
48
+ }
@@ -0,0 +1,5 @@
1
+ import type { SafetyMetadata } from "../safety-hook.js";
2
+ /** Dynamically import the safety package's sidecar renderer.
3
+ * Uses a variable-held specifier so tsc doesn't try to resolve the
4
+ * @typecad/safety types at build time (avoids circular dependency). */
5
+ export declare function renderSafetySidecar(metadata: SafetyMetadata, toolVersion: string): Promise<string>;
@@ -0,0 +1,22 @@
1
+ /** Dynamically import the safety package's sidecar renderer.
2
+ * Uses a variable-held specifier so tsc doesn't try to resolve the
3
+ * @typecad/safety types at build time (avoids circular dependency). */
4
+ export async function renderSafetySidecar(metadata, toolVersion) {
5
+ const spec = "@typecad/safety/iso26262/sidecar-writer";
6
+ try {
7
+ const mod = await import(spec);
8
+ return mod.renderSafetySidecar(metadata, toolVersion);
9
+ }
10
+ catch {
11
+ // Fallback: inline the renderer so the sidecar is produced even if
12
+ // the subpath export isn't configured.
13
+ return JSON.stringify({
14
+ schemaVersion: "1.0.0",
15
+ standard: "ISO 26262 Part 6",
16
+ tool: "cuttlefish (@typecad/safety)",
17
+ toolVersion,
18
+ generatedAt: new Date().toISOString(),
19
+ safetyFunctions: metadata.functions,
20
+ }, null, 2);
21
+ }
22
+ }
@@ -0,0 +1,79 @@
1
+ import type { HALOpIR, ProgramIR, RuntimePolyfillIR, Diagnostic } from "./api/shared/index.js";
2
+ /** Context handed to transformIR. */
3
+ export interface SafetyTransformContext {
4
+ /** True iff the entry file imports `safe` from @typecad/safety. The pass
5
+ * uses this as a fast no-op guard. */
6
+ readonly safetyInUse: boolean;
7
+ /** Build target (e.g. "esp32", "avr"). Strategies still resolve the
8
+ * underlying pinMode/digitalRead symbols; the safety package is target-
9
+ * agnostic. */
10
+ readonly target: string;
11
+ }
12
+ /** Capabilities cuttlefish core needs from the safety engine.
13
+ *
14
+ * Part A uses transformIR + resolveSafetyOp + resolveSemanticCall.
15
+ * Part B (ISO 26262 Part 6 rules) adds analyzeIR; Part C (sidecar) will
16
+ * add collectSafetyMetadata. Both reuse this same seam with no new core
17
+ * machinery. */
18
+ export interface TranspilerSafetyHook {
19
+ /** Post-build IR transform. Must return a (possibly new) ProgramIR. Part A
20
+ * uses this to inject safety.record_pin_mode companions after every
21
+ * gpio.pin_mode / safety.pin_mode op. Called only when hasSafetyHook(). */
22
+ transformIR(program: ProgramIR, ctx: SafetyTransformContext): ProgramIR;
23
+ /** Resolve a safety.* HAL op to C++ code or expression. Called from the
24
+ * extended routeHALOp() for any op whose `operation` starts with "safety.".
25
+ * NEVER delegated to a per-target strategy. Returns undefined if the op
26
+ * is not recognized (caller emits an unhandled-op warning). */
27
+ resolveSafetyOp(op: HALOpIR): {
28
+ code?: string;
29
+ expression?: string;
30
+ } | undefined;
31
+ /** Lower a safe.* TS call to a HAL op. Called from an extension point in
32
+ * tryResolveSemanticCall (hal-plugins.ts) when the callee resolves to the
33
+ * @typecad/safety package. Returns undefined if not a safety call. */
34
+ resolveSemanticCall?(callee: string, args: readonly unknown[]): HALOpIR | undefined;
35
+ /** Provide safety runtime polyfills (mode table + voter). Called from
36
+ * buildEmitterContext so the polyfills participate in tree-shaking.
37
+ * Returns [] when safety is not in use. */
38
+ buildPolyfills?(): RuntimePolyfillIR[];
39
+ /** Part B: read-only ISO 26262 Part 6 software-rule analysis. Called
40
+ * after transformIR completes, on the final transformed IR. Returns
41
+ * diagnostics that flow into the build's diagnostic list. Diagnostics
42
+ * with severity "error" abort the build (via throwIfFatalDiagnostics);
43
+ * "warning"/"info" are logged but the build succeeds. */
44
+ analyzeIR?(program: ProgramIR, ctx: SafetyTransformContext): Diagnostic[];
45
+ /** Part C: collect safety metadata for sidecar artifact generation.
46
+ * Called after analyzeIR completes. Returns structured metadata about
47
+ * each safety-critical function (ASIL level, mechanisms, rule results)
48
+ * that the caller writes to a sidecar JSON file. */
49
+ collectSafetyMetadata?(program: ProgramIR, ctx: SafetyTransformContext): SafetyMetadata[];
50
+ }
51
+ /** Set the safety hook. Called by transpile.ts after dynamically loading
52
+ * @typecad/safety/engine. Passing null clears it. */
53
+ export declare function setSafetyHook(hook: TranspilerSafetyHook | null): void;
54
+ /** Get the current safety hook, or null if @typecad/safety is not loaded. */
55
+ export declare function getSafetyHook(): TranspilerSafetyHook | null;
56
+ /** Returns true if the safety hook is registered (i.e. @typecad/safety loaded). */
57
+ export declare function hasSafetyHook(): boolean;
58
+ /** Get the safety hook, throwing if it's not set. Use only inside
59
+ * `if (hasSafetyHook())` guards. */
60
+ export declare function requireSafetyHook(): TranspilerSafetyHook;
61
+ export type { Diagnostic };
62
+ /** Metadata about one safety-critical function, collected for Part C. */
63
+ export interface SafetyFunctionMetadata {
64
+ name: string;
65
+ asilLevel: string;
66
+ source?: {
67
+ tsFile: string;
68
+ tsLine: number;
69
+ };
70
+ mechanisms: string[];
71
+ rules: Record<string, "pass" | {
72
+ severity: string;
73
+ message: string;
74
+ }>;
75
+ }
76
+ /** Result of Part C's metadata collection. */
77
+ export interface SafetyMetadata {
78
+ functions: SafetyFunctionMetadata[];
79
+ }
@@ -0,0 +1,35 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Safety hook — the contract cuttlefish core uses to talk to the optional
3
+ // @typecad/safety package. Modeled on ui-hook.ts.
4
+ //
5
+ // @typecad/safety is an optional peer dependency. When it is installed and
6
+ // imported by a sketch, transpile.ts calls loadSafetyEngine() which dynamic-
7
+ // imports @typecad/safety/engine and calls registerSafetyEngine() to push an
8
+ // implementation of this interface into the registry. When absent, every
9
+ // hasSafetyHook() guard returns false and cuttlefish behaves as before.
10
+ // ---------------------------------------------------------------------------
11
+ // ── Module-level hook state ────────────────────────────────────────────────
12
+ let safetyHook = null;
13
+ /** Set the safety hook. Called by transpile.ts after dynamically loading
14
+ * @typecad/safety/engine. Passing null clears it. */
15
+ export function setSafetyHook(hook) {
16
+ safetyHook = hook;
17
+ }
18
+ /** Get the current safety hook, or null if @typecad/safety is not loaded. */
19
+ export function getSafetyHook() {
20
+ return safetyHook;
21
+ }
22
+ /** Returns true if the safety hook is registered (i.e. @typecad/safety loaded). */
23
+ export function hasSafetyHook() {
24
+ return safetyHook !== null;
25
+ }
26
+ /** Get the safety hook, throwing if it's not set. Use only inside
27
+ * `if (hasSafetyHook())` guards. */
28
+ export function requireSafetyHook() {
29
+ if (!safetyHook) {
30
+ throw new Error("Safety hook is not registered. This code path requires @typecad/safety " +
31
+ "to be installed and loaded. This should not happen — the hook is set " +
32
+ "at the start of transpileFile() when safety is detected.");
33
+ }
34
+ return safetyHook;
35
+ }
package/dist/testing.d.ts CHANGED
@@ -12,9 +12,13 @@ export { inferSnprintfArg, createEmissionScopeState, escapeCppStringLiteral } fr
12
12
  export { setLoadedFramework } from "./framework-registry.js";
13
13
  export { registerPlatformStrategy, resolveStrategy, clearAllProfileCaches } from "./platform/registry.js";
14
14
  export type { EmitMode, GeneratedOutputs, TargetProfile, PlatformContext } from "./types.js";
15
+ export { ComplianceContext, runSelfCheck, renderRegistryJson } from "./emit/compliance/index.js";
16
+ export type { ComplianceMode, SelfCheckFinding, Deviation } from "./emit/compliance/index.js";
15
17
  export { findConfigFile, parseConfigFile, loadCuttlefishConfig, generateVirtualTypeDeclaration, } from "./config-loader.js";
16
18
  export { transpileFile } from "./transpile.js";
17
19
  export { resetUIEngine, __simulateUIAbsentForTest } from "./ui/ui-bridge.js";
20
+ export { resetSafetyEngine, __simulateSafetyAbsentForTest } from "./safety/safety-bridge.js";
21
+ export { setSafetyHook, hasSafetyHook } from "./safety-hook.js";
18
22
  export { scaffoldProject, normalizeProjectName, KNOWN_BOARDS, generateProjectPackageJson, generateProjectTsconfig, generateProjectConfig, generateProjectEnvDts, generateStarterSketch, generateStarterTest, generateStarterSim, generateGitignore, generateEslintConfig, runInitWizard, } from "./create/index.js";
19
23
  export type { InitProjectOptions } from "./create/index.js";
20
24
  export { scaffoldBoardPackages, parseBoardSpec, safeParseBoardSpec, stripJsonc, } from "./create/index.js";
@@ -30,6 +34,8 @@ export { LINT_RULES, ESLINT_OPT_OUT_KINDS, kindRegistryEntries, } from "./ir/fea
30
34
  export type { LintRule, FeatureEntry, FeatureStatus, DiagnosticMatch } from "./ir/feature-registry.js";
31
35
  export { runEslintCheck } from "./eslint-check.js";
32
36
  export type { ESLintError } from "./eslint-check.js";
37
+ export { checkLintCache, recordLintSuccess, invalidateLint, computeLintFingerprint, resolveEslintConfigPath, } from "./lint-cache.js";
38
+ export type { LintFingerprint, GateCacheResult } from "./lint-cache.js";
33
39
  export { runSemanticGates } from "./orchestrator/type-checker.js";
34
40
  export { canonicalize, buildSemanticFacts, } from "./orchestrator/semantic-facts.js";
35
41
  export type { CanonicalType, SemanticFacts, FactStore, ValueCategory, Lifetime, Nullable, SemanticOrigin, AnalysisResult, BindingResolver, } from "./orchestrator/semantic-facts.js";
@@ -40,7 +46,7 @@ export { parseCommandLine } from "./utils/cli.js";
40
46
  export { parseHeader, stripPreprocessorBlocks } from "./libdef/header-parser.js";
41
47
  export { BaseClassResolver, buildClassIndex } from "./libdef/base-class-resolver.js";
42
48
  export type { ResolveResult } from "./libdef/base-class-resolver.js";
43
- export { generateDecl, generateDeclsForDirectory } from "./libdef/cpp-to-decl.js";
49
+ export { generateDecl, generateDeclsForDirectory, generateComponentDeclsForProject } from "./libdef/cpp-to-decl.js";
44
50
  export { renderExprAsText } from "./ir/render-expr.js";
45
51
  export { contextStorage, CompilationContext } from "./ir/build-ir-state.js";
46
52
  export type { ExpressionIR } from "./api/index.js";
package/dist/testing.js CHANGED
@@ -11,12 +11,17 @@ export { analyzePeripheralUsage, createEmptyPeripheralUsage } from "./ir/periphe
11
11
  export { inferSnprintfArg, createEmissionScopeState, escapeCppStringLiteral } from "./emit/snprintf-helpers.js";
12
12
  export { setLoadedFramework } from "./framework-registry.js";
13
13
  export { registerPlatformStrategy, resolveStrategy, clearAllProfileCaches } from "./platform/registry.js";
14
+ // ── AUTOSAR compliance module (test-visible) ───────────────────────────────
15
+ export { ComplianceContext, runSelfCheck, renderRegistryJson } from "./emit/compliance/index.js";
14
16
  // ── Config loader ───────────────────────────────────────────────────────────
15
17
  export { findConfigFile, parseConfigFile, loadCuttlefishConfig, generateVirtualTypeDeclaration, } from "./config-loader.js";
16
18
  // ── Transpiler internal API ─────────────────────────────────────────────────
17
19
  export { transpileFile } from "./transpile.js";
18
20
  // ── UI bridge (optional @typecad/ui) ─────────────────────────────────────────
19
21
  export { resetUIEngine, __simulateUIAbsentForTest } from "./ui/ui-bridge.js";
22
+ // ── Safety bridge (optional @typecad/safety) ────────────────────────────────
23
+ export { resetSafetyEngine, __simulateSafetyAbsentForTest } from "./safety/safety-bridge.js";
24
+ export { setSafetyHook, hasSafetyHook } from "./safety-hook.js";
20
25
  // ── Project scaffolding ──────────────────────────────────────────────────────
21
26
  export { scaffoldProject, normalizeProjectName, KNOWN_BOARDS, generateProjectPackageJson, generateProjectTsconfig, generateProjectConfig, generateProjectEnvDts, generateStarterSketch, generateStarterTest, generateStarterSim, generateGitignore, generateEslintConfig, runInitWizard, } from "./create/index.js";
22
27
  // ── Board codegen (`cuttlefish board add`) ───────────────────────────────────
@@ -34,6 +39,8 @@ export { prescanUnsupportedFeatures } from "./ir/feature-prescan.js";
34
39
  export { LINT_RULES, ESLINT_OPT_OUT_KINDS, kindRegistryEntries, } from "./ir/feature-registry.js";
35
40
  // ── ESLint gate ──────────────────────────────────────────────────────────────
36
41
  export { runEslintCheck } from "./eslint-check.js";
42
+ // ── ESLint gate cache ────────────────────────────────────────────────────────
43
+ export { checkLintCache, recordLintSuccess, invalidateLint, computeLintFingerprint, resolveEslintConfigPath, } from "./lint-cache.js";
37
44
  // ── Semantic gates (TypeChecker-based) ──────────────────────────────────────
38
45
  export { runSemanticGates } from "./orchestrator/type-checker.js";
39
46
  export { canonicalize, buildSemanticFacts, } from "./orchestrator/semantic-facts.js";
@@ -43,7 +50,7 @@ export { discoverWatchDirs, isRelevantChange } from "./watch.js";
43
50
  export { parseCommandLine } from "./utils/cli.js";
44
51
  export { parseHeader, stripPreprocessorBlocks } from "./libdef/header-parser.js";
45
52
  export { BaseClassResolver, buildClassIndex } from "./libdef/base-class-resolver.js";
46
- export { generateDecl, generateDeclsForDirectory } from "./libdef/cpp-to-decl.js";
53
+ export { generateDecl, generateDeclsForDirectory, generateComponentDeclsForProject } from "./libdef/cpp-to-decl.js";
47
54
  // ── IR rendering internals (for fail-closed regression tests) ───────────────
48
55
  export { renderExprAsText } from "./ir/render-expr.js";
49
56
  export { contextStorage, CompilationContext } from "./ir/build-ir-state.js";
@@ -1,3 +1,6 @@
1
1
  import { GenerateLibdefOptions, GeneratedOutputs, TranspileOptions } from "./types.js";
2
+ import { loadFrameworkPackage } from "./framework-package.js";
3
+ export { loadFrameworkPackage };
4
+ export { getLoadedFramework, hasLoadedFramework } from "./framework-registry.js";
2
5
  export declare function transpileFile(options: TranspileOptions): Promise<GeneratedOutputs>;
3
6
  export declare function generateLibraryDefinitions(options: GenerateLibdefOptions): string[];