@tsplc/compiler 0.0.0-stage → 0.2.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 +16 -2
- package/backends/codesys/config.ts +54 -0
- package/backends/codesys/emit.ts +1063 -0
- package/backends/codesys/engineering.ts +88 -0
- package/backends/codesys/http.ts +598 -0
- package/backends/codesys/index.ts +12 -0
- package/backends/codesys/io-paths.ts +103 -0
- package/backends/codesys/names.ts +76 -0
- package/backends/codesys/numeric.ts +356 -0
- package/backends/codesys/plan.ts +512 -0
- package/backends/codesys/publication.ts +59 -0
- package/backends/codesys/storage.ts +63 -0
- package/backends/codesys/task-access.ts +118 -0
- package/backends/codesys/types.ts +178 -0
- package/backends/codesys/vendor.ts +108 -0
- package/dist/cli.js +1396 -0
- package/dist/cli.js.map +16 -0
- package/dist/clock.js +8 -0
- package/dist/clock.js.map +10 -0
- package/dist/codesys.js +2587 -0
- package/dist/codesys.js.map +22 -0
- package/dist/elaborate-capture.js +118 -0
- package/dist/elaborate-capture.js.map +10 -0
- package/dist/index.js +6859 -0
- package/dist/index.js.map +25 -0
- package/dist/ir.js +1888 -0
- package/dist/ir.js.map +22 -0
- package/dist/math.js +24 -0
- package/dist/math.js.map +10 -0
- package/dist/project.js +429 -0
- package/dist/project.js.map +11 -0
- package/ir/aggregates.ts +333 -0
- package/ir/allocation.ts +74 -0
- package/ir/core-model.ts +116 -0
- package/ir/core.ts +63 -0
- package/ir/declarations.ts +201 -0
- package/ir/diagnostics.ts +43 -0
- package/ir/domains.ts +96 -0
- package/ir/index.ts +7 -0
- package/ir/link.ts +176 -0
- package/ir/model.ts +268 -0
- package/ir/normalization-error.ts +10 -0
- package/ir/routine.ts +826 -0
- package/ir/scalars.ts +675 -0
- package/ir/types.ts +70 -0
- package/package.json +106 -4
- package/project/artifacts.ts +277 -0
- package/project/cli.ts +305 -0
- package/project/index.ts +1 -0
- package/project/plant.ts +437 -0
- package/project/project.ts +312 -0
- package/project/server.ts +83 -0
- package/src/frontend/async.ts +1060 -0
- package/src/frontend/blocks.ts +419 -0
- package/src/frontend/configuration.ts +167 -0
- package/src/frontend/const-functions.ts +153 -0
- package/src/frontend/cooperative.ts +75 -0
- package/src/frontend/elaborate/capture.ts +138 -0
- package/src/frontend/elaborate/graph.ts +94 -0
- package/src/frontend/elaborate/index.ts +302 -0
- package/src/frontend/elaborate/layouts.ts +390 -0
- package/src/frontend/elaborate/model.ts +177 -0
- package/src/frontend/elaborate/specialize.ts +2280 -0
- package/src/frontend/exposure.ts +147 -0
- package/src/frontend/module-graph.ts +63 -0
- package/src/frontend/promises.ts +751 -0
- package/src/frontend/services.ts +435 -0
- package/src/frontend/types.ts +578 -0
- package/src/frontend/typescript.ts +2442 -0
- package/src/index.ts +7 -0
- package/stdlib/clock.ts +2 -0
- package/stdlib/math.ts +19 -0
- package/types/async.d.ts +81 -0
- package/types/clock.d.ts +4 -0
- package/types/config.d.ts +2 -0
- package/types/data-types.d.ts +31 -0
- package/types/globals.d.ts +40 -0
- package/types/index.d.ts +111 -0
- package/types/plc.d.ts +5 -0
package/ir/model.ts
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import type { SourceSpan, Diagnostic } from "./diagnostics.ts";
|
|
2
|
+
import type { PlcType, SymbolId, TypeId } from "./types.ts";
|
|
3
|
+
|
|
4
|
+
export type Constant =
|
|
5
|
+
| { kind: "bool"; value: boolean }
|
|
6
|
+
| { kind: "integer"; value: string }
|
|
7
|
+
| { kind: "float"; value: number }
|
|
8
|
+
| { kind: "duration"; nanoseconds: string }
|
|
9
|
+
| { kind: "calendar"; value: string }
|
|
10
|
+
| { kind: "string"; value: string }
|
|
11
|
+
| { kind: "array"; items: readonly Constant[] }
|
|
12
|
+
| { kind: "record"; fields: Readonly<Record<string, Constant>> };
|
|
13
|
+
|
|
14
|
+
export interface Variable {
|
|
15
|
+
id: SymbolId;
|
|
16
|
+
name: string;
|
|
17
|
+
type: TypeId;
|
|
18
|
+
storage:
|
|
19
|
+
| "module"
|
|
20
|
+
| "local"
|
|
21
|
+
| "parameter"
|
|
22
|
+
| "input"
|
|
23
|
+
| "output"
|
|
24
|
+
| "field"
|
|
25
|
+
| "instance"
|
|
26
|
+
| "constant"
|
|
27
|
+
| "blockOutput";
|
|
28
|
+
mutable: boolean;
|
|
29
|
+
retain: boolean;
|
|
30
|
+
exported?: true;
|
|
31
|
+
exposure?: { name: string; version: string };
|
|
32
|
+
mode?: "inOut";
|
|
33
|
+
initial?: Constant;
|
|
34
|
+
span: SourceSpan;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface Place {
|
|
38
|
+
root: SymbolId;
|
|
39
|
+
path: readonly ({ kind: "field"; name: string } | { kind: "index"; value: Expression })[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type BinaryOperator =
|
|
43
|
+
| "add"
|
|
44
|
+
| "subtract"
|
|
45
|
+
| "multiply"
|
|
46
|
+
| "divide"
|
|
47
|
+
| "remainder"
|
|
48
|
+
| "equal"
|
|
49
|
+
| "notEqual"
|
|
50
|
+
| "less"
|
|
51
|
+
| "lessEqual"
|
|
52
|
+
| "greater"
|
|
53
|
+
| "greaterEqual"
|
|
54
|
+
| "and"
|
|
55
|
+
| "or"
|
|
56
|
+
| "bitAnd"
|
|
57
|
+
| "bitOr"
|
|
58
|
+
| "bitXor"
|
|
59
|
+
| "shiftLeft"
|
|
60
|
+
| "shiftRight";
|
|
61
|
+
|
|
62
|
+
export const comparisonOperators: ReadonlySet<BinaryOperator> = new Set([
|
|
63
|
+
"equal",
|
|
64
|
+
"notEqual",
|
|
65
|
+
"less",
|
|
66
|
+
"lessEqual",
|
|
67
|
+
"greater",
|
|
68
|
+
"greaterEqual",
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
export type Expression = { type: TypeId; span: SourceSpan } & (
|
|
72
|
+
| { kind: "constant"; value: Constant }
|
|
73
|
+
| { kind: "load"; place: Place }
|
|
74
|
+
| {
|
|
75
|
+
kind: "unary";
|
|
76
|
+
operator: "not" | "negate" | "bitNot" | "timeToMilliseconds" | "clock";
|
|
77
|
+
operand: Expression;
|
|
78
|
+
}
|
|
79
|
+
| {
|
|
80
|
+
kind: "binary";
|
|
81
|
+
operator: BinaryOperator;
|
|
82
|
+
left: Expression;
|
|
83
|
+
right: Expression;
|
|
84
|
+
policy?: "wrap" | "saturate";
|
|
85
|
+
}
|
|
86
|
+
| {
|
|
87
|
+
kind: "call";
|
|
88
|
+
function: SymbolId;
|
|
89
|
+
instance?: SymbolId;
|
|
90
|
+
index?: Expression;
|
|
91
|
+
arguments: readonly Expression[];
|
|
92
|
+
}
|
|
93
|
+
| { kind: "conditional"; condition: Expression; then: Expression; else: Expression }
|
|
94
|
+
| { kind: "convert"; operand: Expression; policy: "exact" | "wrap" | "saturate" }
|
|
95
|
+
| { kind: "borrow"; place: Place }
|
|
96
|
+
| { kind: "length"; operand: Expression }
|
|
97
|
+
| { kind: "copy"; operand: Expression }
|
|
98
|
+
| { kind: "record"; fields: Readonly<Record<string, Expression>> }
|
|
99
|
+
| { kind: "array"; items: readonly Expression[] }
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
export type Statement = { span: SourceSpan } & (
|
|
103
|
+
| { kind: "assign"; destination: Place; value: Expression }
|
|
104
|
+
| { kind: "if"; condition: Expression; then: readonly Statement[]; else: readonly Statement[] }
|
|
105
|
+
| {
|
|
106
|
+
kind: "switch";
|
|
107
|
+
value: Expression;
|
|
108
|
+
cases: readonly { values: readonly Constant[]; body: readonly Statement[] }[];
|
|
109
|
+
fallback: readonly Statement[];
|
|
110
|
+
}
|
|
111
|
+
| {
|
|
112
|
+
kind: "for";
|
|
113
|
+
counter: SymbolId;
|
|
114
|
+
/** Existing storage remains observable after the loop exits. */
|
|
115
|
+
counterScope?: "existing";
|
|
116
|
+
start: Expression;
|
|
117
|
+
limit: Expression;
|
|
118
|
+
step: string;
|
|
119
|
+
exclusive?: true;
|
|
120
|
+
maxIterations: number;
|
|
121
|
+
body: readonly Statement[];
|
|
122
|
+
}
|
|
123
|
+
| {
|
|
124
|
+
kind: "invoke";
|
|
125
|
+
function: SymbolId;
|
|
126
|
+
instance?: SymbolId;
|
|
127
|
+
index?: Expression;
|
|
128
|
+
arguments: readonly Expression[];
|
|
129
|
+
destination?: Place;
|
|
130
|
+
}
|
|
131
|
+
| {
|
|
132
|
+
kind: "blockUpdate";
|
|
133
|
+
instance: SymbolId;
|
|
134
|
+
index?: Expression;
|
|
135
|
+
inputs: Readonly<Record<string, Expression>>;
|
|
136
|
+
}
|
|
137
|
+
| { kind: "return"; value?: Expression }
|
|
138
|
+
| { kind: "break" | "continue" }
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
export interface MethodOwner {
|
|
142
|
+
block: SymbolId;
|
|
143
|
+
access: "public" | "private" | "protected";
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface PlcFunction {
|
|
147
|
+
owner?: MethodOwner;
|
|
148
|
+
id: SymbolId;
|
|
149
|
+
name: string;
|
|
150
|
+
parameters: readonly Variable[];
|
|
151
|
+
locals: readonly Variable[];
|
|
152
|
+
result?: TypeId;
|
|
153
|
+
/** A `@tsplc/compiler/math` helper, whose result range follows from its arguments' ranges. */
|
|
154
|
+
bounds?: MathHelper;
|
|
155
|
+
body: readonly Statement[];
|
|
156
|
+
span: SourceSpan;
|
|
157
|
+
}
|
|
158
|
+
export type MathHelper = "min" | "max" | "clamp";
|
|
159
|
+
|
|
160
|
+
// Native vendor blocks under their TypeScript names. Ports are [name, native name, type];
|
|
161
|
+
// every output starts FALSE or T#0s, matching the vendor library blocks.
|
|
162
|
+
const timer = (input: string, output: string) =>
|
|
163
|
+
({
|
|
164
|
+
inputs: [
|
|
165
|
+
[input, "IN", "BOOL"],
|
|
166
|
+
["duration", "PT", "TIME"],
|
|
167
|
+
],
|
|
168
|
+
outputs: [
|
|
169
|
+
[output, "Q", "BOOL"],
|
|
170
|
+
["elapsed", "ET", "TIME"],
|
|
171
|
+
],
|
|
172
|
+
}) as const;
|
|
173
|
+
export const standardBlocks = {
|
|
174
|
+
OnDelayTimer: { native: "TON", ...timer("enabled", "done") },
|
|
175
|
+
OffDelayTimer: { native: "TOF", ...timer("enabled", "active") },
|
|
176
|
+
PulseTimer: { native: "TP", ...timer("start", "active") },
|
|
177
|
+
RisingEdge: {
|
|
178
|
+
native: "R_TRIG",
|
|
179
|
+
inputs: [["signal", "CLK", "BOOL"]],
|
|
180
|
+
outputs: [["rose", "Q", "BOOL"]],
|
|
181
|
+
},
|
|
182
|
+
FallingEdge: {
|
|
183
|
+
native: "F_TRIG",
|
|
184
|
+
inputs: [["signal", "CLK", "BOOL"]],
|
|
185
|
+
outputs: [["fell", "Q", "BOOL"]],
|
|
186
|
+
},
|
|
187
|
+
Blinker: {
|
|
188
|
+
native: "Util.BLINK",
|
|
189
|
+
inputs: [
|
|
190
|
+
["enabled", "ENABLE", "BOOL"],
|
|
191
|
+
["offTime", "TIMELOW", "TIME"],
|
|
192
|
+
["onTime", "TIMEHIGH", "TIME"],
|
|
193
|
+
],
|
|
194
|
+
outputs: [["on", "OUT", "BOOL"]],
|
|
195
|
+
},
|
|
196
|
+
} as const;
|
|
197
|
+
export type StandardBlock = keyof typeof standardBlocks;
|
|
198
|
+
|
|
199
|
+
export interface FunctionBlock {
|
|
200
|
+
id: SymbolId;
|
|
201
|
+
name: string;
|
|
202
|
+
inputs: readonly Variable[];
|
|
203
|
+
outputs: readonly Variable[];
|
|
204
|
+
state: readonly Variable[];
|
|
205
|
+
locals: readonly Variable[];
|
|
206
|
+
body: readonly Statement[];
|
|
207
|
+
result?: TypeId;
|
|
208
|
+
standard?: StandardBlock;
|
|
209
|
+
runtime?:
|
|
210
|
+
| { kind: "mailbox" }
|
|
211
|
+
| { kind: "backgroundHost" }
|
|
212
|
+
| { kind: "rpc"; path: string }
|
|
213
|
+
| {
|
|
214
|
+
kind: "http";
|
|
215
|
+
url: string;
|
|
216
|
+
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
217
|
+
json: boolean;
|
|
218
|
+
};
|
|
219
|
+
span: SourceSpan;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export interface PlcProgram {
|
|
223
|
+
id: SymbolId;
|
|
224
|
+
name: string;
|
|
225
|
+
entry: SymbolId;
|
|
226
|
+
continuation?: { instance: string; file: string };
|
|
227
|
+
background?: { intervalNanoseconds: string; priority: number; mailbox: string; worker: string };
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export interface PlcModule {
|
|
231
|
+
types: readonly PlcType[];
|
|
232
|
+
variables: readonly Variable[];
|
|
233
|
+
functions: readonly PlcFunction[];
|
|
234
|
+
blocks: readonly FunctionBlock[];
|
|
235
|
+
programs: readonly PlcProgram[];
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export interface Task {
|
|
239
|
+
name: string;
|
|
240
|
+
intervalNanoseconds: string;
|
|
241
|
+
priority: number;
|
|
242
|
+
programs: readonly string[];
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export interface Deployment {
|
|
246
|
+
tasks: readonly Task[];
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export interface Artifact {
|
|
250
|
+
path: string;
|
|
251
|
+
content: string;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export interface GeneratedObject {
|
|
255
|
+
parent?: SymbolId;
|
|
256
|
+
sourcePath?: string;
|
|
257
|
+
id: SymbolId;
|
|
258
|
+
kind: "program" | "function" | "functionBlock" | "method" | "globalList" | "dataType";
|
|
259
|
+
name: string;
|
|
260
|
+
declaration: string;
|
|
261
|
+
implementation?: string;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export interface EmitResult {
|
|
265
|
+
artifacts: readonly Artifact[];
|
|
266
|
+
objects: readonly GeneratedObject[];
|
|
267
|
+
diagnostics: readonly Diagnostic[];
|
|
268
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { error, type Diagnostic, type SourceSpan } from "./diagnostics.ts";
|
|
2
|
+
|
|
3
|
+
export class InvalidCore extends Error {
|
|
4
|
+
constructor(readonly diagnostic: Diagnostic) {
|
|
5
|
+
super(diagnostic.message);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export function reject(message: string, span?: SourceSpan): never {
|
|
9
|
+
throw new InvalidCore(error("PLC6001", message, span));
|
|
10
|
+
}
|