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.
- package/LICENSE +21 -0
- package/README.md +166 -2
- package/dist/compiler/binary.d.ts +44 -0
- package/dist/compiler/binary.js +132 -0
- package/dist/compiler/binary.js.map +1 -0
- package/dist/compiler/compiler.d.ts +51 -0
- package/dist/compiler/compiler.js +86 -0
- package/dist/compiler/compiler.js.map +1 -0
- package/dist/compiler/index.d.ts +14 -0
- package/dist/compiler/index.js +31 -0
- package/dist/compiler/index.js.map +1 -0
- package/dist/compiler/ir.d.ts +45 -0
- package/dist/compiler/ir.js +32 -0
- package/dist/compiler/ir.js.map +1 -0
- package/dist/debug/controller.d.ts +67 -0
- package/dist/debug/controller.js +127 -0
- package/dist/debug/controller.js.map +1 -0
- package/dist/debug/index.d.ts +2 -0
- package/dist/debug/index.js +19 -0
- package/dist/debug/index.js.map +1 -0
- package/dist/debug/lineMap.d.ts +58 -0
- package/dist/debug/lineMap.js +102 -0
- package/dist/debug/lineMap.js.map +1 -0
- package/dist/editor/completion.d.ts +8 -0
- package/dist/editor/completion.js +118 -0
- package/dist/editor/completion.js.map +1 -0
- package/dist/editor/hover.d.ts +10 -0
- package/dist/editor/hover.js +98 -0
- package/dist/editor/hover.js.map +1 -0
- package/dist/editor/index.d.ts +2 -0
- package/dist/editor/index.js +19 -0
- package/dist/editor/index.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/language/analyzer.d.ts +12 -0
- package/dist/language/analyzer.js +344 -0
- package/dist/language/analyzer.js.map +1 -0
- package/dist/language/ast.d.ts +290 -0
- package/dist/language/ast.js +11 -0
- package/dist/language/ast.js.map +1 -0
- package/dist/language/configuration.d.ts +10 -0
- package/dist/language/configuration.js +190 -0
- package/dist/language/configuration.js.map +1 -0
- package/dist/language/definition.d.ts +22 -0
- package/dist/language/definition.js +72 -0
- package/dist/language/definition.js.map +1 -0
- package/dist/language/diagnostics.d.ts +15 -0
- package/dist/language/diagnostics.js +3 -0
- package/dist/language/diagnostics.js.map +1 -0
- package/dist/language/lexer.d.ts +41 -0
- package/dist/language/lexer.js +362 -0
- package/dist/language/lexer.js.map +1 -0
- package/dist/language/loader.d.ts +33 -0
- package/dist/language/loader.js +60 -0
- package/dist/language/loader.js.map +1 -0
- package/dist/language/parser.d.ts +123 -0
- package/dist/language/parser.js +1217 -0
- package/dist/language/parser.js.map +1 -0
- package/dist/language/symbols.d.ts +97 -0
- package/dist/language/symbols.js +152 -0
- package/dist/language/symbols.js.map +1 -0
- package/dist/language/units.d.ts +47 -0
- package/dist/language/units.js +177 -0
- package/dist/language/units.js.map +1 -0
- package/dist/node/binaryNode.d.ts +28 -0
- package/dist/node/binaryNode.js +112 -0
- package/dist/node/binaryNode.js.map +1 -0
- package/dist/node/index.d.ts +3 -0
- package/dist/node/index.js +20 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/nodeHost.d.ts +2 -0
- package/dist/node/nodeHost.js +60 -0
- package/dist/node/nodeHost.js.map +1 -0
- package/dist/node/pythonNode.d.ts +21 -0
- package/dist/node/pythonNode.js +167 -0
- package/dist/node/pythonNode.js.map +1 -0
- package/dist/runtime/action.d.ts +25 -0
- package/dist/runtime/action.js +3 -0
- package/dist/runtime/action.js.map +1 -0
- package/dist/runtime/datalog.d.ts +5 -0
- package/dist/runtime/datalog.js +127 -0
- package/dist/runtime/datalog.js.map +1 -0
- package/dist/runtime/env.d.ts +18 -0
- package/dist/runtime/env.js +61 -0
- package/dist/runtime/env.js.map +1 -0
- package/dist/runtime/eval.d.ts +24 -0
- package/dist/runtime/eval.js +227 -0
- package/dist/runtime/eval.js.map +1 -0
- package/dist/runtime/executor.d.ts +36 -0
- package/dist/runtime/executor.js +676 -0
- package/dist/runtime/executor.js.map +1 -0
- package/dist/runtime/index.d.ts +10 -0
- package/dist/runtime/index.js +27 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/python.d.ts +159 -0
- package/dist/runtime/python.js +245 -0
- package/dist/runtime/python.js.map +1 -0
- package/dist/runtime/runner.d.ts +27 -0
- package/dist/runtime/runner.js +94 -0
- package/dist/runtime/runner.js.map +1 -0
- package/dist/runtime/simulator.d.ts +39 -0
- package/dist/runtime/simulator.js +113 -0
- package/dist/runtime/simulator.js.map +1 -0
- package/dist/runtime/types.d.ts +165 -0
- package/dist/runtime/types.js +3 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/runtime/values.d.ts +45 -0
- package/dist/runtime/values.js +79 -0
- package/dist/runtime/values.js.map +1 -0
- package/docs/BINARY_FORMAT.md +197 -0
- package/docs/LANGUAGE.md +499 -0
- package/package.json +67 -4
- 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
|
-
#
|
|
1
|
+
# atelang-core
|
|
2
2
|
|
|
3
|
-
|
|
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":"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","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;
|