@typecad/cuttlefish 0.1.0-alpha.2 → 1.0.0-alpha.6
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/README.md +10 -10
- package/dist/api/board-types.d.ts +1 -1
- package/dist/api/shared/hal-op-ir.d.ts +10 -1
- package/dist/api/shared/platform-strategy.d.ts +6 -0
- package/dist/api/shared/types.d.ts +8 -0
- package/dist/cli-utils.d.ts +1 -0
- package/dist/cli-utils.js +3 -1
- package/dist/cli.js +75 -0
- package/dist/create/index.d.ts +1 -1
- package/dist/create/index.js +1 -1
- package/dist/create/init-scaffold.js +48 -2
- package/dist/create/init-templates.d.ts +2 -0
- package/dist/create/init-templates.js +189 -9
- package/dist/emit/emitters/setup.js +122 -1
- package/dist/ir/adc-range-validation.js +26 -25
- package/dist/ir/expression-to-ir.js +43 -6
- package/dist/ir/hal/hal-plugins.js +10 -0
- package/dist/ir/interrupt-analysis.js +8 -3
- package/dist/ir/memory-budget-validation.js +1 -0
- package/dist/ir/ownership-analysis.js +19 -0
- package/dist/ir/peripheral-ownership.js +5 -0
- package/dist/ir/peripheral-validation.d.ts +1 -1
- package/dist/ir/peripheral-validation.js +6 -3
- package/dist/ir/pin-alias-conflict.d.ts +1 -1
- package/dist/ir/pin-alias-conflict.js +2 -1
- package/dist/ir/pin-capability-validation.js +34 -32
- package/dist/ir/pin-mode-validation.js +5 -0
- package/dist/ir/pin-safety.d.ts +1 -1
- package/dist/ir/pin-safety.js +2 -1
- package/dist/ir/program-analysis.d.ts +16 -0
- package/dist/ir/program-analysis.js +113 -0
- package/dist/ir/pulldown-validation.d.ts +1 -1
- package/dist/ir/pulldown-validation.js +2 -1
- package/dist/ir/pwm-timer-sharing.d.ts +1 -1
- package/dist/ir/pwm-timer-sharing.js +2 -1
- package/dist/ir/resource-analysis.js +2 -0
- package/dist/ir/timer0-pwm-timing-conflict.d.ts +1 -1
- package/dist/ir/timer0-pwm-timing-conflict.js +2 -1
- package/dist/ir/timing-validation.js +1 -0
- package/dist/ir/transformers/variables.js +46 -17
- package/dist/ir/try-catch-validation.js +2 -0
- package/dist/ir/type-resolution.js +2 -2
- package/dist/ir/unit-suspicion-validation.js +9 -7
- package/dist/ir/validation-orchestrator.js +6 -6
- package/dist/licenses.d.ts +185 -0
- package/dist/licenses.js +963 -0
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1 -1
- package/dist/transpile.js +17 -9
- package/dist/types.d.ts +7 -1
- package/dist/utils/cli.js +44 -0
- package/package.json +5 -4
- package/dist/ir/heap-array-validation.d.ts +0 -24
- package/dist/ir/heap-array-validation.js +0 -29
package/dist/testing.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export type { EmitMode, GeneratedOutputs, TargetProfile, PlatformContext } from
|
|
|
15
15
|
export { findConfigFile, parseConfigFile, loadCuttlefishConfig, generateVirtualTypeDeclaration, } from "./config-loader.js";
|
|
16
16
|
export { transpileFile } from "./transpile.js";
|
|
17
17
|
export { resetUIEngine, __simulateUIAbsentForTest } from "./ui/ui-bridge.js";
|
|
18
|
-
export { scaffoldProject, normalizeProjectName, KNOWN_BOARDS, generateProjectPackageJson, generateProjectTsconfig, generateProjectConfig, generateProjectEnvDts, generateStarterSketch, generateGitignore, generateEslintConfig, runInitWizard, } from "./create/index.js";
|
|
18
|
+
export { scaffoldProject, normalizeProjectName, KNOWN_BOARDS, generateProjectPackageJson, generateProjectTsconfig, generateProjectConfig, generateProjectEnvDts, generateStarterSketch, generateStarterTest, generateStarterSim, generateGitignore, generateEslintConfig, runInitWizard, } from "./create/index.js";
|
|
19
19
|
export type { InitProjectOptions } from "./create/index.js";
|
|
20
20
|
export { scaffoldBoardPackages, parseBoardSpec, safeParseBoardSpec, stripJsonc, } from "./create/index.js";
|
|
21
21
|
export type { BoardSpec, ScaffoldBoardResult } from "./create/index.js";
|
package/dist/testing.js
CHANGED
|
@@ -18,7 +18,7 @@ export { transpileFile } from "./transpile.js";
|
|
|
18
18
|
// ── UI bridge (optional @typecad/ui) ─────────────────────────────────────────
|
|
19
19
|
export { resetUIEngine, __simulateUIAbsentForTest } from "./ui/ui-bridge.js";
|
|
20
20
|
// ── Project scaffolding ──────────────────────────────────────────────────────
|
|
21
|
-
export { scaffoldProject, normalizeProjectName, KNOWN_BOARDS, generateProjectPackageJson, generateProjectTsconfig, generateProjectConfig, generateProjectEnvDts, generateStarterSketch, generateGitignore, generateEslintConfig, runInitWizard, } from "./create/index.js";
|
|
21
|
+
export { scaffoldProject, normalizeProjectName, KNOWN_BOARDS, generateProjectPackageJson, generateProjectTsconfig, generateProjectConfig, generateProjectEnvDts, generateStarterSketch, generateStarterTest, generateStarterSim, generateGitignore, generateEslintConfig, runInitWizard, } from "./create/index.js";
|
|
22
22
|
// ── Board codegen (`cuttlefish board add`) ───────────────────────────────────
|
|
23
23
|
export { scaffoldBoardPackages, parseBoardSpec, safeParseBoardSpec, stripJsonc, } from "./create/index.js";
|
|
24
24
|
export { BoardGenerators } from "./create/index.js";
|
package/dist/transpile.js
CHANGED
|
@@ -138,8 +138,9 @@ function formatFatalDiagnostics(entries) {
|
|
|
138
138
|
`Transpilation aborted because ${errors.length} unsupported pattern${errors.length === 1 ? "" : "s"} were found.`,
|
|
139
139
|
];
|
|
140
140
|
for (const { filePath, diagnostic } of errors) {
|
|
141
|
-
const
|
|
142
|
-
|
|
141
|
+
const resolvedFile = filePath ?? diagnostic.filePath;
|
|
142
|
+
const locationBase = resolvedFile
|
|
143
|
+
? path.relative(process.cwd(), resolvedFile) || resolvedFile
|
|
143
144
|
: diagnostic.source ?? "user code";
|
|
144
145
|
const position = diagnostic.line != null
|
|
145
146
|
? `(${diagnostic.line}:${diagnostic.column ?? 1})`
|
|
@@ -336,7 +337,7 @@ export async function transpileFile(options) {
|
|
|
336
337
|
code: "themeCss-ui-entry-ignored",
|
|
337
338
|
message: `display.themeCss is ignored for .ui single-file entries; the inline <style> in ${path.basename(options.inputFile)} is the sole CSS source.`,
|
|
338
339
|
hint: `Move the standalone CSS into the .ui file's <style> block, or change the entry to a .ts file that imports a .ui.html module.`,
|
|
339
|
-
|
|
340
|
+
filePath: path.basename(options.inputFile),
|
|
340
341
|
});
|
|
341
342
|
}
|
|
342
343
|
}
|
|
@@ -348,7 +349,7 @@ export async function transpileFile(options) {
|
|
|
348
349
|
if (hasUIHook()) {
|
|
349
350
|
for (const mod of requireUIHook().allUIModules()) {
|
|
350
351
|
for (const d of mod.diagnostics) {
|
|
351
|
-
diagnostics.push({ ...d,
|
|
352
|
+
diagnostics.push({ ...d, filePath: d.filePath ?? path.basename(mod.htmlPath) });
|
|
352
353
|
}
|
|
353
354
|
}
|
|
354
355
|
}
|
|
@@ -466,7 +467,7 @@ export async function transpileFile(options) {
|
|
|
466
467
|
if (hasUIHook()) {
|
|
467
468
|
for (const mod of requireUIHook().allUIModules()) {
|
|
468
469
|
for (const d of mod.mountDiagnostics) {
|
|
469
|
-
diagnostics.push({ ...d,
|
|
470
|
+
diagnostics.push({ ...d, filePath: d.filePath ?? path.basename(mod.htmlPath) });
|
|
470
471
|
}
|
|
471
472
|
}
|
|
472
473
|
}
|
|
@@ -689,6 +690,7 @@ export async function transpileFile(options) {
|
|
|
689
690
|
profiler.endTimer("post:flatten");
|
|
690
691
|
// Profiler session ends (profiling disabled - no report generation)
|
|
691
692
|
// ── Generate diagnostics report if enabled ──────────────────────────────
|
|
693
|
+
let diagnosticsReportPath;
|
|
692
694
|
if (options.diagnostics) {
|
|
693
695
|
try {
|
|
694
696
|
const entryPreBuilt = preBuilt.get(entryFile);
|
|
@@ -708,17 +710,23 @@ export async function transpileFile(options) {
|
|
|
708
710
|
removedSymbols: allRemovedSymbols,
|
|
709
711
|
});
|
|
710
712
|
writeDiagnosticsReport(report, entryPreBuilt?.programIR ?? null, outDir);
|
|
713
|
+
diagnosticsReportPath = path.join(outDir, "diagnostics.md");
|
|
711
714
|
}
|
|
712
715
|
catch (e) {
|
|
713
|
-
// Diagnostics report generation is best-effort; don't fail the build
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
716
|
+
// Diagnostics report generation is best-effort; don't fail the build,
|
|
717
|
+
// but surface the failure so the user knows --diagnostics didn't work.
|
|
718
|
+
diagnostics.push({
|
|
719
|
+
severity: "warning",
|
|
720
|
+
message: `Diagnostics report generation failed: ${e instanceof Error ? e.message : String(e)}`,
|
|
721
|
+
code: "diagnostics-report-failed",
|
|
722
|
+
source: "transpile",
|
|
723
|
+
});
|
|
717
724
|
}
|
|
718
725
|
}
|
|
719
726
|
return {
|
|
720
727
|
...entryOutputs,
|
|
721
728
|
diagnostics,
|
|
729
|
+
diagnosticsReportPath,
|
|
722
730
|
};
|
|
723
731
|
}
|
|
724
732
|
export function generateLibraryDefinitions(options) {
|
package/dist/types.d.ts
CHANGED
|
@@ -114,7 +114,11 @@ export interface LibraryDefinition {
|
|
|
114
114
|
variants?: LibraryDefinitionVariant[];
|
|
115
115
|
}
|
|
116
116
|
export interface CommandLineOptions {
|
|
117
|
-
command: "default" | "build" | "gen-libdefs" | "gen-decls" | "map-error" | "preview";
|
|
117
|
+
command: "default" | "build" | "gen-libdefs" | "gen-decls" | "map-error" | "preview" | "doctor" | "licenses";
|
|
118
|
+
/** For `licenses`: treat unknown/missing licenses as failures (exit 1). */
|
|
119
|
+
strict?: boolean;
|
|
120
|
+
/** For `licenses`: scan all installed libraries (default: this project's only). */
|
|
121
|
+
all?: boolean;
|
|
118
122
|
inputFile?: string;
|
|
119
123
|
emitMode: EmitMode;
|
|
120
124
|
target: TargetProfile;
|
|
@@ -181,6 +185,8 @@ export interface GeneratedOutputs {
|
|
|
181
185
|
diagnostics: Diagnostic[];
|
|
182
186
|
asyncTaskNames?: string[];
|
|
183
187
|
usesTimers?: boolean;
|
|
188
|
+
/** Path to the diagnostics.md report, if --diagnostics was passed. */
|
|
189
|
+
diagnosticsReportPath?: string;
|
|
184
190
|
}
|
|
185
191
|
interface CompileErrorEntry {
|
|
186
192
|
filePath: string;
|
package/dist/utils/cli.js
CHANGED
|
@@ -17,6 +17,8 @@ export function printHelp() {
|
|
|
17
17
|
console.log(` cuttlefish board add <spec.jsonc> [--force] Generate board + MCU packages from a chip spec`);
|
|
18
18
|
console.log(` cuttlefish gen-decls <input.cpp|--all <directory>>`);
|
|
19
19
|
console.log(` cuttlefish map-error <mapFile> [options]`);
|
|
20
|
+
console.log(` cuttlefish doctor Check that arduino-cli is installed and the board's core is present`);
|
|
21
|
+
console.log(` cuttlefish licenses [--all] [--strict] Scan this project's Arduino libraries for SPDX licenses (--all: every installed library)`);
|
|
20
22
|
console.log();
|
|
21
23
|
console.log(chalk.gray(`Transpilation is always performed first. Use --compile, --upload, and`));
|
|
22
24
|
console.log(chalk.gray(`--monitor to chain operations after transpilation.`));
|
|
@@ -337,6 +339,48 @@ export function parseCommandLine(argv) {
|
|
|
337
339
|
port: port ? String(port) : undefined,
|
|
338
340
|
};
|
|
339
341
|
}
|
|
342
|
+
// doctor subcommand — verify arduino-cli + board core presence
|
|
343
|
+
if (firstArg === "doctor") {
|
|
344
|
+
return {
|
|
345
|
+
command: "doctor",
|
|
346
|
+
// The remaining pipeline fields are unused by doctor; fill with safe
|
|
347
|
+
// defaults, the same way the preview branch does.
|
|
348
|
+
inputFile: undefined,
|
|
349
|
+
emitMode: "split",
|
|
350
|
+
target: "generic",
|
|
351
|
+
outDir: undefined,
|
|
352
|
+
emitMaps: true,
|
|
353
|
+
noTranspile: false,
|
|
354
|
+
compile: false,
|
|
355
|
+
upload: false,
|
|
356
|
+
monitor: false,
|
|
357
|
+
watch: false,
|
|
358
|
+
baud: 9600,
|
|
359
|
+
platformContext: {},
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
// licenses subcommand — scan installed Arduino libraries for SPDX licenses
|
|
363
|
+
if (firstArg === "licenses") {
|
|
364
|
+
return {
|
|
365
|
+
command: "licenses",
|
|
366
|
+
strict: argv.includes("--strict"),
|
|
367
|
+
all: argv.includes("--all"),
|
|
368
|
+
// The remaining pipeline fields are unused by licenses; fill with safe
|
|
369
|
+
// defaults, the same way the doctor branch does.
|
|
370
|
+
inputFile: undefined,
|
|
371
|
+
emitMode: "split",
|
|
372
|
+
target: "generic",
|
|
373
|
+
outDir: undefined,
|
|
374
|
+
emitMaps: true,
|
|
375
|
+
noTranspile: false,
|
|
376
|
+
compile: false,
|
|
377
|
+
upload: false,
|
|
378
|
+
monitor: false,
|
|
379
|
+
watch: false,
|
|
380
|
+
baud: 9600,
|
|
381
|
+
platformContext: {},
|
|
382
|
+
};
|
|
383
|
+
}
|
|
340
384
|
// Named subcommands
|
|
341
385
|
if (firstArg === "gen-libdefs" || firstArg === "gen-decls" || firstArg === "map-error") {
|
|
342
386
|
const command = firstArg;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typecad/cuttlefish",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0-alpha.6",
|
|
4
4
|
"description": "TypeScript to C++ transpiler — native, Arduino, and bare-metal targets",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/transpile.js",
|
|
@@ -80,10 +80,11 @@
|
|
|
80
80
|
"dependencies": {
|
|
81
81
|
"chalk": "^4.1.2",
|
|
82
82
|
"typescript": "^5.7.3",
|
|
83
|
-
"zod": "^3.24.0"
|
|
83
|
+
"zod": "^3.24.0",
|
|
84
|
+
"@typecad/arduino-cli": "1.0.0-alpha.6"
|
|
84
85
|
},
|
|
85
86
|
"peerDependencies": {
|
|
86
|
-
"@typecad/ui": "
|
|
87
|
+
"@typecad/ui": "1.0.0-alpha.6"
|
|
87
88
|
},
|
|
88
89
|
"peerDependenciesMeta": {
|
|
89
90
|
"@typecad/ui": {
|
|
@@ -91,7 +92,7 @@
|
|
|
91
92
|
}
|
|
92
93
|
},
|
|
93
94
|
"optionalDependencies": {
|
|
94
|
-
"@typecad/framework-native": "
|
|
95
|
+
"@typecad/framework-native": "1.0.0-alpha.6"
|
|
95
96
|
},
|
|
96
97
|
"devDependencies": {
|
|
97
98
|
"@types/node": "^22.10.7"
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { Diagnostic } from '../types.js';
|
|
2
|
-
import type { BoardConstants } from './board-resolver.js';
|
|
3
|
-
import type { StatementIR } from '../api/index.js';
|
|
4
|
-
import type { PlatformStrategy } from '../api/shared/index.js';
|
|
5
|
-
/**
|
|
6
|
-
* @deprecated Heap allocation is now validated at emit time by the platform
|
|
7
|
-
* strategy's `profileDiagnostics` (see framework-arduino `collectHeapAllocationDiagnostics`).
|
|
8
|
-
* This build-time stub returns no diagnostics. Kept to preserve the
|
|
9
|
-
* `validation-orchestrator.ts` import; remove that call site when convenient.
|
|
10
|
-
*/
|
|
11
|
-
export declare function validateHeapArrayUsage(_program: {
|
|
12
|
-
topLevelStatements: StatementIR[];
|
|
13
|
-
functions: Array<{
|
|
14
|
-
statements: StatementIR[];
|
|
15
|
-
}>;
|
|
16
|
-
classes: Array<{
|
|
17
|
-
methods: Array<{
|
|
18
|
-
statements: StatementIR[];
|
|
19
|
-
}>;
|
|
20
|
-
constructor?: {
|
|
21
|
-
statements: StatementIR[];
|
|
22
|
-
};
|
|
23
|
-
}>;
|
|
24
|
-
}, _boardConstants: BoardConstants | undefined, _strategy?: PlatformStrategy): Diagnostic[];
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// Heap Allocation Validator (retired — moved to the emit-time profile gate)
|
|
3
|
-
//
|
|
4
|
-
// Heap allocation via `new` on no-heap architectures (AVR, etc.) is now
|
|
5
|
-
// rejected by the Arduino strategy's `profileDiagnostics`
|
|
6
|
-
// (`framework-arduino/src/strategy.ts` `collectHeapAllocationDiagnostics`).
|
|
7
|
-
//
|
|
8
|
-
// WHY THE MOVE: this build-time validator keyed off `boardConstants.architecture`,
|
|
9
|
-
// which is only populated when an MCU/board `import` is present. Programs with
|
|
10
|
-
// no such import silently bypassed it — so demo #33's `new Accumulator()`
|
|
11
|
-
// passed while a HAL-importing demo's `new Blinker()` failed, for the same
|
|
12
|
-
// source pattern. The profile-time gate derives `arch` from the FQBN
|
|
13
|
-
// (`frameworkData.buildTarget`), so it fires regardless of import structure
|
|
14
|
-
// (demo #34 Finding A). It also keys off the `newClassName` marker a user-class
|
|
15
|
-
// `new` tags its raw IR node with (set in `expression-to-ir.ts`), making
|
|
16
|
-
// detection structural rather than textual.
|
|
17
|
-
//
|
|
18
|
-
// The export is kept (returns `[]`) so `validation-orchestrator.ts`'s import
|
|
19
|
-
// stays valid; the real work happens at emit time.
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
|
-
/**
|
|
22
|
-
* @deprecated Heap allocation is now validated at emit time by the platform
|
|
23
|
-
* strategy's `profileDiagnostics` (see framework-arduino `collectHeapAllocationDiagnostics`).
|
|
24
|
-
* This build-time stub returns no diagnostics. Kept to preserve the
|
|
25
|
-
* `validation-orchestrator.ts` import; remove that call site when convenient.
|
|
26
|
-
*/
|
|
27
|
-
export function validateHeapArrayUsage(_program, _boardConstants, _strategy) {
|
|
28
|
-
return [];
|
|
29
|
-
}
|