dirac-lang 0.1.13 → 0.1.15
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/dist/{chunk-34CYTCOP.js → chunk-74EQEVS6.js} +250 -130
- package/dist/chunk-HRHAMPOB.js +123 -0
- package/dist/{chunk-Z6QGGWWD.js → chunk-UO6QEXZV.js} +4 -2
- package/dist/cli.js +4 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -3
- package/dist/{interpreter-MAG7PN4D.js → interpreter-SE5I5ROB.js} +2 -1
- package/dist/parser-T6W3WPLU.js +6 -0
- package/dist/test-runner.js +4 -2
- package/package.json +1 -1
- package/src/runtime/interpreter.ts +24 -0
- package/src/runtime/parser.ts +4 -0
- package/src/tags/attr.ts +64 -0
- package/src/tags/available-subroutines.ts +70 -0
- package/src/tags/call.ts +6 -2
- package/src/tags/defvar.ts +53 -2
- package/src/tags/foreach.ts +170 -0
- package/src/types/index.ts +1 -0
- package/test-available-extends.di +28 -0
- package/test-available-simple.di +12 -0
- package/test-available-subroutines.di +16 -0
- package/test-extend-basic.di +17 -0
- package/test-extend-person.di +17 -0
- package/test-extend3-trouble.di +23 -0
- package/test-simple-call.di +7 -0
- package/tests/available-subroutines-foreach.test.di +32 -0
- package/tests/comments-before-content.test.di +6 -0
- package/tests/extend-basic.test.di +19 -0
- package/tests/extend-inheritance-chain.test.di +26 -0
- package/tests/extend-multiple-nested.test.di +24 -0
- package/tests/extend-self.test.di +19 -0
- package/tests/extend-with-parameters.test.di +14 -0
- package/tests/no-root-element.test.di +6 -0
- package/tests/parameters-basic.test.di +2 -1
- package/tests/extend.test.di +0 -108
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DiracParser
|
|
3
|
+
} from "./chunk-HRHAMPOB.js";
|
|
1
4
|
import {
|
|
2
5
|
executeSubroutine
|
|
3
6
|
} from "./chunk-E7PWEMZA.js";
|
|
@@ -91,7 +94,9 @@ async function executeDefvar(session, element) {
|
|
|
91
94
|
if (valueAttr !== void 0) {
|
|
92
95
|
value = substituteVariables(session, valueAttr);
|
|
93
96
|
} else if (literal) {
|
|
94
|
-
if (element.
|
|
97
|
+
if (element.children && element.children.length > 0) {
|
|
98
|
+
value = serializeToXml(element.children);
|
|
99
|
+
} else if (element.text) {
|
|
95
100
|
value = substituteVariables(session, element.text);
|
|
96
101
|
} else {
|
|
97
102
|
value = "";
|
|
@@ -118,6 +123,35 @@ async function executeDefvar(session, element) {
|
|
|
118
123
|
}
|
|
119
124
|
setVariable(session, name, value, visible);
|
|
120
125
|
}
|
|
126
|
+
function serializeToXml(children) {
|
|
127
|
+
let xml = "";
|
|
128
|
+
for (const child of children) {
|
|
129
|
+
if (!child.tag || child.tag === "") {
|
|
130
|
+
xml += child.text || "";
|
|
131
|
+
} else {
|
|
132
|
+
xml += `<${child.tag}`;
|
|
133
|
+
for (const [attrName, attrValue] of Object.entries(child.attributes)) {
|
|
134
|
+
xml += ` ${attrName}="${escapeXml(attrValue)}"`;
|
|
135
|
+
}
|
|
136
|
+
if (child.children.length === 0 && !child.text) {
|
|
137
|
+
xml += " />";
|
|
138
|
+
} else {
|
|
139
|
+
xml += ">";
|
|
140
|
+
if (child.text) {
|
|
141
|
+
xml += escapeXml(child.text);
|
|
142
|
+
}
|
|
143
|
+
if (child.children.length > 0) {
|
|
144
|
+
xml += serializeToXml(child.children);
|
|
145
|
+
}
|
|
146
|
+
xml += `</${child.tag}>`;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return xml;
|
|
151
|
+
}
|
|
152
|
+
function escapeXml(text) {
|
|
153
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
154
|
+
}
|
|
121
155
|
|
|
122
156
|
// src/tags/variable.ts
|
|
123
157
|
function executeVariable(session, element) {
|
|
@@ -206,7 +240,7 @@ async function registerExtendChain(session, subroutine, currentName) {
|
|
|
206
240
|
} else {
|
|
207
241
|
parentName = currentName;
|
|
208
242
|
}
|
|
209
|
-
const parent = getParentSubroutine(session, parentName, parentName === currentName);
|
|
243
|
+
const parent = getParentSubroutine(session, parentName, parentName === currentName ? subroutine : void 0);
|
|
210
244
|
if (!parent) {
|
|
211
245
|
return subroutine;
|
|
212
246
|
}
|
|
@@ -234,6 +268,8 @@ async function executeCallInternal(session, subroutine, callElement, isExtendExe
|
|
|
234
268
|
const oldBoundary = setBoundary(session);
|
|
235
269
|
const wasReturn = session.isReturn;
|
|
236
270
|
session.isReturn = false;
|
|
271
|
+
const oldSubroutineName = session.currentSubroutineName;
|
|
272
|
+
session.currentSubroutineName = callElement.tag;
|
|
237
273
|
const oldSkipFlag = session.skipSubroutineRegistration;
|
|
238
274
|
if (isExtendExecution) {
|
|
239
275
|
session.skipSubroutineRegistration = true;
|
|
@@ -360,12 +396,12 @@ async function executeIf(session, element) {
|
|
|
360
396
|
const condition = await evaluatePredicate(session, conditionElement);
|
|
361
397
|
if (condition) {
|
|
362
398
|
if (thenElement) {
|
|
363
|
-
const { integrateChildren: integrateChildren2 } = await import("./interpreter-
|
|
399
|
+
const { integrateChildren: integrateChildren2 } = await import("./interpreter-SE5I5ROB.js");
|
|
364
400
|
await integrateChildren2(session, thenElement);
|
|
365
401
|
}
|
|
366
402
|
} else {
|
|
367
403
|
if (elseElement) {
|
|
368
|
-
const { integrateChildren: integrateChildren2 } = await import("./interpreter-
|
|
404
|
+
const { integrateChildren: integrateChildren2 } = await import("./interpreter-SE5I5ROB.js");
|
|
369
405
|
await integrateChildren2(session, elseElement);
|
|
370
406
|
}
|
|
371
407
|
}
|
|
@@ -378,7 +414,7 @@ async function evaluatePredicate(session, predicateElement) {
|
|
|
378
414
|
return await evaluateCondition(session, predicateElement);
|
|
379
415
|
}
|
|
380
416
|
const outputLengthBefore = session.output.length;
|
|
381
|
-
const { integrate: integrate2 } = await import("./interpreter-
|
|
417
|
+
const { integrate: integrate2 } = await import("./interpreter-SE5I5ROB.js");
|
|
382
418
|
await integrate2(session, predicateElement);
|
|
383
419
|
const newOutputChunks = session.output.slice(outputLengthBefore);
|
|
384
420
|
const result = newOutputChunks.join("").trim();
|
|
@@ -401,11 +437,11 @@ async function evaluateCondition(session, condElement) {
|
|
|
401
437
|
}
|
|
402
438
|
const outputLengthBefore = session.output.length;
|
|
403
439
|
const args = [];
|
|
404
|
-
const { integrate: integrate2 } = await import("./interpreter-
|
|
440
|
+
const { integrate: integrate2 } = await import("./interpreter-SE5I5ROB.js");
|
|
405
441
|
for (const child of condElement.children) {
|
|
406
442
|
if (child.tag.toLowerCase() === "arg") {
|
|
407
443
|
const argOutputStart = session.output.length;
|
|
408
|
-
const { integrateChildren: integrateChildren2 } = await import("./interpreter-
|
|
444
|
+
const { integrateChildren: integrateChildren2 } = await import("./interpreter-SE5I5ROB.js");
|
|
409
445
|
await integrateChildren2(session, child);
|
|
410
446
|
const newChunks = session.output.slice(argOutputStart);
|
|
411
447
|
const argValue = newChunks.join("");
|
|
@@ -463,123 +499,6 @@ function evaluateConditionType(evalType, args) {
|
|
|
463
499
|
}
|
|
464
500
|
}
|
|
465
501
|
|
|
466
|
-
// src/runtime/parser.ts
|
|
467
|
-
import { XMLParser } from "fast-xml-parser";
|
|
468
|
-
var DiracParser = class {
|
|
469
|
-
parser;
|
|
470
|
-
constructor() {
|
|
471
|
-
this.parser = new XMLParser({
|
|
472
|
-
ignoreAttributes: false,
|
|
473
|
-
attributeNamePrefix: "@_",
|
|
474
|
-
trimValues: false,
|
|
475
|
-
// Preserve whitespace in mixed content
|
|
476
|
-
parseAttributeValue: false,
|
|
477
|
-
parseTagValue: false,
|
|
478
|
-
textNodeName: "#text",
|
|
479
|
-
cdataPropName: "#cdata",
|
|
480
|
-
preserveOrder: true,
|
|
481
|
-
// Preserve element order!
|
|
482
|
-
commentPropName: "#comment"
|
|
483
|
-
});
|
|
484
|
-
}
|
|
485
|
-
parse(source) {
|
|
486
|
-
if (source.startsWith("#!")) {
|
|
487
|
-
source = source.replace(/^#!.*\n/, "");
|
|
488
|
-
}
|
|
489
|
-
const result = this.parser.parse(source);
|
|
490
|
-
if (!Array.isArray(result) || result.length === 0) {
|
|
491
|
-
throw new Error("Empty or invalid XML");
|
|
492
|
-
}
|
|
493
|
-
for (const item of result) {
|
|
494
|
-
if (!item["#comment"]) {
|
|
495
|
-
return this.convertOrderedToElement(item);
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
throw new Error("No root element found");
|
|
499
|
-
}
|
|
500
|
-
convertOrderedToElement(obj) {
|
|
501
|
-
const tagName = Object.keys(obj).find((k) => k !== ":@" && k !== "#comment");
|
|
502
|
-
if (!tagName) {
|
|
503
|
-
throw new Error("Invalid element structure");
|
|
504
|
-
}
|
|
505
|
-
const element = {
|
|
506
|
-
tag: tagName,
|
|
507
|
-
attributes: {},
|
|
508
|
-
children: []
|
|
509
|
-
};
|
|
510
|
-
if (obj[":@"]) {
|
|
511
|
-
for (const [key, value] of Object.entries(obj[":@"])) {
|
|
512
|
-
if (key.startsWith("@_")) {
|
|
513
|
-
element.attributes[key.slice(2)] = value;
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
const children = obj[tagName];
|
|
518
|
-
if (Array.isArray(children)) {
|
|
519
|
-
for (const child of children) {
|
|
520
|
-
if (child["#text"]) {
|
|
521
|
-
element.children.push({
|
|
522
|
-
tag: "",
|
|
523
|
-
text: child["#text"],
|
|
524
|
-
attributes: {},
|
|
525
|
-
children: []
|
|
526
|
-
});
|
|
527
|
-
if (!element.text) {
|
|
528
|
-
element.text = child["#text"];
|
|
529
|
-
} else {
|
|
530
|
-
element.text += child["#text"];
|
|
531
|
-
}
|
|
532
|
-
} else if (child["#comment"]) {
|
|
533
|
-
continue;
|
|
534
|
-
} else {
|
|
535
|
-
element.children.push(this.convertOrderedToElement(child));
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
return element;
|
|
540
|
-
}
|
|
541
|
-
// Old method - no longer used
|
|
542
|
-
convertToElement(obj, tagName) {
|
|
543
|
-
if (!tagName) {
|
|
544
|
-
const keys = Object.keys(obj);
|
|
545
|
-
if (keys.length === 0) {
|
|
546
|
-
throw new Error("Empty XML");
|
|
547
|
-
}
|
|
548
|
-
tagName = keys[0];
|
|
549
|
-
obj = obj[tagName];
|
|
550
|
-
}
|
|
551
|
-
const element = {
|
|
552
|
-
tag: tagName,
|
|
553
|
-
attributes: {},
|
|
554
|
-
children: []
|
|
555
|
-
};
|
|
556
|
-
if (typeof obj === "string") {
|
|
557
|
-
element.text = obj;
|
|
558
|
-
return element;
|
|
559
|
-
}
|
|
560
|
-
if (!obj) {
|
|
561
|
-
return element;
|
|
562
|
-
}
|
|
563
|
-
for (const key of Object.keys(obj)) {
|
|
564
|
-
const value = obj[key];
|
|
565
|
-
if (key === "#text") {
|
|
566
|
-
element.text = value;
|
|
567
|
-
} else if (key.startsWith("@_")) {
|
|
568
|
-
element.attributes[key.slice(2)] = value;
|
|
569
|
-
} else {
|
|
570
|
-
if (Array.isArray(value)) {
|
|
571
|
-
for (const item of value) {
|
|
572
|
-
element.children.push(this.convertToElement(item, key));
|
|
573
|
-
}
|
|
574
|
-
} else {
|
|
575
|
-
element.children.push(this.convertToElement(value, key));
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
return element;
|
|
580
|
-
}
|
|
581
|
-
};
|
|
582
|
-
|
|
583
502
|
// src/tags/llm.ts
|
|
584
503
|
async function executeLLM(session, element) {
|
|
585
504
|
if (!session.llmClient) {
|
|
@@ -1316,7 +1235,7 @@ async function executeTagCheck(session, element) {
|
|
|
1316
1235
|
const executeTag = correctedTag || tagName;
|
|
1317
1236
|
console.error(`[tag-check] Executing <${executeTag}/> as all checks passed and execute=true.`);
|
|
1318
1237
|
const elementToExecute = correctedTag ? { ...child, tag: correctedTag } : child;
|
|
1319
|
-
const { integrate: integrate2 } = await import("./interpreter-
|
|
1238
|
+
const { integrate: integrate2 } = await import("./interpreter-SE5I5ROB.js");
|
|
1320
1239
|
await integrate2(session, elementToExecute);
|
|
1321
1240
|
}
|
|
1322
1241
|
}
|
|
@@ -1325,7 +1244,7 @@ async function executeTagCheck(session, element) {
|
|
|
1325
1244
|
// src/tags/throw.ts
|
|
1326
1245
|
async function executeThrow(session, element) {
|
|
1327
1246
|
const exceptionName = element.attributes?.name || "exception";
|
|
1328
|
-
const { integrateChildren: integrateChildren2 } = await import("./interpreter-
|
|
1247
|
+
const { integrateChildren: integrateChildren2 } = await import("./interpreter-SE5I5ROB.js");
|
|
1329
1248
|
const exceptionDom = {
|
|
1330
1249
|
tag: "exception-content",
|
|
1331
1250
|
attributes: { name: exceptionName },
|
|
@@ -1338,7 +1257,7 @@ async function executeThrow(session, element) {
|
|
|
1338
1257
|
// src/tags/try.ts
|
|
1339
1258
|
async function executeTry(session, element) {
|
|
1340
1259
|
setExceptionBoundary(session);
|
|
1341
|
-
const { integrateChildren: integrateChildren2 } = await import("./interpreter-
|
|
1260
|
+
const { integrateChildren: integrateChildren2 } = await import("./interpreter-SE5I5ROB.js");
|
|
1342
1261
|
await integrateChildren2(session, element);
|
|
1343
1262
|
unsetExceptionBoundary(session);
|
|
1344
1263
|
}
|
|
@@ -1348,7 +1267,7 @@ async function executeCatch(session, element) {
|
|
|
1348
1267
|
const exceptionName = element.attributes?.name || "exception";
|
|
1349
1268
|
const caughtCount = lookupException(session, exceptionName);
|
|
1350
1269
|
if (caughtCount > 0) {
|
|
1351
|
-
const { integrateChildren: integrateChildren2 } = await import("./interpreter-
|
|
1270
|
+
const { integrateChildren: integrateChildren2 } = await import("./interpreter-SE5I5ROB.js");
|
|
1352
1271
|
await integrateChildren2(session, element);
|
|
1353
1272
|
}
|
|
1354
1273
|
flushCurrentException(session);
|
|
@@ -1357,7 +1276,7 @@ async function executeCatch(session, element) {
|
|
|
1357
1276
|
// src/tags/exception.ts
|
|
1358
1277
|
async function executeException(session, element) {
|
|
1359
1278
|
const exceptions = getCurrentExceptions(session);
|
|
1360
|
-
const { integrateChildren: integrateChildren2 } = await import("./interpreter-
|
|
1279
|
+
const { integrateChildren: integrateChildren2 } = await import("./interpreter-SE5I5ROB.js");
|
|
1361
1280
|
for (const exceptionDom of exceptions) {
|
|
1362
1281
|
await integrateChildren2(session, exceptionDom);
|
|
1363
1282
|
}
|
|
@@ -1443,6 +1362,192 @@ function evaluateCondition2(session, test) {
|
|
|
1443
1362
|
return true;
|
|
1444
1363
|
}
|
|
1445
1364
|
|
|
1365
|
+
// src/tags/available-subroutines.ts
|
|
1366
|
+
async function executeAvailableSubroutines(session, element) {
|
|
1367
|
+
const availableSubroutines = /* @__PURE__ */ new Map();
|
|
1368
|
+
const currentSubroutineName = session.subBoundary < session.subroutines.length ? session.subroutines[session.subBoundary].name : null;
|
|
1369
|
+
for (let i = session.subroutines.length - 1; i >= session.subBoundary; i--) {
|
|
1370
|
+
const sub = session.subroutines[i];
|
|
1371
|
+
if (sub.name === currentSubroutineName) {
|
|
1372
|
+
continue;
|
|
1373
|
+
}
|
|
1374
|
+
if (!availableSubroutines.has(sub.name)) {
|
|
1375
|
+
availableSubroutines.set(sub.name, sub.element);
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
session.output.push("<subroutines>");
|
|
1379
|
+
for (const [name, subElement] of availableSubroutines) {
|
|
1380
|
+
const attrs = [`name="${escapeXml2(name)}"`];
|
|
1381
|
+
const description = subElement.attributes.description;
|
|
1382
|
+
if (description) {
|
|
1383
|
+
attrs.push(`description="${escapeXml2(description)}"`);
|
|
1384
|
+
}
|
|
1385
|
+
for (const [attrName, attrValue] of Object.entries(subElement.attributes)) {
|
|
1386
|
+
if (attrName.startsWith("param-")) {
|
|
1387
|
+
attrs.push(`${attrName}="${escapeXml2(attrValue)}"`);
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
const attrString = attrs.join(" ");
|
|
1391
|
+
session.output.push(` <subroutine ${attrString} />`);
|
|
1392
|
+
}
|
|
1393
|
+
session.output.push("</subroutines>");
|
|
1394
|
+
}
|
|
1395
|
+
function escapeXml2(text) {
|
|
1396
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
// src/tags/foreach.ts
|
|
1400
|
+
import { XMLParser } from "fast-xml-parser";
|
|
1401
|
+
async function executeForeach(session, element) {
|
|
1402
|
+
const fromAttr = element.attributes.from;
|
|
1403
|
+
const asVar = element.attributes.as || "item";
|
|
1404
|
+
const xpath = element.attributes.xpath;
|
|
1405
|
+
if (!fromAttr) {
|
|
1406
|
+
throw new Error('<foreach> requires "from" attribute');
|
|
1407
|
+
}
|
|
1408
|
+
let xmlContent;
|
|
1409
|
+
if (fromAttr.startsWith("$")) {
|
|
1410
|
+
const varName = fromAttr.substring(1);
|
|
1411
|
+
xmlContent = getVariable(session, varName) || "";
|
|
1412
|
+
} else if (fromAttr.startsWith("<")) {
|
|
1413
|
+
const savedOutput = session.output;
|
|
1414
|
+
session.output = [];
|
|
1415
|
+
const { DiracParser: DiracParser2 } = await import("./parser-T6W3WPLU.js");
|
|
1416
|
+
const parser2 = new DiracParser2();
|
|
1417
|
+
try {
|
|
1418
|
+
const fromElement = parser2.parse(fromAttr);
|
|
1419
|
+
const { integrate: integrate2 } = await import("./interpreter-SE5I5ROB.js");
|
|
1420
|
+
await integrate2(session, fromElement);
|
|
1421
|
+
} catch (e) {
|
|
1422
|
+
session.output = savedOutput;
|
|
1423
|
+
throw new Error(`Failed to evaluate from="${fromAttr}": ${e}`);
|
|
1424
|
+
}
|
|
1425
|
+
xmlContent = session.output.join("");
|
|
1426
|
+
session.output = savedOutput;
|
|
1427
|
+
} else {
|
|
1428
|
+
xmlContent = substituteVariables(session, fromAttr);
|
|
1429
|
+
}
|
|
1430
|
+
if (!xmlContent || xmlContent.trim() === "") {
|
|
1431
|
+
return;
|
|
1432
|
+
}
|
|
1433
|
+
const parser = new XMLParser({
|
|
1434
|
+
ignoreAttributes: false,
|
|
1435
|
+
attributeNamePrefix: "@_",
|
|
1436
|
+
parseAttributeValue: false,
|
|
1437
|
+
preserveOrder: true
|
|
1438
|
+
});
|
|
1439
|
+
let parsed;
|
|
1440
|
+
try {
|
|
1441
|
+
parsed = parser.parse(`<root>${xmlContent}</root>`);
|
|
1442
|
+
} catch (e) {
|
|
1443
|
+
throw new Error(`Failed to parse XML in <foreach>: ${e}`);
|
|
1444
|
+
}
|
|
1445
|
+
const items = extractElements(parsed, xpath);
|
|
1446
|
+
for (const item of items) {
|
|
1447
|
+
setVariable(session, asVar, item, false);
|
|
1448
|
+
await integrateChildren(session, element);
|
|
1449
|
+
if (session.isBreak) {
|
|
1450
|
+
session.isBreak = false;
|
|
1451
|
+
break;
|
|
1452
|
+
}
|
|
1453
|
+
if (session.isReturn) {
|
|
1454
|
+
break;
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
function extractElements(parsed, xpath) {
|
|
1459
|
+
const items = [];
|
|
1460
|
+
if (!Array.isArray(parsed)) {
|
|
1461
|
+
return items;
|
|
1462
|
+
}
|
|
1463
|
+
const extractFromNode = (node) => {
|
|
1464
|
+
if (!node) return;
|
|
1465
|
+
const tagName = Object.keys(node).find((k) => k !== ":@" && k !== "#text" && k !== "#comment");
|
|
1466
|
+
if (!tagName) return;
|
|
1467
|
+
const item = {
|
|
1468
|
+
tag: tagName,
|
|
1469
|
+
attributes: {}
|
|
1470
|
+
};
|
|
1471
|
+
if (node[":@"]) {
|
|
1472
|
+
for (const [key, value] of Object.entries(node[":@"])) {
|
|
1473
|
+
if (key.startsWith("@_")) {
|
|
1474
|
+
item.attributes[key.slice(2)] = value;
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
const children = node[tagName];
|
|
1479
|
+
if (Array.isArray(children)) {
|
|
1480
|
+
for (const child of children) {
|
|
1481
|
+
if (child["#text"]) {
|
|
1482
|
+
item.text = (item.text || "") + child["#text"];
|
|
1483
|
+
} else {
|
|
1484
|
+
extractFromNode(child);
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
if (!xpath || matchesXPath(item, xpath)) {
|
|
1489
|
+
items.push(item);
|
|
1490
|
+
}
|
|
1491
|
+
};
|
|
1492
|
+
for (const rootItem of parsed) {
|
|
1493
|
+
if (rootItem["root"]) {
|
|
1494
|
+
const rootChildren = rootItem["root"];
|
|
1495
|
+
if (Array.isArray(rootChildren)) {
|
|
1496
|
+
for (const child of rootChildren) {
|
|
1497
|
+
extractFromNode(child);
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
return items;
|
|
1503
|
+
}
|
|
1504
|
+
function matchesXPath(item, xpath) {
|
|
1505
|
+
const tagMatch = xpath.match(/\/{0,2}(\w+)/);
|
|
1506
|
+
if (tagMatch) {
|
|
1507
|
+
return item.tag === tagMatch[1];
|
|
1508
|
+
}
|
|
1509
|
+
return true;
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
// src/tags/attr.ts
|
|
1513
|
+
async function executeAttr(session, element) {
|
|
1514
|
+
const nameAttr = element.attributes.name;
|
|
1515
|
+
const fromAttr = element.attributes.from;
|
|
1516
|
+
if (!nameAttr) {
|
|
1517
|
+
throw new Error('<attr> requires "name" attribute');
|
|
1518
|
+
}
|
|
1519
|
+
if (!fromAttr) {
|
|
1520
|
+
throw new Error('<attr> requires "from" attribute');
|
|
1521
|
+
}
|
|
1522
|
+
let item;
|
|
1523
|
+
if (fromAttr.startsWith("$")) {
|
|
1524
|
+
const varName = fromAttr.substring(1);
|
|
1525
|
+
item = getVariable(session, varName);
|
|
1526
|
+
} else {
|
|
1527
|
+
const substituted = substituteVariables(session, fromAttr);
|
|
1528
|
+
item = getVariable(session, substituted);
|
|
1529
|
+
}
|
|
1530
|
+
if (!item) {
|
|
1531
|
+
return;
|
|
1532
|
+
}
|
|
1533
|
+
let value = "";
|
|
1534
|
+
if (typeof item === "object") {
|
|
1535
|
+
if (item.attributes && typeof item.attributes === "object") {
|
|
1536
|
+
value = item.attributes[nameAttr] || "";
|
|
1537
|
+
} else if (item[nameAttr] !== void 0) {
|
|
1538
|
+
value = String(item[nameAttr]);
|
|
1539
|
+
}
|
|
1540
|
+
} else if (typeof item === "string") {
|
|
1541
|
+
value = extractAttrFromXml(item, nameAttr);
|
|
1542
|
+
}
|
|
1543
|
+
session.output.push(value);
|
|
1544
|
+
}
|
|
1545
|
+
function extractAttrFromXml(xml, attrName) {
|
|
1546
|
+
const regex = new RegExp(`${attrName}="([^"]*)"`, "i");
|
|
1547
|
+
const match = xml.match(regex);
|
|
1548
|
+
return match ? match[1] : "";
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1446
1551
|
// src/runtime/interpreter.ts
|
|
1447
1552
|
async function integrate(session, element) {
|
|
1448
1553
|
if (session.limits.currentDepth >= session.limits.maxDepth) {
|
|
@@ -1526,9 +1631,25 @@ async function integrate(session, element) {
|
|
|
1526
1631
|
case "test-if":
|
|
1527
1632
|
await executeTestIf(session, element);
|
|
1528
1633
|
break;
|
|
1634
|
+
case "available-subroutines":
|
|
1635
|
+
await executeAvailableSubroutines(session, element);
|
|
1636
|
+
break;
|
|
1637
|
+
case "foreach":
|
|
1638
|
+
await executeForeach(session, element);
|
|
1639
|
+
break;
|
|
1640
|
+
case "attr":
|
|
1641
|
+
await executeAttr(session, element);
|
|
1642
|
+
break;
|
|
1529
1643
|
case "require_module":
|
|
1530
1644
|
await executeRequireModule(session, element);
|
|
1531
1645
|
break;
|
|
1646
|
+
case "dirac":
|
|
1647
|
+
case "DIRAC-ROOT":
|
|
1648
|
+
for (const child of element.children) {
|
|
1649
|
+
await integrate(session, child);
|
|
1650
|
+
if (session.isReturn || session.isBreak) break;
|
|
1651
|
+
}
|
|
1652
|
+
break;
|
|
1532
1653
|
default:
|
|
1533
1654
|
const subroutine = getSubroutine(session, element.tag);
|
|
1534
1655
|
if (subroutine) {
|
|
@@ -1552,7 +1673,6 @@ async function integrateChildren(session, element) {
|
|
|
1552
1673
|
}
|
|
1553
1674
|
|
|
1554
1675
|
export {
|
|
1555
|
-
DiracParser,
|
|
1556
1676
|
integrate,
|
|
1557
1677
|
integrateChildren
|
|
1558
1678
|
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// src/runtime/parser.ts
|
|
2
|
+
import { XMLParser } from "fast-xml-parser";
|
|
3
|
+
var DiracParser = class {
|
|
4
|
+
parser;
|
|
5
|
+
constructor() {
|
|
6
|
+
this.parser = new XMLParser({
|
|
7
|
+
ignoreAttributes: false,
|
|
8
|
+
attributeNamePrefix: "@_",
|
|
9
|
+
trimValues: false,
|
|
10
|
+
// Preserve whitespace in mixed content
|
|
11
|
+
parseAttributeValue: false,
|
|
12
|
+
parseTagValue: false,
|
|
13
|
+
textNodeName: "#text",
|
|
14
|
+
cdataPropName: "#cdata",
|
|
15
|
+
preserveOrder: true,
|
|
16
|
+
// Preserve element order!
|
|
17
|
+
commentPropName: "#comment"
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
parse(source) {
|
|
21
|
+
if (source.startsWith("#!")) {
|
|
22
|
+
source = source.replace(/^#!.*\n/, "");
|
|
23
|
+
}
|
|
24
|
+
source = `<DIRAC-ROOT>
|
|
25
|
+
${source}
|
|
26
|
+
</DIRAC-ROOT>`;
|
|
27
|
+
const result = this.parser.parse(source);
|
|
28
|
+
if (!Array.isArray(result) || result.length === 0) {
|
|
29
|
+
throw new Error("Empty or invalid XML");
|
|
30
|
+
}
|
|
31
|
+
for (const item of result) {
|
|
32
|
+
if (!item["#comment"]) {
|
|
33
|
+
return this.convertOrderedToElement(item);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
throw new Error("No root element found");
|
|
37
|
+
}
|
|
38
|
+
convertOrderedToElement(obj) {
|
|
39
|
+
const tagName = Object.keys(obj).find((k) => k !== ":@" && k !== "#comment");
|
|
40
|
+
if (!tagName) {
|
|
41
|
+
throw new Error("Invalid element structure");
|
|
42
|
+
}
|
|
43
|
+
const element = {
|
|
44
|
+
tag: tagName,
|
|
45
|
+
attributes: {},
|
|
46
|
+
children: []
|
|
47
|
+
};
|
|
48
|
+
if (obj[":@"]) {
|
|
49
|
+
for (const [key, value] of Object.entries(obj[":@"])) {
|
|
50
|
+
if (key.startsWith("@_")) {
|
|
51
|
+
element.attributes[key.slice(2)] = value;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const children = obj[tagName];
|
|
56
|
+
if (Array.isArray(children)) {
|
|
57
|
+
for (const child of children) {
|
|
58
|
+
if (child["#text"]) {
|
|
59
|
+
element.children.push({
|
|
60
|
+
tag: "",
|
|
61
|
+
text: child["#text"],
|
|
62
|
+
attributes: {},
|
|
63
|
+
children: []
|
|
64
|
+
});
|
|
65
|
+
if (!element.text) {
|
|
66
|
+
element.text = child["#text"];
|
|
67
|
+
} else {
|
|
68
|
+
element.text += child["#text"];
|
|
69
|
+
}
|
|
70
|
+
} else if (child["#comment"]) {
|
|
71
|
+
continue;
|
|
72
|
+
} else {
|
|
73
|
+
element.children.push(this.convertOrderedToElement(child));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return element;
|
|
78
|
+
}
|
|
79
|
+
// Old method - no longer used
|
|
80
|
+
convertToElement(obj, tagName) {
|
|
81
|
+
if (!tagName) {
|
|
82
|
+
const keys = Object.keys(obj);
|
|
83
|
+
if (keys.length === 0) {
|
|
84
|
+
throw new Error("Empty XML");
|
|
85
|
+
}
|
|
86
|
+
tagName = keys[0];
|
|
87
|
+
obj = obj[tagName];
|
|
88
|
+
}
|
|
89
|
+
const element = {
|
|
90
|
+
tag: tagName,
|
|
91
|
+
attributes: {},
|
|
92
|
+
children: []
|
|
93
|
+
};
|
|
94
|
+
if (typeof obj === "string") {
|
|
95
|
+
element.text = obj;
|
|
96
|
+
return element;
|
|
97
|
+
}
|
|
98
|
+
if (!obj) {
|
|
99
|
+
return element;
|
|
100
|
+
}
|
|
101
|
+
for (const key of Object.keys(obj)) {
|
|
102
|
+
const value = obj[key];
|
|
103
|
+
if (key === "#text") {
|
|
104
|
+
element.text = value;
|
|
105
|
+
} else if (key.startsWith("@_")) {
|
|
106
|
+
element.attributes[key.slice(2)] = value;
|
|
107
|
+
} else {
|
|
108
|
+
if (Array.isArray(value)) {
|
|
109
|
+
for (const item of value) {
|
|
110
|
+
element.children.push(this.convertToElement(item, key));
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
element.children.push(this.convertToElement(value, key));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return element;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export {
|
|
122
|
+
DiracParser
|
|
123
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
execute
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-UO6QEXZV.js";
|
|
5
|
+
import "./chunk-74EQEVS6.js";
|
|
6
|
+
import "./chunk-HRHAMPOB.js";
|
|
6
7
|
import "./chunk-E7PWEMZA.js";
|
|
7
8
|
import "./chunk-52ED23DR.js";
|
|
8
9
|
|
|
@@ -12,7 +13,7 @@ import "dotenv/config";
|
|
|
12
13
|
// package.json
|
|
13
14
|
var package_default = {
|
|
14
15
|
name: "dirac-lang",
|
|
15
|
-
version: "0.1.
|
|
16
|
+
version: "0.1.15",
|
|
16
17
|
description: "LLM-Augmented Declarative Execution",
|
|
17
18
|
type: "module",
|
|
18
19
|
main: "dist/index.js",
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -2,11 +2,13 @@ import {
|
|
|
2
2
|
createLLMAdapter,
|
|
3
3
|
execute,
|
|
4
4
|
executeUserCommand
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-UO6QEXZV.js";
|
|
6
6
|
import {
|
|
7
|
-
DiracParser,
|
|
8
7
|
integrate
|
|
9
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-74EQEVS6.js";
|
|
9
|
+
import {
|
|
10
|
+
DiracParser
|
|
11
|
+
} from "./chunk-HRHAMPOB.js";
|
|
10
12
|
import "./chunk-E7PWEMZA.js";
|
|
11
13
|
import {
|
|
12
14
|
createSession,
|