atelang-core 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +166 -2
  3. package/dist/compiler/binary.d.ts +44 -0
  4. package/dist/compiler/binary.js +132 -0
  5. package/dist/compiler/binary.js.map +1 -0
  6. package/dist/compiler/compiler.d.ts +51 -0
  7. package/dist/compiler/compiler.js +86 -0
  8. package/dist/compiler/compiler.js.map +1 -0
  9. package/dist/compiler/index.d.ts +14 -0
  10. package/dist/compiler/index.js +31 -0
  11. package/dist/compiler/index.js.map +1 -0
  12. package/dist/compiler/ir.d.ts +45 -0
  13. package/dist/compiler/ir.js +32 -0
  14. package/dist/compiler/ir.js.map +1 -0
  15. package/dist/debug/controller.d.ts +67 -0
  16. package/dist/debug/controller.js +127 -0
  17. package/dist/debug/controller.js.map +1 -0
  18. package/dist/debug/index.d.ts +2 -0
  19. package/dist/debug/index.js +19 -0
  20. package/dist/debug/index.js.map +1 -0
  21. package/dist/debug/lineMap.d.ts +58 -0
  22. package/dist/debug/lineMap.js +102 -0
  23. package/dist/debug/lineMap.js.map +1 -0
  24. package/dist/editor/completion.d.ts +8 -0
  25. package/dist/editor/completion.js +118 -0
  26. package/dist/editor/completion.js.map +1 -0
  27. package/dist/editor/hover.d.ts +10 -0
  28. package/dist/editor/hover.js +98 -0
  29. package/dist/editor/hover.js.map +1 -0
  30. package/dist/editor/index.d.ts +2 -0
  31. package/dist/editor/index.js +19 -0
  32. package/dist/editor/index.js.map +1 -0
  33. package/dist/index.d.ts +11 -0
  34. package/dist/index.js +28 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/language/analyzer.d.ts +12 -0
  37. package/dist/language/analyzer.js +344 -0
  38. package/dist/language/analyzer.js.map +1 -0
  39. package/dist/language/ast.d.ts +290 -0
  40. package/dist/language/ast.js +11 -0
  41. package/dist/language/ast.js.map +1 -0
  42. package/dist/language/configuration.d.ts +10 -0
  43. package/dist/language/configuration.js +190 -0
  44. package/dist/language/configuration.js.map +1 -0
  45. package/dist/language/definition.d.ts +22 -0
  46. package/dist/language/definition.js +72 -0
  47. package/dist/language/definition.js.map +1 -0
  48. package/dist/language/diagnostics.d.ts +15 -0
  49. package/dist/language/diagnostics.js +3 -0
  50. package/dist/language/diagnostics.js.map +1 -0
  51. package/dist/language/lexer.d.ts +41 -0
  52. package/dist/language/lexer.js +362 -0
  53. package/dist/language/lexer.js.map +1 -0
  54. package/dist/language/loader.d.ts +33 -0
  55. package/dist/language/loader.js +60 -0
  56. package/dist/language/loader.js.map +1 -0
  57. package/dist/language/parser.d.ts +123 -0
  58. package/dist/language/parser.js +1217 -0
  59. package/dist/language/parser.js.map +1 -0
  60. package/dist/language/symbols.d.ts +97 -0
  61. package/dist/language/symbols.js +152 -0
  62. package/dist/language/symbols.js.map +1 -0
  63. package/dist/language/units.d.ts +47 -0
  64. package/dist/language/units.js +177 -0
  65. package/dist/language/units.js.map +1 -0
  66. package/dist/node/binaryNode.d.ts +28 -0
  67. package/dist/node/binaryNode.js +112 -0
  68. package/dist/node/binaryNode.js.map +1 -0
  69. package/dist/node/index.d.ts +3 -0
  70. package/dist/node/index.js +20 -0
  71. package/dist/node/index.js.map +1 -0
  72. package/dist/node/nodeHost.d.ts +2 -0
  73. package/dist/node/nodeHost.js +60 -0
  74. package/dist/node/nodeHost.js.map +1 -0
  75. package/dist/node/pythonNode.d.ts +21 -0
  76. package/dist/node/pythonNode.js +167 -0
  77. package/dist/node/pythonNode.js.map +1 -0
  78. package/dist/runtime/action.d.ts +25 -0
  79. package/dist/runtime/action.js +3 -0
  80. package/dist/runtime/action.js.map +1 -0
  81. package/dist/runtime/datalog.d.ts +5 -0
  82. package/dist/runtime/datalog.js +127 -0
  83. package/dist/runtime/datalog.js.map +1 -0
  84. package/dist/runtime/env.d.ts +18 -0
  85. package/dist/runtime/env.js +61 -0
  86. package/dist/runtime/env.js.map +1 -0
  87. package/dist/runtime/eval.d.ts +24 -0
  88. package/dist/runtime/eval.js +227 -0
  89. package/dist/runtime/eval.js.map +1 -0
  90. package/dist/runtime/executor.d.ts +36 -0
  91. package/dist/runtime/executor.js +676 -0
  92. package/dist/runtime/executor.js.map +1 -0
  93. package/dist/runtime/index.d.ts +10 -0
  94. package/dist/runtime/index.js +27 -0
  95. package/dist/runtime/index.js.map +1 -0
  96. package/dist/runtime/python.d.ts +159 -0
  97. package/dist/runtime/python.js +245 -0
  98. package/dist/runtime/python.js.map +1 -0
  99. package/dist/runtime/runner.d.ts +27 -0
  100. package/dist/runtime/runner.js +94 -0
  101. package/dist/runtime/runner.js.map +1 -0
  102. package/dist/runtime/simulator.d.ts +39 -0
  103. package/dist/runtime/simulator.js +113 -0
  104. package/dist/runtime/simulator.js.map +1 -0
  105. package/dist/runtime/types.d.ts +165 -0
  106. package/dist/runtime/types.js +3 -0
  107. package/dist/runtime/types.js.map +1 -0
  108. package/dist/runtime/values.d.ts +45 -0
  109. package/dist/runtime/values.js +79 -0
  110. package/dist/runtime/values.js.map +1 -0
  111. package/docs/BINARY_FORMAT.md +197 -0
  112. package/docs/LANGUAGE.md +499 -0
  113. package/package.json +67 -4
  114. package/resources/python/ate_bridge.py +214 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Semight
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,167 @@
1
- # Temporary Holding Version
1
+ # atelang-core
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Reusable ATELang (`.ate`) language, compiler, execution engine, and Node adapters.
4
+ This is an independent npm package, version `0.1.0`, requiring Node.js 18 or newer.
5
+ It ships CommonJS JavaScript and TypeScript declarations with no runtime dependencies.
6
+ Installing the package does not require the sibling plugin or example projects.
7
+
8
+ The core owns tokenization, AST types, quantities/units, import loading through an
9
+ injected `Host`, symbols, diagnostics, definition lookup, compilation units, and the
10
+ binary codec, execution, simulation, datalog, and Python method support. The sibling
11
+ `atelang-vscode` plugin owns the CLI, VS Code integration, and
12
+ debug adapter. The core also owns pause/step control and executable source mappings.
13
+ The root, runtime, and debug entries do not import VS Code or Node APIs; Node
14
+ filesystem, gzip, and Python process adapters are isolated behind the `/node` entry.
15
+
16
+ ## Build, Test, and Pack
17
+
18
+ Run independently from `atelang-core/`:
19
+
20
+ ```bash
21
+ npm install # install dev dependencies; prepare builds dist/
22
+ npm run build # explicit rebuild after source changes
23
+ npm test # build and run JavaScript tests in test/ against the public API
24
+ npm pack --dry-run # inspect the package contents
25
+ npm pack # create atelang-core-0.1.0.tgz locally
26
+ ```
27
+
28
+ `prepare` builds on install/pack; `prepublishOnly` runs tests before publishing.
29
+ `npm pack` does not publish or run `prepublishOnly`, so run `npm test` before packing.
30
+ The package includes `dist/index.*`, `dist/language/`, `dist/compiler/`,
31
+ `dist/runtime/`, `dist/debug/`, `dist/editor/`, `dist/node/`, `resources/python/`, and `docs/`;
32
+ compiled tests are excluded. `npm run clean` removes `dist/`.
33
+
34
+ To install the tarball in a sibling Node project:
35
+
36
+ ```bash
37
+ npm install ../atelang-core/atelang-core-0.1.0.tgz
38
+ ```
39
+
40
+ ## Public API
41
+
42
+ Import language/compiler values and types from `atelang-core`, execution
43
+ APIs from `atelang-core/runtime`, debugging primitives from
44
+ `atelang-core/debug`, completion and hover data from
45
+ `atelang-core/editor`, and Node adapters from
46
+ `atelang-core/node`. The package root is backed by `dist/index.js` and
47
+ `dist/index.d.ts`; deep imports such as
48
+ `atelang-core/dist/language/parser` are not exported.
49
+
50
+ The editor entry exposes `getCompletions(linePrefix, symbols)` and
51
+ `getHover(symbolName, symbols)`. They return plain candidate and Markdown/code-block
52
+ data without editor dependencies. Hosts supply cursor context and adapt the results
53
+ to their editor APIs; document lifecycle and caching remain host responsibilities.
54
+
55
+ ```js
56
+ const { parse, compile, memoryHost } = require("atelang-core");
57
+
58
+ const source = "flow MainFlow {}";
59
+ const { program, errors } = parse(source, "main.ate");
60
+ console.log(program.body, errors);
61
+
62
+ // A flat in-memory project; real hosts resolve imports relative to the importer.
63
+ const host = memoryHost({ "main.ate": source }, (_from, spec) => spec);
64
+ const { analysis } = compile("main.ate", host);
65
+ console.log(analysis.diagnostics);
66
+ ```
67
+
68
+ | Entry points | Purpose |
69
+ | --- | --- |
70
+ | `tokenize`, `tokenizeSafe`, `parse` | Tokens and ASTs with source ranges and parse errors |
71
+ | `loadProgram`, `memoryHost` | Load an import graph using caller-supplied file access and resolution |
72
+ | `compile`, `analyze`, `buildSymbols`, `findDefinition` | Project analysis, symbols, diagnostics, and definition locations |
73
+ | `compileToUnit`, `loadResultFromUnit`, `formatDiagnostic` | Produce/reload a `CompilationUnit` and format diagnostics |
74
+ | `encodeBinary`, `decodeBinary`, `looksLikeBinary`, `AteBinaryError` | Encode/decode bytes and report binary format errors |
75
+
76
+ Types including `Program`, `Expr`, `Stmt`, `Diagnostic`, `Host`, `CompilationUnit`, and
77
+ `Compressor` are exported from the same root. `Host.readFile(path)` returns source text
78
+ or `null`; `Host.resolve(fromPath, spec)` returns the resolved import path. `compile()`
79
+ loads and analyzes without executing; `compileToUnit()` produces no unit if any error
80
+ diagnostic exists. Warnings remain available in its result.
81
+
82
+ The codec accepts/returns `Uint8Array`. Encoding is uncompressed by default; gzip
83
+ requires an injected `Compressor` with `deflate` and `inflate`. File reads/writes and
84
+ compression belong to the caller; see the [binary format guide](docs/BINARY_FORMAT.md).
85
+
86
+ ## Variables, Boards, and Instrument Actions
87
+
88
+ ```atelang
89
+ dutBoard Board { pin VDD : Power pin CLK : Digital }
90
+ var Conditions {
91
+ DC { set nominal { VDD = 3.3V RANGE = 5 } }
92
+ AC { set nominal { PERIOD = 100ns } }
93
+ }
94
+ levels L { useVarSet: Conditions.nominal VDD { force_v: VDD } }
95
+ timing T { useVarSet: Conditions.nominal period: PERIOD }
96
+ action PowerOn {
97
+ signal: VDD
98
+ instrument: dcVI
99
+ type: vforce
100
+ params {
101
+ forceValue: Conditions.DC.nominal.VDD
102
+ irange: Conditions.DC.nominal.RANGE
103
+ iclampH: 100mA
104
+ iclampL: -100mA
105
+ localsense: true
106
+ }
107
+ }
108
+ flow Main { apply_levels("L") apply_timing("T") execute PowerOn }
109
+ ```
110
+
111
+ Variable sets have separate AC/DC domains. `levels` binds DC and `timing` binds AC;
112
+ set-local names shadow spec constants. Expressions retain SI values and dimensions.
113
+ The set-oriented syntax represents the same variable/set matrix as cpoweb's
114
+ `ACVar`/`DCVar` data. Flow-local `var name = expression` remains supported.
115
+
116
+ Named actions are distinct from test `on_fail`/`on_pass` actions. The five supported
117
+ `dcVI` types are `vforce`, `vmeas`, `imeas`, `vforce_slewrate`, and `poweroff`.
118
+ `irange` is an integer code 0..6, not a physical current; `slewrate` is 0..7 and
119
+ `gm` is 0..3. Force/clamp values use explicit physical units, and limits are checked
120
+ against the selected range. See the [language reference](docs/LANGUAGE.md#action).
121
+
122
+ Hosts implement `ActionBackend` from `atelang-core/runtime` and pass it to
123
+ `run(path, host, options, rootText, controller, methodBackend, actionBackend)` or
124
+ `runFromUnit(unit, options, controller, methodBackend, actionBackend)`. Its async
125
+ `run(context)` receives the named action, expanded signal pins, SI-valued params,
126
+ active site mask, declaration path, and resolved levels/timing. Return
127
+ `{ ok: true, value?, note? }` or `{ ok: false, error }`. A returned `Value` can be
128
+ captured using `measurement = execute MeasureAction`.
129
+
130
+ No hardware driver or automatic action simulation is bundled. Missing backends,
131
+ backend errors, and thrown exceptions stop the flow and produce runtime diagnostics;
132
+ they never fall back to fabricated measurements. External method backends also receive
133
+ `resolvedLevels`/`resolvedTiming`; Python functions receive `resolved_levels` and
134
+ `resolved_timing` with quantity objects under `props` and `pins`.
135
+
136
+ `dutBoard` fully replaces `pinmap`, including AST types (`DutBoardDecl`), symbol table
137
+ keys (`dutBoards`), and pin ownership (`dutBoard`). There is no legacy alias. IR version
138
+ 2 rejects version-1 artifacts; rename old source declarations and recompile.
139
+
140
+ ## Local Plugin Development
141
+
142
+ The plugin declares `atelang-core` as `file:../atelang-core`. Its `.npmrc`
143
+ sets `install-links=true`, so npm packs and copies the core into `node_modules`
144
+ instead of linking to the sibling source directory. Build/install the core first,
145
+ then run `npm install` in `atelang-vscode/`.
146
+
147
+ After changing core sources, run these from `atelang-vscode/` to refresh that copy:
148
+
149
+ ```bash
150
+ npm --prefix ../atelang-core run build
151
+ npm uninstall atelang-core --no-save
152
+ npm install
153
+ npm run build
154
+ ```
155
+
156
+ Removing the installed copy first makes npm repack same-version local changes;
157
+ `--no-save` keeps the dependency declaration and lockfile.
158
+
159
+ ## Compatibility and References
160
+
161
+ The npm package version tracks the public API and in-memory AST contract.
162
+ `IR_VERSION` (currently `2`) separately tracks the serialized `.ateb` schema;
163
+ an incompatible serialized AST change requires an IR version bump. During `0.x`,
164
+ review API/AST compatibility when updating the package.
165
+
166
+ See the [language reference](docs/LANGUAGE.md) and [binary format](docs/BINARY_FORMAT.md).
167
+ Example projects remain in the separately distributed sibling `../atelang-examples/`.
@@ -0,0 +1,44 @@
1
+ /**
2
+ * binary.ts — Pure codec for the `.ateb` compiled-artifact container.
3
+ *
4
+ * Layout (little-endian):
5
+ *
6
+ * offset size field
7
+ * 0 4 magic = "ATEB" (0x41 0x54 0x45 0x42)
8
+ * 4 2 version:u16 — IR_VERSION the artifact was written with
9
+ * 6 2 flags:u16 — bit0 = payload is compressed
10
+ * 8 4 payloadLen:u32 — byte length of the payload as stored
11
+ * 12 N payload — UTF-8 JSON of the CompilationUnit
12
+ *
13
+ * Compression is *injected* (`Compressor`) so this module stays free of Node/vscode
14
+ * and is fully testable in memory; the CLI/extension supply a zlib-backed one. Every
15
+ * failure path throws an `AteBinaryError` with a stable `code` and a human-readable
16
+ * message, so a corrupt or foreign file produces a precise diagnostic instead of a
17
+ * stack trace.
18
+ */
19
+ import { type CompilationUnit } from "./ir";
20
+ export declare const MAGIC = "ATEB";
21
+ export declare const HEADER_SIZE = 12;
22
+ export declare const FLAG_COMPRESSED = 1;
23
+ export type BinaryErrorCode = "too-short" | "bad-magic" | "unsupported-version" | "unknown-flags" | "truncated" | "needs-decompressor" | "decompress-failed" | "bad-json" | "bad-shape";
24
+ export declare class AteBinaryError extends Error {
25
+ readonly code: BinaryErrorCode;
26
+ constructor(code: BinaryErrorCode, message: string);
27
+ }
28
+ /** Injected (de)compression so the core codec has no runtime dependencies. */
29
+ export interface Compressor {
30
+ deflate(bytes: Uint8Array): Uint8Array;
31
+ inflate(bytes: Uint8Array): Uint8Array;
32
+ }
33
+ export interface EncodeOptions {
34
+ /** Compress the JSON payload. Requires `compressor` when true. Default false. */
35
+ compress?: boolean;
36
+ compressor?: Compressor;
37
+ }
38
+ export interface DecodeOptions {
39
+ compressor?: Compressor;
40
+ }
41
+ export declare function encodeBinary(unit: CompilationUnit, opts?: EncodeOptions): Uint8Array;
42
+ /** True when `bytes` begins with the ATEB magic (cheap content sniff). */
43
+ export declare function looksLikeBinary(bytes: Uint8Array): boolean;
44
+ export declare function decodeBinary(bytes: Uint8Array, opts?: DecodeOptions): CompilationUnit;
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AteBinaryError = exports.FLAG_COMPRESSED = exports.HEADER_SIZE = exports.MAGIC = void 0;
4
+ exports.encodeBinary = encodeBinary;
5
+ exports.looksLikeBinary = looksLikeBinary;
6
+ exports.decodeBinary = decodeBinary;
7
+ /**
8
+ * binary.ts — Pure codec for the `.ateb` compiled-artifact container.
9
+ *
10
+ * Layout (little-endian):
11
+ *
12
+ * offset size field
13
+ * 0 4 magic = "ATEB" (0x41 0x54 0x45 0x42)
14
+ * 4 2 version:u16 — IR_VERSION the artifact was written with
15
+ * 6 2 flags:u16 — bit0 = payload is compressed
16
+ * 8 4 payloadLen:u32 — byte length of the payload as stored
17
+ * 12 N payload — UTF-8 JSON of the CompilationUnit
18
+ *
19
+ * Compression is *injected* (`Compressor`) so this module stays free of Node/vscode
20
+ * and is fully testable in memory; the CLI/extension supply a zlib-backed one. Every
21
+ * failure path throws an `AteBinaryError` with a stable `code` and a human-readable
22
+ * message, so a corrupt or foreign file produces a precise diagnostic instead of a
23
+ * stack trace.
24
+ */
25
+ const ir_1 = require("./ir");
26
+ exports.MAGIC = "ATEB";
27
+ exports.HEADER_SIZE = 12;
28
+ exports.FLAG_COMPRESSED = 0x0001;
29
+ class AteBinaryError extends Error {
30
+ code;
31
+ constructor(code, message) {
32
+ super(message);
33
+ this.name = "AteBinaryError";
34
+ this.code = code;
35
+ }
36
+ }
37
+ exports.AteBinaryError = AteBinaryError;
38
+ const textEncoder = new TextEncoder();
39
+ const textDecoder = new TextDecoder();
40
+ function isUnit(x) {
41
+ if (!x || typeof x !== "object")
42
+ return false;
43
+ const u = x;
44
+ return typeof u.version === "number" && typeof u.entry === "string" && Array.isArray(u.modules);
45
+ }
46
+ function encodeBinary(unit, opts = {}) {
47
+ const json = JSON.stringify(unit);
48
+ let payload = textEncoder.encode(json);
49
+ let flags = 0;
50
+ if (opts.compress) {
51
+ if (!opts.compressor) {
52
+ throw new AteBinaryError("needs-decompressor", "compression requested but no Compressor was provided");
53
+ }
54
+ payload = opts.compressor.deflate(payload);
55
+ flags |= exports.FLAG_COMPRESSED;
56
+ }
57
+ const out = new Uint8Array(exports.HEADER_SIZE + payload.length);
58
+ const view = new DataView(out.buffer);
59
+ for (let i = 0; i < exports.MAGIC.length; i++)
60
+ out[i] = exports.MAGIC.charCodeAt(i);
61
+ view.setUint16(4, unit.version, true);
62
+ view.setUint16(6, flags, true);
63
+ view.setUint32(8, payload.length, true);
64
+ out.set(payload, exports.HEADER_SIZE);
65
+ return out;
66
+ }
67
+ /** True when `bytes` begins with the ATEB magic (cheap content sniff). */
68
+ function looksLikeBinary(bytes) {
69
+ if (bytes.length < exports.MAGIC.length)
70
+ return false;
71
+ for (let i = 0; i < exports.MAGIC.length; i++) {
72
+ if (bytes[i] !== exports.MAGIC.charCodeAt(i))
73
+ return false;
74
+ }
75
+ return true;
76
+ }
77
+ function decodeBinary(bytes, opts = {}) {
78
+ if (bytes.length < exports.HEADER_SIZE) {
79
+ throw new AteBinaryError("too-short", `not an ATELang binary: file is only ${bytes.length} byte(s), expected a ${exports.HEADER_SIZE}-byte header`);
80
+ }
81
+ if (!looksLikeBinary(bytes)) {
82
+ const got = textDecoder.decode(bytes.slice(0, 4));
83
+ throw new AteBinaryError("bad-magic", `not an ATELang binary: expected magic "${exports.MAGIC}" but found "${got}"`);
84
+ }
85
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
86
+ const version = view.getUint16(4, true);
87
+ const flags = view.getUint16(6, true);
88
+ const payloadLen = view.getUint32(8, true);
89
+ if (version > ir_1.IR_VERSION) {
90
+ throw new AteBinaryError("unsupported-version", `artifact was written by a newer compiler (version ${version}; this build understands up to ${ir_1.IR_VERSION}) — recompile the source`);
91
+ }
92
+ if (version < ir_1.IR_VERSION) {
93
+ throw new AteBinaryError("unsupported-version", `artifact version ${version} is incompatible; recompile using dutBoard`);
94
+ }
95
+ if ((flags & ~exports.FLAG_COMPRESSED) !== 0) {
96
+ throw new AteBinaryError("unknown-flags", `artifact uses unknown feature flags (0x${flags.toString(16)}) — recompile with this version`);
97
+ }
98
+ if (exports.HEADER_SIZE + payloadLen > bytes.length) {
99
+ throw new AteBinaryError("truncated", `artifact is truncated: header declares a ${payloadLen}-byte payload but only ${bytes.length - exports.HEADER_SIZE} byte(s) are present`);
100
+ }
101
+ let payload = bytes.slice(exports.HEADER_SIZE, exports.HEADER_SIZE + payloadLen);
102
+ if (flags & exports.FLAG_COMPRESSED) {
103
+ if (!opts.compressor) {
104
+ throw new AteBinaryError("needs-decompressor", "artifact payload is compressed but no Compressor was provided");
105
+ }
106
+ try {
107
+ payload = opts.compressor.inflate(payload);
108
+ }
109
+ catch (e) {
110
+ throw new AteBinaryError("decompress-failed", `failed to decompress artifact payload: ${e.message}`);
111
+ }
112
+ }
113
+ let parsed;
114
+ try {
115
+ parsed = JSON.parse(textDecoder.decode(payload));
116
+ }
117
+ catch (e) {
118
+ throw new AteBinaryError("bad-json", `artifact payload is not valid JSON: ${e.message}`);
119
+ }
120
+ if (!isUnit(parsed)) {
121
+ throw new AteBinaryError("bad-shape", "artifact payload is missing required fields (version, entry, modules)");
122
+ }
123
+ if (parsed.version !== version)
124
+ throw new AteBinaryError("bad-shape", "payload version differs from header");
125
+ for (const module of parsed.modules) {
126
+ if (!module.ast || !Array.isArray(module.ast.body) || module.ast.body.some((node) => !["import", "dutBoard", "variables", "instrumentAction", "spec", "levels", "timing", "wavetable", "test", "flow", "methodExtern"].includes(node.kind))) {
127
+ throw new AteBinaryError("bad-shape", "artifact contains an unsupported declaration");
128
+ }
129
+ }
130
+ return parsed;
131
+ }
132
+ //# sourceMappingURL=binary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary.js","sourceRoot":"","sources":["../../src/compiler/binary.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * binary.ts — Pure codec for the `.ateb` compiled-artifact container.\n *\n * Layout (little-endian):\n *\n * offset size field\n * 0 4 magic = \"ATEB\" (0x41 0x54 0x45 0x42)\n * 4 2 version:u16 — IR_VERSION the artifact was written with\n * 6 2 flags:u16 — bit0 = payload is compressed\n * 8 4 payloadLen:u32 — byte length of the payload as stored\n * 12 N payload — UTF-8 JSON of the CompilationUnit\n *\n * Compression is *injected* (`Compressor`) so this module stays free of Node/vscode\n * and is fully testable in memory; the CLI/extension supply a zlib-backed one. Every\n * failure path throws an `AteBinaryError` with a stable `code` and a human-readable\n * message, so a corrupt or foreign file produces a precise diagnostic instead of a\n * stack trace.\n */\nimport { IR_VERSION, type CompilationUnit } from \"./ir\";\n\nexport const MAGIC = \"ATEB\";\nexport const HEADER_SIZE = 12;\nexport const FLAG_COMPRESSED = 0x0001;\n\nexport type BinaryErrorCode =\n | \"too-short\"\n | \"bad-magic\"\n | \"unsupported-version\"\n | \"unknown-flags\"\n | \"truncated\"\n | \"needs-decompressor\"\n | \"decompress-failed\"\n | \"bad-json\"\n | \"bad-shape\";\n\nexport class AteBinaryError extends Error {\n readonly code: BinaryErrorCode;\n constructor(code: BinaryErrorCode, message: string) {\n super(message);\n this.name = \"AteBinaryError\";\n this.code = code;\n }\n}\n\n/** Injected (de)compression so the core codec has no runtime dependencies. */\nexport interface Compressor {\n deflate(bytes: Uint8Array): Uint8Array;\n inflate(bytes: Uint8Array): Uint8Array;\n}\n\nexport interface EncodeOptions {\n /** Compress the JSON payload. Requires `compressor` when true. Default false. */\n compress?: boolean;\n compressor?: Compressor;\n}\n\nexport interface DecodeOptions {\n compressor?: Compressor;\n}\n\nconst textEncoder = new TextEncoder();\nconst textDecoder = new TextDecoder();\n\nfunction isUnit(x: unknown): x is CompilationUnit {\n if (!x || typeof x !== \"object\") return false;\n const u = x as Record<string, unknown>;\n return typeof u.version === \"number\" && typeof u.entry === \"string\" && Array.isArray(u.modules);\n}\n\nexport function encodeBinary(unit: CompilationUnit, opts: EncodeOptions = {}): Uint8Array {\n const json = JSON.stringify(unit);\n let payload: Uint8Array = textEncoder.encode(json);\n\n let flags = 0;\n if (opts.compress) {\n if (!opts.compressor) {\n throw new AteBinaryError(\"needs-decompressor\", \"compression requested but no Compressor was provided\");\n }\n payload = opts.compressor.deflate(payload);\n flags |= FLAG_COMPRESSED;\n }\n\n const out = new Uint8Array(HEADER_SIZE + payload.length);\n const view = new DataView(out.buffer);\n for (let i = 0; i < MAGIC.length; i++) out[i] = MAGIC.charCodeAt(i);\n view.setUint16(4, unit.version, true);\n view.setUint16(6, flags, true);\n view.setUint32(8, payload.length, true);\n out.set(payload, HEADER_SIZE);\n return out;\n}\n\n/** True when `bytes` begins with the ATEB magic (cheap content sniff). */\nexport function looksLikeBinary(bytes: Uint8Array): boolean {\n if (bytes.length < MAGIC.length) return false;\n for (let i = 0; i < MAGIC.length; i++) {\n if (bytes[i] !== MAGIC.charCodeAt(i)) return false;\n }\n return true;\n}\n\nexport function decodeBinary(bytes: Uint8Array, opts: DecodeOptions = {}): CompilationUnit {\n if (bytes.length < HEADER_SIZE) {\n throw new AteBinaryError(\"too-short\", `not an ATELang binary: file is only ${bytes.length} byte(s), expected a ${HEADER_SIZE}-byte header`);\n }\n if (!looksLikeBinary(bytes)) {\n const got = textDecoder.decode(bytes.slice(0, 4));\n throw new AteBinaryError(\"bad-magic\", `not an ATELang binary: expected magic \"${MAGIC}\" but found \"${got}\"`);\n }\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const version = view.getUint16(4, true);\n const flags = view.getUint16(6, true);\n const payloadLen = view.getUint32(8, true);\n\n if (version > IR_VERSION) {\n throw new AteBinaryError(\"unsupported-version\", `artifact was written by a newer compiler (version ${version}; this build understands up to ${IR_VERSION}) — recompile the source`);\n }\n if (version < IR_VERSION) {\n throw new AteBinaryError(\"unsupported-version\", `artifact version ${version} is incompatible; recompile using dutBoard`);\n }\n if ((flags & ~FLAG_COMPRESSED) !== 0) {\n throw new AteBinaryError(\"unknown-flags\", `artifact uses unknown feature flags (0x${flags.toString(16)}) — recompile with this version`);\n }\n if (HEADER_SIZE + payloadLen > bytes.length) {\n throw new AteBinaryError(\"truncated\", `artifact is truncated: header declares a ${payloadLen}-byte payload but only ${bytes.length - HEADER_SIZE} byte(s) are present`);\n }\n\n let payload: Uint8Array = bytes.slice(HEADER_SIZE, HEADER_SIZE + payloadLen);\n if (flags & FLAG_COMPRESSED) {\n if (!opts.compressor) {\n throw new AteBinaryError(\"needs-decompressor\", \"artifact payload is compressed but no Compressor was provided\");\n }\n try {\n payload = opts.compressor.inflate(payload);\n } catch (e) {\n throw new AteBinaryError(\"decompress-failed\", `failed to decompress artifact payload: ${(e as Error).message}`);\n }\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(textDecoder.decode(payload));\n } catch (e) {\n throw new AteBinaryError(\"bad-json\", `artifact payload is not valid JSON: ${(e as Error).message}`);\n }\n if (!isUnit(parsed)) {\n throw new AteBinaryError(\"bad-shape\", \"artifact payload is missing required fields (version, entry, modules)\");\n }\n if (parsed.version !== version) throw new AteBinaryError(\"bad-shape\", \"payload version differs from header\");\n for (const module of parsed.modules) {\n if (!module.ast || !Array.isArray(module.ast.body) || module.ast.body.some((node) => ![\"import\", \"dutBoard\", \"variables\", \"instrumentAction\", \"spec\", \"levels\", \"timing\", \"wavetable\", \"test\", \"flow\", \"methodExtern\"].includes(node.kind))) {\n throw new AteBinaryError(\"bad-shape\", \"artifact contains an unsupported declaration\");\n }\n }\n return parsed;\n}\n"]}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * compiler.ts — Front end: turn a root `.ate` file into a self-contained
3
+ * `CompilationUnit`, or report precisely why it could not be compiled.
4
+ *
5
+ * This is the *only* place lexing, parsing, import resolution, and semantic analysis
6
+ * happen for a build. Execution of a compiled artifact (`runner.runFromUnit`) skips
7
+ * all of it and simply re-derives the symbol table from the bundled ASTs, so a flow
8
+ * that compiles cleanly here runs identically from source or from the binary.
9
+ *
10
+ * Pure: depends only on the `language/` layer and `ir.ts` (no Node, no vscode).
11
+ */
12
+ import { type AnalyzeResult } from "../language/analyzer";
13
+ import type { Program } from "../language/ast";
14
+ import type { Diagnostic } from "../language/diagnostics";
15
+ import { type Host, type LoadResult } from "../language/loader";
16
+ import { type CompilationUnit } from "./ir";
17
+ export interface CompileResult {
18
+ load: LoadResult;
19
+ analysis: AnalyzeResult;
20
+ rootProgram: Program | null;
21
+ }
22
+ /** Load and analyze a project, optionally using an unsaved root buffer. */
23
+ export declare function compile(rootPath: string, host: Host, rootText?: string): CompileResult;
24
+ export interface CompileOutcome {
25
+ /** Present only when compilation succeeded (no error-severity diagnostics). */
26
+ unit?: CompilationUnit;
27
+ /** Every diagnostic produced (errors *and* warnings), for reporting. */
28
+ diagnostics: Diagnostic[];
29
+ /** True when `unit` was produced. */
30
+ ok: boolean;
31
+ }
32
+ export interface CompileUnitOptions {
33
+ /** Compile an unsaved buffer for the root while still resolving imports from disk. */
34
+ rootText?: string;
35
+ }
36
+ /**
37
+ * Compile `rootPath` into a `CompilationUnit`.
38
+ *
39
+ * Fails (ok:false, no unit) if *any* error-severity diagnostic is produced — syntax
40
+ * errors, unresolved imports, duplicate declarations, undefined references, or unit
41
+ * (dimension) mismatches. Warnings (e.g. an unknown test method that the simulator can
42
+ * still stub) do not block the build but are returned for reporting.
43
+ */
44
+ export declare function compileToUnit(rootPath: string, host: Host, opts?: CompileUnitOptions): CompileOutcome;
45
+ /**
46
+ * Rebuild a `LoadResult` from a compiled unit so the analyzer can re-derive the symbol
47
+ * table. Errors/missingImports are empty: a unit only exists if it compiled cleanly.
48
+ */
49
+ export declare function loadResultFromUnit(unit: CompilationUnit): LoadResult;
50
+ /** Format a diagnostic as `path:line:col SEVERITY message [code]` (1-based line/col). */
51
+ export declare function formatDiagnostic(d: Diagnostic): string;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.compile = compile;
4
+ exports.compileToUnit = compileToUnit;
5
+ exports.loadResultFromUnit = loadResultFromUnit;
6
+ exports.formatDiagnostic = formatDiagnostic;
7
+ /**
8
+ * compiler.ts — Front end: turn a root `.ate` file into a self-contained
9
+ * `CompilationUnit`, or report precisely why it could not be compiled.
10
+ *
11
+ * This is the *only* place lexing, parsing, import resolution, and semantic analysis
12
+ * happen for a build. Execution of a compiled artifact (`runner.runFromUnit`) skips
13
+ * all of it and simply re-derives the symbol table from the bundled ASTs, so a flow
14
+ * that compiles cleanly here runs identically from source or from the binary.
15
+ *
16
+ * Pure: depends only on the `language/` layer and `ir.ts` (no Node, no vscode).
17
+ */
18
+ const analyzer_1 = require("../language/analyzer");
19
+ const loader_1 = require("../language/loader");
20
+ const ir_1 = require("./ir");
21
+ /** Load and analyze a project, optionally using an unsaved root buffer. */
22
+ function compile(rootPath, host, rootText) {
23
+ const effectiveHost = rootText !== undefined
24
+ ? { readFile: (p) => (p === rootPath ? rootText : host.readFile(p)), resolve: host.resolve.bind(host) }
25
+ : host;
26
+ const load = (0, loader_1.loadProgram)(rootPath, effectiveHost);
27
+ const analysis = (0, analyzer_1.analyze)(load);
28
+ const rootProgram = load.programs.find((p) => p.path === rootPath) ?? load.programs[load.programs.length - 1] ?? null;
29
+ return { load, analysis, rootProgram };
30
+ }
31
+ /**
32
+ * Compile `rootPath` into a `CompilationUnit`.
33
+ *
34
+ * Fails (ok:false, no unit) if *any* error-severity diagnostic is produced — syntax
35
+ * errors, unresolved imports, duplicate declarations, undefined references, or unit
36
+ * (dimension) mismatches. Warnings (e.g. an unknown test method that the simulator can
37
+ * still stub) do not block the build but are returned for reporting.
38
+ */
39
+ function compileToUnit(rootPath, host, opts = {}) {
40
+ const effectiveHost = opts.rootText !== undefined
41
+ ? { readFile: (p) => (p === rootPath ? opts.rootText : host.readFile(p)), resolve: host.resolve.bind(host) }
42
+ : host;
43
+ const load = (0, loader_1.loadProgram)(rootPath, effectiveHost);
44
+ const analysis = (0, analyzer_1.analyze)(load);
45
+ const diagnostics = analysis.diagnostics;
46
+ const hasError = diagnostics.some((d) => d.severity === "error");
47
+ if (hasError || load.programs.length === 0) {
48
+ return { ok: false, diagnostics };
49
+ }
50
+ const modules = load.programs.map((program) => stripModule(program));
51
+ const unit = {
52
+ version: ir_1.IR_VERSION,
53
+ entry: rootPath,
54
+ compiledAt: new Date().toISOString(),
55
+ modules,
56
+ };
57
+ return { ok: true, unit, diagnostics };
58
+ }
59
+ /** Hash + record a program's source, then return a copy with the text stripped. */
60
+ function stripModule(program) {
61
+ const source = program.source ?? "";
62
+ const sourceHash = (0, ir_1.hashSource)(source);
63
+ const sourceLength = new TextEncoder().encode(source).length;
64
+ // Shallow copy: the body is never mutated, and JSON serialization drops nothing else.
65
+ const ast = { ...program, source: "" };
66
+ return { path: program.path, sourceHash, sourceLength, ast };
67
+ }
68
+ /**
69
+ * Rebuild a `LoadResult` from a compiled unit so the analyzer can re-derive the symbol
70
+ * table. Errors/missingImports are empty: a unit only exists if it compiled cleanly.
71
+ */
72
+ function loadResultFromUnit(unit) {
73
+ return {
74
+ programs: unit.modules.map((m) => m.ast),
75
+ errors: [],
76
+ missingImports: [],
77
+ };
78
+ }
79
+ /** Format a diagnostic as `path:line:col SEVERITY message [code]` (1-based line/col). */
80
+ function formatDiagnostic(d) {
81
+ const line = d.range.start.line + 1;
82
+ const col = d.range.start.character + 1;
83
+ const code = d.code ? ` [${d.code}]` : "";
84
+ return `${d.path}:${line}:${col} ${d.severity.toUpperCase()} ${d.message}${code}`;
85
+ }
86
+ //# sourceMappingURL=compiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler.js","sourceRoot":"","sources":["../../src/compiler/compiler.ts"],"names":[],"mappings":";;AAwBA,0BAQC;AAwBD,sCAsBC;AAgBD,gDAMC;AAGD,4CAKC;AA5GD;;;;;;;;;;GAUG;AACH,mDAAmE;AAGnE,+CAA6E;AAC7E,6BAAyF;AAQzF,2EAA2E;AAC3E,SAAgB,OAAO,CAAC,QAAgB,EAAE,IAAU,EAAE,QAAiB;IACrE,MAAM,aAAa,GAAS,QAAQ,KAAK,SAAS;QAChD,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACvG,CAAC,CAAC,IAAI,CAAC;IACT,MAAM,IAAI,GAAG,IAAA,oBAAW,EAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,IAAA,kBAAO,EAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC;IACtH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AACzC,CAAC;AAgBD;;;;;;;GAOG;AACH,SAAgB,aAAa,CAAC,QAAgB,EAAE,IAAU,EAAE,OAA2B,EAAE;IACvF,MAAM,aAAa,GAAS,IAAI,CAAC,QAAQ,KAAK,SAAS;QACrD,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAC7G,CAAC,CAAC,IAAI,CAAC;IAET,MAAM,IAAI,GAAG,IAAA,oBAAW,EAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,IAAA,kBAAO,EAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC;IAEzC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;IACjE,IAAI,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IACpC,CAAC;IAED,MAAM,OAAO,GAAqB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;IACvF,MAAM,IAAI,GAAoB;QAC5B,OAAO,EAAE,eAAU;QACnB,KAAK,EAAE,QAAQ;QACf,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,OAAO;KACR,CAAC;IACF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AACzC,CAAC;AAED,mFAAmF;AACnF,SAAS,WAAW,CAAC,OAAgB;IACnC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;IACpC,MAAM,UAAU,GAAG,IAAA,eAAU,EAAC,MAAM,CAAC,CAAC;IACtC,MAAM,YAAY,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;IAC7D,sFAAsF;IACtF,MAAM,GAAG,GAAY,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAChD,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;AAC/D,CAAC;AAED;;;GAGG;AACH,SAAgB,kBAAkB,CAAC,IAAqB;IACtD,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QACxC,MAAM,EAAE,EAAE;QACV,cAAc,EAAE,EAAE;KACnB,CAAC;AACJ,CAAC;AAED,yFAAyF;AACzF,SAAgB,gBAAgB,CAAC,CAAa;IAC5C,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1C,OAAO,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;AACpF,CAAC","sourcesContent":["/**\n * compiler.ts — Front end: turn a root `.ate` file into a self-contained\n * `CompilationUnit`, or report precisely why it could not be compiled.\n *\n * This is the *only* place lexing, parsing, import resolution, and semantic analysis\n * happen for a build. Execution of a compiled artifact (`runner.runFromUnit`) skips\n * all of it and simply re-derives the symbol table from the bundled ASTs, so a flow\n * that compiles cleanly here runs identically from source or from the binary.\n *\n * Pure: depends only on the `language/` layer and `ir.ts` (no Node, no vscode).\n */\nimport { analyze, type AnalyzeResult } from \"../language/analyzer\";\nimport type { Program } from \"../language/ast\";\nimport type { Diagnostic } from \"../language/diagnostics\";\nimport { loadProgram, type Host, type LoadResult } from \"../language/loader\";\nimport { hashSource, IR_VERSION, type CompilationUnit, type CompiledModule } from \"./ir\";\n\nexport interface CompileResult {\n load: LoadResult;\n analysis: AnalyzeResult;\n rootProgram: Program | null;\n}\n\n/** Load and analyze a project, optionally using an unsaved root buffer. */\nexport function compile(rootPath: string, host: Host, rootText?: string): CompileResult {\n const effectiveHost: Host = rootText !== undefined\n ? { readFile: (p) => (p === rootPath ? rootText : host.readFile(p)), resolve: host.resolve.bind(host) }\n : host;\n const load = loadProgram(rootPath, effectiveHost);\n const analysis = analyze(load);\n const rootProgram = load.programs.find((p) => p.path === rootPath) ?? load.programs[load.programs.length - 1] ?? null;\n return { load, analysis, rootProgram };\n}\n\nexport interface CompileOutcome {\n /** Present only when compilation succeeded (no error-severity diagnostics). */\n unit?: CompilationUnit;\n /** Every diagnostic produced (errors *and* warnings), for reporting. */\n diagnostics: Diagnostic[];\n /** True when `unit` was produced. */\n ok: boolean;\n}\n\nexport interface CompileUnitOptions {\n /** Compile an unsaved buffer for the root while still resolving imports from disk. */\n rootText?: string;\n}\n\n/**\n * Compile `rootPath` into a `CompilationUnit`.\n *\n * Fails (ok:false, no unit) if *any* error-severity diagnostic is produced — syntax\n * errors, unresolved imports, duplicate declarations, undefined references, or unit\n * (dimension) mismatches. Warnings (e.g. an unknown test method that the simulator can\n * still stub) do not block the build but are returned for reporting.\n */\nexport function compileToUnit(rootPath: string, host: Host, opts: CompileUnitOptions = {}): CompileOutcome {\n const effectiveHost: Host = opts.rootText !== undefined\n ? { readFile: (p) => (p === rootPath ? opts.rootText! : host.readFile(p)), resolve: host.resolve.bind(host) }\n : host;\n\n const load = loadProgram(rootPath, effectiveHost);\n const analysis = analyze(load);\n const diagnostics = analysis.diagnostics;\n\n const hasError = diagnostics.some((d) => d.severity === \"error\");\n if (hasError || load.programs.length === 0) {\n return { ok: false, diagnostics };\n }\n\n const modules: CompiledModule[] = load.programs.map((program) => stripModule(program));\n const unit: CompilationUnit = {\n version: IR_VERSION,\n entry: rootPath,\n compiledAt: new Date().toISOString(),\n modules,\n };\n return { ok: true, unit, diagnostics };\n}\n\n/** Hash + record a program's source, then return a copy with the text stripped. */\nfunction stripModule(program: Program): CompiledModule {\n const source = program.source ?? \"\";\n const sourceHash = hashSource(source);\n const sourceLength = new TextEncoder().encode(source).length;\n // Shallow copy: the body is never mutated, and JSON serialization drops nothing else.\n const ast: Program = { ...program, source: \"\" };\n return { path: program.path, sourceHash, sourceLength, ast };\n}\n\n/**\n * Rebuild a `LoadResult` from a compiled unit so the analyzer can re-derive the symbol\n * table. Errors/missingImports are empty: a unit only exists if it compiled cleanly.\n */\nexport function loadResultFromUnit(unit: CompilationUnit): LoadResult {\n return {\n programs: unit.modules.map((m) => m.ast),\n errors: [],\n missingImports: [],\n };\n}\n\n/** Format a diagnostic as `path:line:col SEVERITY message [code]` (1-based line/col). */\nexport function formatDiagnostic(d: Diagnostic): string {\n const line = d.range.start.line + 1;\n const col = d.range.start.character + 1;\n const code = d.code ? ` [${d.code}]` : \"\";\n return `${d.path}:${line}:${col} ${d.severity.toUpperCase()} ${d.message}${code}`;\n}\n"]}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * index.ts — Public surface of the ATEDSL compiler.
3
+ *
4
+ * Pure entry points (usable everywhere):
5
+ * - compileToUnit / loadResultFromUnit / formatDiagnostic
6
+ * - encodeBinary / decodeBinary / looksLikeBinary / AteBinaryError
7
+ * - IR types + hashSource
8
+ *
9
+ * Filesystem and compression adapters are supplied by consumers, so the core
10
+ * keeps zero runtime dependencies.
11
+ */
12
+ export * from "./ir";
13
+ export * from "./binary";
14
+ export * from "./compiler";
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ /**
18
+ * index.ts — Public surface of the ATEDSL compiler.
19
+ *
20
+ * Pure entry points (usable everywhere):
21
+ * - compileToUnit / loadResultFromUnit / formatDiagnostic
22
+ * - encodeBinary / decodeBinary / looksLikeBinary / AteBinaryError
23
+ * - IR types + hashSource
24
+ *
25
+ * Filesystem and compression adapters are supplied by consumers, so the core
26
+ * keeps zero runtime dependencies.
27
+ */
28
+ __exportStar(require("./ir"), exports);
29
+ __exportStar(require("./binary"), exports);
30
+ __exportStar(require("./compiler"), exports);
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/compiler/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;;;;;;;;;;GAUG;AACH,uCAAqB;AACrB,2CAAyB;AACzB,6CAA2B","sourcesContent":["/**\n * index.ts — Public surface of the ATEDSL compiler.\n *\n * Pure entry points (usable everywhere):\n * - compileToUnit / loadResultFromUnit / formatDiagnostic\n * - encodeBinary / decodeBinary / looksLikeBinary / AteBinaryError\n * - IR types + hashSource\n *\n * Filesystem and compression adapters are supplied by consumers, so the core\n * keeps zero runtime dependencies.\n */\nexport * from \"./ir\";\nexport * from \"./binary\";\nexport * from \"./compiler\";\n"]}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * ir.ts — Intermediate representation for a compiled ATEDSL program.
3
+ *
4
+ * A `CompilationUnit` is the *self-contained* result of compiling one root `.ate`
5
+ * file: it bundles the whole import graph (parsed ASTs in dependency order, root
6
+ * last) plus enough metadata to validate, cache, and re-analyze the program without
7
+ * ever touching the original sources again.
8
+ *
9
+ * This module is pure (no Node, no vscode): the AST nodes it wraps are already plain
10
+ * JSON-serializable data, so the unit round-trips through JSON in `binary.ts`.
11
+ */
12
+ import type { Program } from "../language/ast";
13
+ /** Bumped whenever the on-disk IR shape changes in an incompatible way. */
14
+ export declare const IR_VERSION = 2;
15
+ /** One compiled module: the parsed AST plus a hash of the source it came from. */
16
+ export interface CompiledModule {
17
+ /** Path the module was loaded from (kept for diagnostics + Python-method resolution). */
18
+ path: string;
19
+ /** FNV-1a hash of the original source text, as 8 lowercase hex chars. */
20
+ sourceHash: string;
21
+ /** Byte length of the original source (informational; helps staleness reports). */
22
+ sourceLength: number;
23
+ /** Parsed AST. `source` is stripped to "" to keep the artifact compact. */
24
+ ast: Program;
25
+ }
26
+ export interface CompilationUnit {
27
+ /** IR/format version this unit was produced with. */
28
+ version: number;
29
+ /** Path of the root module (the file that was compiled). */
30
+ entry: string;
31
+ /** ISO-8601 timestamp of when the unit was built. */
32
+ compiledAt: string;
33
+ /** Modules in dependency order — imports before importers, root last. */
34
+ modules: CompiledModule[];
35
+ }
36
+ /**
37
+ * Deterministic 32-bit FNV-1a hash of a string's UTF-8 bytes, as 8 hex chars.
38
+ *
39
+ * We roll our own (instead of Node's `crypto`) so the compiler core stays free of
40
+ * runtime dependencies and behaves identically in the CLI, the extension host, and
41
+ * unit tests. It only needs to detect source changes, not resist attacks.
42
+ */
43
+ export declare function hashSource(text: string): string;
44
+ /** Total number of top-level declarations across every module (handy for logs). */
45
+ export declare function countDecls(unit: CompilationUnit): number;