@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.
- package/dist/api/config.d.ts +32 -0
- package/dist/api/index.d.ts +1 -1
- package/dist/api/schema/types.d.ts +15 -0
- package/dist/api/shared/async-runtime-static.d.ts +12 -1
- package/dist/api/shared/async-runtime-static.js +69 -24
- package/dist/api/shared/async-symbol-detector.d.ts +11 -0
- package/dist/api/shared/async-symbol-detector.js +140 -0
- package/dist/api/shared/async-types.d.ts +24 -0
- package/dist/api/shared/coop-scheduler.d.ts +60 -0
- package/dist/api/shared/coop-scheduler.js +149 -0
- package/dist/api/shared/display-adapter.d.ts +4 -3
- package/dist/api/shared/display-adapter.js +15 -118
- package/dist/api/shared/display-adapters/sdl.js +38 -31
- package/dist/api/shared/display-profile.d.ts +47 -25
- package/dist/api/shared/display-profile.js +31 -164
- package/dist/api/shared/framework-manifest-registry.d.ts +9 -0
- package/dist/api/shared/framework-manifest-registry.js +27 -0
- package/dist/api/shared/framework-manifest.d.ts +581 -0
- package/dist/api/shared/framework-manifest.js +182 -0
- package/dist/api/shared/glcdfont.d.ts +12 -0
- package/dist/api/shared/glcdfont.js +124 -0
- package/dist/api/shared/graphics-strategy.d.ts +37 -0
- package/dist/api/shared/hal-op-ir.d.ts +755 -1
- package/dist/api/shared/hal-op-ir.js +129 -1
- package/dist/api/shared/index.d.ts +20 -2
- package/dist/api/shared/index.js +25 -1
- package/dist/api/shared/ir-core.d.ts +4 -0
- package/dist/api/shared/ir-declarations.d.ts +6 -0
- package/dist/api/shared/native-display-op-resolver.d.ts +10 -0
- package/dist/api/shared/native-display-op-resolver.js +64 -0
- package/dist/api/shared/platform-strategy.d.ts +113 -2
- package/dist/api/shared/polyfill-helper-registry.js +18 -1
- package/dist/api/shared/promise-runtime.d.ts +1 -1
- package/dist/api/shared/promise-runtime.js +95 -13
- package/dist/api/shared/toolchain-types.d.ts +17 -0
- package/dist/api/shared/validate-framework-manifest.d.ts +28 -0
- package/dist/api/shared/validate-framework-manifest.js +494 -0
- package/dist/api/shared/worker-runtime-polyfill.d.ts +22 -0
- package/dist/api/shared/worker-runtime-polyfill.js +34 -0
- package/dist/api/shared/worker-runtime.d.ts +69 -0
- package/dist/api/shared/worker-runtime.js +163 -0
- package/dist/cli.js +186 -82
- package/dist/config-loader.d.ts +7 -2
- package/dist/config-loader.js +23 -3
- package/dist/config-schema.d.ts +112 -70
- package/dist/config-schema.js +14 -0
- package/dist/contract/board-generator.d.ts +17 -0
- package/dist/contract/board-generator.js +57 -0
- package/dist/contract/contract-parser.d.ts +217 -0
- package/dist/contract/contract-parser.js +224 -0
- package/dist/contract/index.d.ts +22 -0
- package/dist/contract/index.js +68 -0
- package/dist/create/board-codegen.js +4 -4
- package/dist/create/board-generators.js +4 -5
- package/dist/create/board-spec.d.ts +72 -75
- package/dist/create/board-spec.js +0 -1
- package/dist/create/init-scaffold.d.ts +9 -2
- package/dist/create/init-scaffold.js +0 -14
- package/dist/create/init-templates.d.ts +2 -0
- package/dist/create/init-templates.js +74 -8
- package/dist/create/init-wizard.js +31 -7
- package/dist/debug/preprocessor.js +178 -39
- package/dist/debug/types.d.ts +23 -0
- package/dist/diagnostics/mermaid-builder.d.ts +1 -1
- package/dist/diagnostics/mermaid-builder.js +34 -24
- package/dist/emit/compliance/arxml-writer.d.ts +11 -0
- package/dist/emit/compliance/arxml-writer.js +34 -0
- package/dist/emit/compliance/compliance-context.d.ts +57 -0
- package/dist/emit/compliance/compliance-context.js +113 -0
- package/dist/emit/compliance/deviation-ledger.d.ts +27 -0
- package/dist/emit/compliance/deviation-ledger.js +47 -0
- package/dist/emit/compliance/deviation-writer.d.ts +30 -0
- package/dist/emit/compliance/deviation-writer.js +37 -0
- package/dist/emit/compliance/index.d.ts +7 -0
- package/dist/emit/compliance/index.js +6 -0
- package/dist/emit/compliance/rule-engine.d.ts +13 -0
- package/dist/emit/compliance/rule-engine.js +101 -0
- package/dist/emit/compliance/rules.d.ts +16 -0
- package/dist/emit/compliance/rules.js +191 -0
- package/dist/emit/compliance/types.d.ts +59 -0
- package/dist/emit/compliance/types.js +8 -0
- package/dist/emit/cpp-emitter.js +4 -3
- package/dist/emit/emitters/class-emitter.js +6 -1
- package/dist/emit/emitters/emitter-context.d.ts +28 -1
- package/dist/emit/emitters/function-emitter-impl.js +153 -53
- package/dist/emit/emitters/line-appender.js +19 -0
- package/dist/emit/emitters/line-marker.d.ts +38 -0
- package/dist/emit/emitters/line-marker.js +39 -0
- package/dist/emit/emitters/output-finalizer.d.ts +6 -0
- package/dist/emit/emitters/output-finalizer.js +101 -12
- package/dist/emit/emitters/setup.d.ts +17 -0
- package/dist/emit/emitters/setup.js +257 -36
- package/dist/emit/emitters/top-level-prep.js +8 -0
- package/dist/emit/emitters/type-decl-emitter.js +28 -3
- package/dist/emit/emitters/ui-emitter.js +33 -9
- package/dist/emit/expression-renderer.d.ts +1 -1
- package/dist/emit/expression-renderer.js +91 -6
- package/dist/emit/route-hal-op.js +18 -5
- package/dist/emit/snprintf-helpers.js +15 -4
- package/dist/emit/statement-renderer.d.ts +10 -0
- package/dist/emit/statement-renderer.js +34 -5
- package/dist/emit/utils/async-state-machine.js +221 -125
- package/dist/emit/utils/hal-op-cpp-type.d.ts +6 -0
- package/dist/emit/utils/hal-op-cpp-type.js +40 -0
- package/dist/framework-package.js +2 -0
- package/dist/framework-registry.d.ts +17 -0
- package/dist/ir/adc-range-validation.js +14 -1
- package/dist/ir/build-ir-state.d.ts +1 -0
- package/dist/ir/build-ir-state.js +14 -0
- package/dist/ir/build-ir.js +9 -5
- package/dist/ir/call-graph.js +16 -0
- package/dist/ir/expression-to-ir.js +164 -0
- package/dist/ir/feature-registry.js +7 -25
- package/dist/ir/function-builder.js +22 -0
- package/dist/ir/hal/hal-emitter.d.ts +5 -2
- package/dist/ir/hal/hal-emitter.js +50 -18
- package/dist/ir/hal/hal-parser.d.ts +6 -0
- package/dist/ir/hal/hal-parser.js +81 -0
- package/dist/ir/hal/hal-plugins.js +723 -1
- package/dist/ir/identifier-collector.js +35 -0
- package/dist/ir/interrupt-analysis.d.ts +5 -1
- package/dist/ir/interrupt-analysis.js +8 -16
- package/dist/ir/network-validation.d.ts +4 -0
- package/dist/ir/network-validation.js +184 -0
- package/dist/ir/ownership-analysis.js +20 -1
- package/dist/ir/pin-capability-validation.js +37 -0
- package/dist/ir/pin-mode-validation.d.ts +2 -2
- package/dist/ir/pin-mode-validation.js +49 -18
- package/dist/ir/program-analysis.d.ts +65 -0
- package/dist/ir/program-analysis.js +318 -2
- package/dist/ir/render-expr.js +11 -0
- package/dist/ir/timing-validation.d.ts +6 -1
- package/dist/ir/timing-validation.js +60 -13
- package/dist/ir/transformers/call-statement.js +105 -0
- package/dist/ir/transformers/expressions.js +62 -0
- package/dist/ir/transformers/hal-call-resolver.js +21 -0
- package/dist/ir/transformers/hal-emit-helpers.js +1 -1
- package/dist/ir/transformers/namespace-methods.js +17 -12
- package/dist/ir/transformers/ui-reactive.js +2 -2
- package/dist/ir/transformers/variables.js +92 -3
- package/dist/ir/type-resolution.js +18 -0
- package/dist/ir/ui-element-auto-wire.js +7 -5
- package/dist/ir/utils/map-statements.d.ts +4 -0
- package/dist/ir/utils/map-statements.js +79 -0
- package/dist/ir/validation-orchestrator.js +9 -2
- package/dist/ir/worker-analysis.d.ts +10 -0
- package/dist/ir/worker-analysis.js +261 -0
- package/dist/libdef/c-to-decl.d.ts +27 -0
- package/dist/libdef/c-to-decl.js +397 -0
- package/dist/libdef/component-decls.d.ts +2 -0
- package/dist/libdef/component-decls.js +6 -0
- package/dist/libdef/component-discovery.d.ts +43 -0
- package/dist/libdef/component-discovery.js +83 -0
- package/dist/libdef/cpp-to-decl.d.ts +9 -0
- package/dist/libdef/cpp-to-decl.js +72 -0
- package/dist/libdef/registry.js +5 -2
- package/dist/lint-cache.d.ts +59 -0
- package/dist/lint-cache.js +257 -0
- package/dist/orchestrator/graph-builder.js +14 -9
- package/dist/platform/coop-scheduler-runtime.d.ts +19 -0
- package/dist/platform/coop-scheduler-runtime.js +41 -0
- package/dist/platform/generic-strategy.d.ts +15 -3
- package/dist/platform/generic-strategy.js +49 -4
- package/dist/safety/safety-bridge.d.ts +11 -0
- package/dist/safety/safety-bridge.js +48 -0
- package/dist/safety/sidecar-bridge.d.ts +5 -0
- package/dist/safety/sidecar-bridge.js +22 -0
- package/dist/safety-hook.d.ts +79 -0
- package/dist/safety-hook.js +35 -0
- package/dist/testing.d.ts +7 -1
- package/dist/testing.js +8 -1
- package/dist/transpile.d.ts +3 -0
- package/dist/transpile.js +175 -41
- package/dist/types.d.ts +13 -2
- package/dist/ui-hook.d.ts +17 -3
- package/dist/utils/cli.js +78 -4
- package/dist/utils/fs.d.ts +13 -0
- package/dist/utils/fs.js +50 -0
- package/package.json +24 -5
- package/dist/api/shared/display-adapters/eink-mono.d.ts +0 -2
- package/dist/api/shared/display-adapters/eink-mono.js +0 -53
- package/dist/api/shared/display-adapters/ssd1309.d.ts +0 -2
- package/dist/api/shared/display-adapters/ssd1309.js +0 -136
- package/dist/api/shared/display-adapters/st7796.d.ts +0 -2
- package/dist/api/shared/display-adapters/st7796.js +0 -132
- package/dist/licenses.d.ts +0 -185
- 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(
|
|
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(
|
|
58
|
-
asyncLoopInjection(
|
|
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
|
|
45
|
+
return this.defaultNumericType();
|
|
46
46
|
return typeName;
|
|
47
47
|
}
|
|
48
|
-
defaultNumericType() {
|
|
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(
|
|
192
|
+
asyncLoopInjection(taskVarNames, configOrBool) {
|
|
189
193
|
let hasPromiseRuntime;
|
|
190
|
-
if (typeof configOrBool ===
|
|
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";
|
package/dist/transpile.d.ts
CHANGED
|
@@ -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[];
|