@microtronics/studio-cli 0.46.0 → 0.48.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/CHANGELOG.md +15 -2
- package/out/dlo/preCompiler.js +116 -1
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
3
|
+
## 0.48.0 (2026-02-10)
|
|
4
4
|
|
|
5
|
-
###
|
|
5
|
+
### Features
|
|
6
6
|
|
|
7
|
+
* **cli:** support multiline statements in DLO precompiler ([b2aef4d](https://bitbucket.org/microtronics-core/vscode-studio/commits/b2aef4d924bdd328d5f8bb90485d02516cd35d3b))
|
|
8
|
+
|
|
9
|
+
## 0.47.0 (2026-02-06)
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **cli:** add missing 'tar' dev package ([707f755](https://bitbucket.org/microtronics-core/vscode-studio/commits/707f75561af14ff302b8c780e55cd5a156a9187a))
|
|
14
|
+
* **cli:** add missing 'uuid' package ([48c2fec](https://bitbucket.org/microtronics-core/vscode-studio/commits/48c2fec8fa052326706df2b2e2c7a0a9b71ece24))
|
|
15
|
+
|
|
16
|
+
## 0.46.0 (2026-02-04)
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
7
20
|
* limit development site name to 50 characters maximum ([6dd6772](https://bitbucket.org/microtronics-core/vscode-studio/commits/6dd6772eb0d0c84ccf3f68b4a3fcbb751a46f7f8)), closes [#bugfix-ready](https://bitbucket.org/microtronics-core/vscode-studio/issues/bugfix-ready)
|
|
8
21
|
|
|
9
22
|
## 0.45.0 (2026-02-04)
|
package/out/dlo/preCompiler.js
CHANGED
|
@@ -74,6 +74,102 @@ var LogLevel;
|
|
|
74
74
|
const rxpDDE = /^(.*)(^|\s*)DDE_(state|result|aloha|volatile|setting|command)_/;
|
|
75
75
|
const rxpUplinkRestore = /^(.*)(^|\s*)onUplink(Restore|Apply)_(state|result|aloha|volatile|setting|command)/;
|
|
76
76
|
const rxpUplinkEvent = /^(.*)(^|\s*)onUplinkEvent/;
|
|
77
|
+
// Regex to detect start of function-like statements that may span multiple lines
|
|
78
|
+
const rxpMultilineFuncStart = /(?:^|\s)(?:assert|catch|applog(?:_ok|_warning|_alarm|_debug|_fatal)?|log(?:_debug|_info|_warn|_error)?)\s*\(/;
|
|
79
|
+
const rxpMultilineCallbackStart = /^\s*#callback\s+\w+\s*\(/;
|
|
80
|
+
/**
|
|
81
|
+
* Count unbalanced parentheses depth in text, respecting string literals.
|
|
82
|
+
* Returns a positive number if there are more opening than closing parens.
|
|
83
|
+
*/
|
|
84
|
+
function getParenthesisDepth(text) {
|
|
85
|
+
let depth = 0;
|
|
86
|
+
let inString = false;
|
|
87
|
+
let stringChar = '';
|
|
88
|
+
for (let i = 0; i < text.length; i++) {
|
|
89
|
+
const ch = text[i];
|
|
90
|
+
if (inString) {
|
|
91
|
+
if (ch === '\\') {
|
|
92
|
+
i++;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (ch === stringChar) {
|
|
96
|
+
inString = false;
|
|
97
|
+
}
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (ch === '"' || ch === "'") {
|
|
101
|
+
inString = true;
|
|
102
|
+
stringChar = ch;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (ch === '(') {
|
|
106
|
+
depth++;
|
|
107
|
+
}
|
|
108
|
+
else if (ch === ')') {
|
|
109
|
+
depth--;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return depth;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Check if a line matches any of the multiline-capable replacement patterns.
|
|
116
|
+
*/
|
|
117
|
+
function matchesAnyMultilineCapablePattern(line) {
|
|
118
|
+
return (rxpCallback.test(line) ||
|
|
119
|
+
rxpAssertF.test(line) ||
|
|
120
|
+
rxpAssert.test(line) ||
|
|
121
|
+
rxpAssert0.test(line) ||
|
|
122
|
+
rxpCatch.test(line) ||
|
|
123
|
+
rxpApplog.test(line) ||
|
|
124
|
+
rxpApplog0.test(line) ||
|
|
125
|
+
rxpLogBackend.test(line));
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Try to accumulate a multiline statement starting at the given line index.
|
|
129
|
+
* Returns null if the line is not a multiline statement start, or if the
|
|
130
|
+
* accumulated joined line doesn't match any replacement pattern.
|
|
131
|
+
*/
|
|
132
|
+
function tryAccumulateMultilineStatement(fileBlob, startIndex, startStripped) {
|
|
133
|
+
// Check if this line could start a multiline statement
|
|
134
|
+
const isCandidate = rxpMultilineFuncStart.test(startStripped) || rxpMultilineCallbackStart.test(startStripped);
|
|
135
|
+
if (!isCandidate) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
// Check if parentheses are unbalanced (indicating continuation on next lines)
|
|
139
|
+
const depth = getParenthesisDepth(startStripped);
|
|
140
|
+
if (depth <= 0) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
// Accumulate lines until parentheses are balanced
|
|
144
|
+
let totalDepth = depth;
|
|
145
|
+
const originalLines = [fileBlob[startIndex]];
|
|
146
|
+
const strippedLines = [startStripped];
|
|
147
|
+
let nextIndex = startIndex + 1;
|
|
148
|
+
const maxAccumulation = 100; // Safety limit
|
|
149
|
+
while (totalDepth > 0 && nextIndex < fileBlob.length && nextIndex - startIndex < maxAccumulation) {
|
|
150
|
+
const nextOriginal = fileBlob[nextIndex];
|
|
151
|
+
const nextStripped = nextOriginal.split('//', 1)[0];
|
|
152
|
+
originalLines.push(nextOriginal);
|
|
153
|
+
strippedLines.push(nextStripped);
|
|
154
|
+
totalDepth += getParenthesisDepth(nextStripped);
|
|
155
|
+
nextIndex++;
|
|
156
|
+
}
|
|
157
|
+
// If we couldn't balance the parens or only have one line, abort
|
|
158
|
+
if (originalLines.length <= 1 || totalDepth > 0) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
const joinedOriginal = originalLines.map((l, i) => (i === 0 ? l : l.trim())).join(' ');
|
|
162
|
+
const joinedStripped = strippedLines.map((l, i) => (i === 0 ? l : l.trim())).join(' ');
|
|
163
|
+
// Only use multiline if the joined line actually matches a replacement pattern
|
|
164
|
+
if (!matchesAnyMultilineCapablePattern(joinedStripped)) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
joinedOriginal,
|
|
169
|
+
joinedStripped,
|
|
170
|
+
extraLineCount: originalLines.length - 1
|
|
171
|
+
};
|
|
172
|
+
}
|
|
77
173
|
class DloPreCompiler {
|
|
78
174
|
pragmaDynamic = null;
|
|
79
175
|
dloFileSequencer = new fileSequencer_1.DloFileSequencer();
|
|
@@ -137,11 +233,24 @@ class DloPreCompiler {
|
|
|
137
233
|
let outLineNumber = 0;
|
|
138
234
|
// !!!
|
|
139
235
|
// !!! output is always single-line to keep line numbers equal to original source!
|
|
236
|
+
// !!! multiline statements are joined into a single line, with empty lines emitted
|
|
237
|
+
// !!! for consumed continuation lines to preserve line number alignment.
|
|
140
238
|
// !!!
|
|
141
239
|
for (let lineNumber = 0; lineNumber < fileBlob.length; lineNumber++) {
|
|
142
240
|
let newLine = fileBlob[lineNumber];
|
|
143
|
-
|
|
241
|
+
let currentLine = newLine.split('//', 1)[0]; // todo dirty solution! strip-off "end of line" comments
|
|
144
242
|
let h = null;
|
|
243
|
+
let consumedExtraLines = 0;
|
|
244
|
+
// Detect multiline statements: if the current single line doesn't match any
|
|
245
|
+
// multiline-capable pattern, try accumulating continuation lines.
|
|
246
|
+
if (!matchesAnyMultilineCapablePattern(currentLine)) {
|
|
247
|
+
const multiline = tryAccumulateMultilineStatement(fileBlob, lineNumber, currentLine);
|
|
248
|
+
if (multiline) {
|
|
249
|
+
newLine = multiline.joinedOriginal;
|
|
250
|
+
currentLine = multiline.joinedStripped;
|
|
251
|
+
consumedExtraLines = multiline.extraLineCount;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
145
254
|
// #options
|
|
146
255
|
if ((h = rxpOptions.exec(currentLine))) {
|
|
147
256
|
newLine = '// ' + newLine;
|
|
@@ -303,6 +412,12 @@ class DloPreCompiler {
|
|
|
303
412
|
}
|
|
304
413
|
precompiledData.push(newLine);
|
|
305
414
|
outLineNumber++;
|
|
415
|
+
// Emit empty lines for consumed multiline continuation lines
|
|
416
|
+
for (let i = 0; i < consumedExtraLines; i++) {
|
|
417
|
+
precompiledData.push('');
|
|
418
|
+
outLineNumber++;
|
|
419
|
+
lineNumber++;
|
|
420
|
+
}
|
|
306
421
|
}
|
|
307
422
|
// add undef of file include
|
|
308
423
|
if (baseName !== 'main.dlo') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@microtronics/studio-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.48.0",
|
|
4
4
|
"description": "Microtronics Studio CLI Tool",
|
|
5
5
|
"main": "./out/api.js",
|
|
6
6
|
"typings": "./dist/studio-cli.d.ts",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"author": "Microtronics",
|
|
26
26
|
"license": "ISC",
|
|
27
27
|
"dependencies": {
|
|
28
|
+
"uuid": "^9.0.1",
|
|
28
29
|
"@gera2ld/tarjs": "^0.3.1",
|
|
29
30
|
"ajv": "^8.17.1",
|
|
30
31
|
"ajv-formats": "^3.0.1",
|
|
@@ -70,9 +71,9 @@
|
|
|
70
71
|
"mocha": "^10.8.2",
|
|
71
72
|
"mocha-junit-reporter": "^2.2.1",
|
|
72
73
|
"openapi-typescript": "^7.6.0",
|
|
73
|
-
"tar": "^7.4.3",
|
|
74
74
|
"ts-node": "^10.9.2",
|
|
75
|
-
"typescript": "^5.6.3"
|
|
75
|
+
"typescript": "^5.6.3",
|
|
76
|
+
"tar": "^7.5.7"
|
|
76
77
|
},
|
|
77
78
|
"mocha": {
|
|
78
79
|
"require": [
|