dirac-lang 0.1.22 → 0.1.24

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.
@@ -419,12 +419,12 @@ async function executeIf(session, element) {
419
419
  const condition = await evaluatePredicate(session, conditionElement);
420
420
  if (condition) {
421
421
  if (thenElement) {
422
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-WUPTTWCU.js");
422
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-MTIIHIIQ.js");
423
423
  await integrateChildren2(session, thenElement);
424
424
  }
425
425
  } else {
426
426
  if (elseElement) {
427
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-WUPTTWCU.js");
427
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-MTIIHIIQ.js");
428
428
  await integrateChildren2(session, elseElement);
429
429
  }
430
430
  }
@@ -437,7 +437,7 @@ async function evaluatePredicate(session, predicateElement) {
437
437
  return await evaluateCondition(session, predicateElement);
438
438
  }
439
439
  const outputLengthBefore = session.output.length;
440
- const { integrate: integrate2 } = await import("./interpreter-WUPTTWCU.js");
440
+ const { integrate: integrate2 } = await import("./interpreter-MTIIHIIQ.js");
441
441
  await integrate2(session, predicateElement);
442
442
  const newOutputChunks = session.output.slice(outputLengthBefore);
443
443
  const result = newOutputChunks.join("").trim();
@@ -460,11 +460,11 @@ async function evaluateCondition(session, condElement) {
460
460
  }
461
461
  const outputLengthBefore = session.output.length;
462
462
  const args = [];
463
- const { integrate: integrate2 } = await import("./interpreter-WUPTTWCU.js");
463
+ const { integrate: integrate2 } = await import("./interpreter-MTIIHIIQ.js");
464
464
  for (const child of condElement.children) {
465
465
  if (child.tag.toLowerCase() === "arg") {
466
466
  const argOutputStart = session.output.length;
467
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-WUPTTWCU.js");
467
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-MTIIHIIQ.js");
468
468
  await integrateChildren2(session, child);
469
469
  const newChunks = session.output.slice(argOutputStart);
470
470
  const argValue = newChunks.join("");
@@ -937,15 +937,56 @@ ${diracCode}
937
937
  }
938
938
 
939
939
  // src/tags/import.ts
940
- import { readFileSync } from "fs";
941
- import { resolve, dirname as dirname2 } from "path";
940
+ import { readFileSync, existsSync as existsSync2 } from "fs";
941
+ import { resolve, dirname as dirname2, join } from "path";
942
+ function resolveImportPath(src, currentDir) {
943
+ if (src.startsWith("./") || src.startsWith("../") || src.startsWith("/")) {
944
+ const resolved2 = resolve(currentDir, src);
945
+ return resolved2.endsWith(".di") ? resolved2 : resolved2 + ".di";
946
+ }
947
+ let searchDir = currentDir;
948
+ while (true) {
949
+ const nodeModulesPath = join(searchDir, "node_modules", src);
950
+ if (existsSync2(nodeModulesPath)) {
951
+ const packageJsonPath = join(nodeModulesPath, "package.json");
952
+ if (existsSync2(packageJsonPath)) {
953
+ try {
954
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
955
+ const mainFile = packageJson.main || "lib/index.di";
956
+ const entryPath = join(nodeModulesPath, mainFile);
957
+ if (existsSync2(entryPath)) {
958
+ return entryPath;
959
+ }
960
+ } catch (err) {
961
+ }
962
+ }
963
+ const fallbacks = [
964
+ join(nodeModulesPath, "lib", "index.di"),
965
+ join(nodeModulesPath, "index.di")
966
+ ];
967
+ for (const fallback of fallbacks) {
968
+ if (existsSync2(fallback)) {
969
+ return fallback;
970
+ }
971
+ }
972
+ throw new Error(`Package "${src}" found but no entry point (.di file) available`);
973
+ }
974
+ const parentDir = dirname2(searchDir);
975
+ if (parentDir === searchDir) {
976
+ break;
977
+ }
978
+ searchDir = parentDir;
979
+ }
980
+ const resolved = resolve(currentDir, src);
981
+ return resolved.endsWith(".di") ? resolved : resolved + ".di";
982
+ }
942
983
  async function executeImport(session, element) {
943
984
  const src = element.attributes.src;
944
985
  if (!src) {
945
986
  throw new Error("<import> requires src attribute");
946
987
  }
947
988
  const currentDir = session.currentFile ? dirname2(session.currentFile) : process.cwd();
948
- const importPath = resolve(currentDir, src);
989
+ const importPath = resolveImportPath(src, currentDir);
949
990
  if (session.debug) {
950
991
  console.error(`[IMPORT] Loading: ${importPath}`);
951
992
  }
@@ -1282,7 +1323,7 @@ async function executeTagCheck(session, element) {
1282
1323
  const executeTag = correctedTag || tagName;
1283
1324
  console.error(`[tag-check] Executing <${executeTag}/> as all checks passed and execute=true.`);
1284
1325
  const elementToExecute = correctedTag ? { ...child, tag: correctedTag } : child;
1285
- const { integrate: integrate2 } = await import("./interpreter-WUPTTWCU.js");
1326
+ const { integrate: integrate2 } = await import("./interpreter-MTIIHIIQ.js");
1286
1327
  await integrate2(session, elementToExecute);
1287
1328
  }
1288
1329
  }
@@ -1291,7 +1332,7 @@ async function executeTagCheck(session, element) {
1291
1332
  // src/tags/throw.ts
1292
1333
  async function executeThrow(session, element) {
1293
1334
  const exceptionName = element.attributes?.name || "exception";
1294
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-WUPTTWCU.js");
1335
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-MTIIHIIQ.js");
1295
1336
  const exceptionDom = {
1296
1337
  tag: "exception-content",
1297
1338
  attributes: { name: exceptionName },
@@ -1304,7 +1345,7 @@ async function executeThrow(session, element) {
1304
1345
  // src/tags/try.ts
1305
1346
  async function executeTry(session, element) {
1306
1347
  setExceptionBoundary(session);
1307
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-WUPTTWCU.js");
1348
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-MTIIHIIQ.js");
1308
1349
  await integrateChildren2(session, element);
1309
1350
  unsetExceptionBoundary(session);
1310
1351
  }
@@ -1314,7 +1355,7 @@ async function executeCatch(session, element) {
1314
1355
  const exceptionName = element.attributes?.name || "exception";
1315
1356
  const caughtCount = lookupException(session, exceptionName);
1316
1357
  if (caughtCount > 0) {
1317
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-WUPTTWCU.js");
1358
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-MTIIHIIQ.js");
1318
1359
  await integrateChildren2(session, element);
1319
1360
  }
1320
1361
  flushCurrentException(session);
@@ -1323,7 +1364,7 @@ async function executeCatch(session, element) {
1323
1364
  // src/tags/exception.ts
1324
1365
  async function executeException(session, element) {
1325
1366
  const exceptions = getCurrentExceptions(session);
1326
- const { integrateChildren: integrateChildren2 } = await import("./interpreter-WUPTTWCU.js");
1367
+ const { integrateChildren: integrateChildren2 } = await import("./interpreter-MTIIHIIQ.js");
1327
1368
  for (const exceptionDom of exceptions) {
1328
1369
  await integrateChildren2(session, exceptionDom);
1329
1370
  }
@@ -1463,7 +1504,7 @@ async function executeForeach(session, element) {
1463
1504
  const parser2 = new DiracParser2();
1464
1505
  try {
1465
1506
  const fromElement = parser2.parse(fromAttr);
1466
- const { integrate: integrate2 } = await import("./interpreter-WUPTTWCU.js");
1507
+ const { integrate: integrate2 } = await import("./interpreter-MTIIHIIQ.js");
1467
1508
  await integrate2(session, fromElement);
1468
1509
  } catch (e) {
1469
1510
  session.output = savedOutput;
@@ -1644,17 +1685,31 @@ async function executeInput(session, element) {
1644
1685
  emit(session, value);
1645
1686
  }
1646
1687
  async function readAllStdin() {
1688
+ process.stdin.removeAllListeners("data");
1689
+ process.stdin.removeAllListeners("end");
1690
+ process.stdin.removeAllListeners("error");
1647
1691
  return new Promise((resolve2, reject) => {
1648
1692
  const chunks = [];
1649
- process.stdin.on("data", (chunk) => {
1693
+ const onData = (chunk) => {
1650
1694
  chunks.push(chunk);
1651
- });
1652
- process.stdin.on("end", () => {
1653
- resolve2(Buffer.concat(chunks).toString("utf-8"));
1654
- });
1655
- process.stdin.on("error", (err) => {
1695
+ };
1696
+ const onEnd = () => {
1697
+ const result = Buffer.concat(chunks).toString("utf-8");
1698
+ process.stdin.removeListener("data", onData);
1699
+ process.stdin.removeListener("end", onEnd);
1700
+ process.stdin.removeListener("error", onError);
1701
+ resolve2(result);
1702
+ };
1703
+ const onError = (err) => {
1704
+ process.stdin.removeListener("data", onData);
1705
+ process.stdin.removeListener("end", onEnd);
1706
+ process.stdin.removeListener("error", onError);
1656
1707
  reject(err);
1657
- });
1708
+ };
1709
+ process.stdin.on("data", onData);
1710
+ process.stdin.on("end", onEnd);
1711
+ process.stdin.on("error", onError);
1712
+ process.stdin.resume();
1658
1713
  });
1659
1714
  }
1660
1715
  var stdinReader = null;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  integrate
3
- } from "./chunk-XGR3IHWY.js";
3
+ } from "./chunk-7OUYWIZV.js";
4
4
  import {
5
5
  DiracParser
6
6
  } from "./chunk-HRHAMPOB.js";
package/dist/cli.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  execute
4
- } from "./chunk-7X5JYLMO.js";
5
- import "./chunk-XGR3IHWY.js";
4
+ } from "./chunk-OUMUIBK3.js";
5
+ import "./chunk-7OUYWIZV.js";
6
6
  import "./chunk-HRHAMPOB.js";
7
7
  import "./chunk-E7PWEMZA.js";
8
8
  import "./chunk-52ED23DR.js";
@@ -13,7 +13,7 @@ import "dotenv/config";
13
13
  // package.json
14
14
  var package_default = {
15
15
  name: "dirac-lang",
16
- version: "0.1.22",
16
+ version: "0.1.23",
17
17
  description: "LLM-Augmented Declarative Execution",
18
18
  type: "module",
19
19
  main: "dist/index.js",
package/dist/index.js CHANGED
@@ -2,10 +2,10 @@ import {
2
2
  createLLMAdapter,
3
3
  execute,
4
4
  executeUserCommand
5
- } from "./chunk-7X5JYLMO.js";
5
+ } from "./chunk-OUMUIBK3.js";
6
6
  import {
7
7
  integrate
8
- } from "./chunk-XGR3IHWY.js";
8
+ } from "./chunk-7OUYWIZV.js";
9
9
  import {
10
10
  DiracParser
11
11
  } from "./chunk-HRHAMPOB.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  integrate,
3
3
  integrateChildren
4
- } from "./chunk-XGR3IHWY.js";
4
+ } from "./chunk-7OUYWIZV.js";
5
5
  import "./chunk-HRHAMPOB.js";
6
6
  import "./chunk-E7PWEMZA.js";
7
7
  import "./chunk-52ED23DR.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  integrate
3
- } from "./chunk-XGR3IHWY.js";
3
+ } from "./chunk-7OUYWIZV.js";
4
4
  import {
5
5
  DiracParser
6
6
  } from "./chunk-HRHAMPOB.js";
@@ -55,17 +55,75 @@ var TestRunner = class {
55
55
  passed: false
56
56
  };
57
57
  try {
58
- const parser = new DiracParser();
59
- const ast = parser.parse(cleanContent);
60
- const session = createSession({ ...this.config, filePath });
61
- await integrate(session, ast);
62
- const output = getOutput(session);
63
- result.actualOutput = output;
58
+ const stdinFile = filePath.replace(".test.di", ".txt");
59
+ let stdinData;
60
+ if (fs.existsSync(stdinFile)) {
61
+ stdinData = fs.readFileSync(stdinFile, "utf-8");
62
+ }
63
+ if (stdinData !== void 0) {
64
+ const originalOn = process.stdin.on.bind(process.stdin);
65
+ const originalResume = process.stdin.resume.bind(process.stdin);
66
+ const originalRemoveAllListeners = process.stdin.removeAllListeners.bind(process.stdin);
67
+ const originalRemoveListener = process.stdin.removeListener.bind(process.stdin);
68
+ const listeners = {};
69
+ process.stdin.on = function(event, callback) {
70
+ if (!listeners[event]) listeners[event] = [];
71
+ listeners[event].push(callback);
72
+ return this;
73
+ };
74
+ process.stdin.removeAllListeners = function(event) {
75
+ if (event) {
76
+ delete listeners[event];
77
+ } else {
78
+ Object.keys(listeners).forEach((k) => delete listeners[k]);
79
+ }
80
+ return this;
81
+ };
82
+ process.stdin.removeListener = function(event, callback) {
83
+ if (listeners[event]) {
84
+ listeners[event] = listeners[event].filter((fn) => fn !== callback);
85
+ }
86
+ return this;
87
+ };
88
+ process.stdin.resume = function() {
89
+ setImmediate(() => {
90
+ if (listeners["data"]) {
91
+ listeners["data"].forEach((fn) => fn(Buffer.from(stdinData, "utf-8")));
92
+ }
93
+ setImmediate(() => {
94
+ if (listeners["end"]) {
95
+ listeners["end"].forEach((fn) => fn());
96
+ }
97
+ });
98
+ });
99
+ return this;
100
+ };
101
+ try {
102
+ const parser = new DiracParser();
103
+ const ast = parser.parse(cleanContent);
104
+ const session = createSession({ ...this.config, filePath });
105
+ await integrate(session, ast);
106
+ const output = getOutput(session);
107
+ result.actualOutput = output;
108
+ } finally {
109
+ process.stdin.on = originalOn;
110
+ process.stdin.resume = originalResume;
111
+ process.stdin.removeAllListeners = originalRemoveAllListeners;
112
+ process.stdin.removeListener = originalRemoveListener;
113
+ }
114
+ } else {
115
+ const parser = new DiracParser();
116
+ const ast = parser.parse(cleanContent);
117
+ const session = createSession({ ...this.config, filePath });
118
+ await integrate(session, ast);
119
+ const output = getOutput(session);
120
+ result.actualOutput = output;
121
+ }
64
122
  if (metadata.expectError) {
65
123
  result.passed = false;
66
- result.error = `Expected error but test succeeded. Output: ${output}`;
124
+ result.error = `Expected error but test succeeded. Output: ${result.actualOutput}`;
67
125
  } else if (metadata.expected !== void 0) {
68
- const normalizedActual = output.replace(/\s+/g, " ").trim();
126
+ const normalizedActual = result.actualOutput.replace(/\s+/g, " ").trim();
69
127
  const normalizedExpected = metadata.expected.replace(/\s+/g, " ").trim();
70
128
  if (normalizedActual === normalizedExpected) {
71
129
  result.passed = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dirac-lang",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
4
4
  "description": "LLM-Augmented Declarative Execution",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -4,11 +4,80 @@
4
4
  */
5
5
 
6
6
  import type { DiracSession, DiracElement } from '../types/index.js';
7
- import { readFileSync } from 'fs';
8
- import { resolve, dirname } from 'path';
7
+ import { readFileSync, existsSync } from 'fs';
8
+ import { resolve, dirname, join } from 'path';
9
9
  import { DiracParser } from '../runtime/parser.js';
10
10
  import { integrate } from '../runtime/interpreter.js';
11
11
 
12
+ /**
13
+ * Resolve import path - supports relative paths and node_modules packages
14
+ * @param src - The import source (e.g., "./file.di" or "package-name")
15
+ * @param currentDir - Current directory context
16
+ * @returns Resolved absolute path
17
+ */
18
+ function resolveImportPath(src: string, currentDir: string): string {
19
+ // If it starts with ./ or ../ or /, it's a relative/absolute path
20
+ if (src.startsWith('./') || src.startsWith('../') || src.startsWith('/')) {
21
+ const resolved = resolve(currentDir, src);
22
+ // Add .di extension if not present
23
+ return resolved.endsWith('.di') ? resolved : resolved + '.di';
24
+ }
25
+
26
+ // Otherwise, try to resolve as a package from node_modules
27
+ // Walk up the directory tree looking for node_modules
28
+ let searchDir = currentDir;
29
+
30
+ while (true) {
31
+ const nodeModulesPath = join(searchDir, 'node_modules', src);
32
+
33
+ if (existsSync(nodeModulesPath)) {
34
+ // Found the package, now find the entry point
35
+ // Try to read package.json to get the "main" field
36
+ const packageJsonPath = join(nodeModulesPath, 'package.json');
37
+
38
+ if (existsSync(packageJsonPath)) {
39
+ try {
40
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
41
+ const mainFile = packageJson.main || 'lib/index.di';
42
+ const entryPath = join(nodeModulesPath, mainFile);
43
+
44
+ if (existsSync(entryPath)) {
45
+ return entryPath;
46
+ }
47
+ } catch (err) {
48
+ // If package.json parse fails, fall through to default
49
+ }
50
+ }
51
+
52
+ // Fallback: try common entry points
53
+ const fallbacks = [
54
+ join(nodeModulesPath, 'lib', 'index.di'),
55
+ join(nodeModulesPath, 'index.di'),
56
+ ];
57
+
58
+ for (const fallback of fallbacks) {
59
+ if (existsSync(fallback)) {
60
+ return fallback;
61
+ }
62
+ }
63
+
64
+ throw new Error(`Package "${src}" found but no entry point (.di file) available`);
65
+ }
66
+
67
+ // Move up one directory
68
+ const parentDir = dirname(searchDir);
69
+ if (parentDir === searchDir) {
70
+ // Reached root, package not found
71
+ break;
72
+ }
73
+ searchDir = parentDir;
74
+ }
75
+
76
+ // Package not found in node_modules, treat as relative path with .di extension
77
+ const resolved = resolve(currentDir, src);
78
+ return resolved.endsWith('.di') ? resolved : resolved + '.di';
79
+ }
80
+
12
81
  export async function executeImport(session: DiracSession, element: DiracElement): Promise<void> {
13
82
  const src = element.attributes.src;
14
83
 
@@ -19,8 +88,8 @@ export async function executeImport(session: DiracSession, element: DiracElement
19
88
  // Get the current file's directory (if available in session)
20
89
  const currentDir = session.currentFile ? dirname(session.currentFile) : process.cwd();
21
90
 
22
- // Resolve the import path
23
- const importPath = resolve(currentDir, src);
91
+ // Resolve the import path (handles both relative paths and node_modules packages)
92
+ const importPath = resolveImportPath(src, currentDir);
24
93
 
25
94
  if (session.debug) {
26
95
  console.error(`[IMPORT] Loading: ${importPath}`);
package/src/tags/input.ts CHANGED
@@ -65,20 +65,43 @@ export async function executeInput(session: DiracSession, element: DiracElement)
65
65
  * Read all stdin content at once
66
66
  */
67
67
  async function readAllStdin(): Promise<string> {
68
+ // Remove any existing listeners to avoid conflicts
69
+ process.stdin.removeAllListeners('data');
70
+ process.stdin.removeAllListeners('end');
71
+ process.stdin.removeAllListeners('error');
72
+
68
73
  return new Promise((resolve, reject) => {
69
74
  const chunks: Buffer[] = [];
70
75
 
71
- process.stdin.on('data', (chunk) => {
76
+ const onData = (chunk: Buffer) => {
72
77
  chunks.push(chunk);
73
- });
78
+ };
74
79
 
75
- process.stdin.on('end', () => {
76
- resolve(Buffer.concat(chunks).toString('utf-8'));
77
- });
80
+ const onEnd = () => {
81
+ const result = Buffer.concat(chunks).toString('utf-8');
82
+
83
+ // Clean up listeners
84
+ process.stdin.removeListener('data', onData);
85
+ process.stdin.removeListener('end', onEnd);
86
+ process.stdin.removeListener('error', onError);
87
+
88
+ resolve(result);
89
+ };
78
90
 
79
- process.stdin.on('error', (err) => {
91
+ const onError = (err: Error) => {
92
+ // Clean up listeners
93
+ process.stdin.removeListener('data', onData);
94
+ process.stdin.removeListener('end', onEnd);
95
+ process.stdin.removeListener('error', onError);
96
+
80
97
  reject(err);
81
- });
98
+ };
99
+
100
+ process.stdin.on('data', onData);
101
+ process.stdin.on('end', onEnd);
102
+ process.stdin.on('error', onError);
103
+
104
+ process.stdin.resume();
82
105
  });
83
106
  }
84
107
 
@@ -81,22 +81,96 @@ export class TestRunner {
81
81
  };
82
82
 
83
83
  try {
84
- const parser = new DiracParser();
85
- const ast = parser.parse(cleanContent);
86
- const session = createSession({ ...this.config, filePath });
87
- await integrate(session, ast);
88
- const output = getOutput(session);
89
-
90
- result.actualOutput = output;
84
+ // Check if there's a stdin input file for this test
85
+ const stdinFile = filePath.replace('.test.di', '.txt');
86
+ let stdinData: string | undefined;
87
+ if (fs.existsSync(stdinFile)) {
88
+ stdinData = fs.readFileSync(stdinFile, 'utf-8');
89
+ }
90
+
91
+ // If stdin data exists, we need to mock stdin
92
+ // Since we can't replace process.stdin directly, we'll use a workaround:
93
+ // temporarily store data in a place the input tag can access it
94
+ if (stdinData !== undefined) {
95
+ // Save original methods
96
+ const originalOn = process.stdin.on.bind(process.stdin);
97
+ const originalResume = process.stdin.resume.bind(process.stdin);
98
+ const originalRemoveAllListeners = process.stdin.removeAllListeners.bind(process.stdin);
99
+ const originalRemoveListener = process.stdin.removeListener.bind(process.stdin);
100
+
101
+ // Mock stdin methods
102
+ const listeners: { [key: string]: Function[] } = {};
103
+
104
+ (process.stdin as any).on = function(event: string, callback: Function) {
105
+ if (!listeners[event]) listeners[event] = [];
106
+ listeners[event].push(callback);
107
+ return this;
108
+ };
109
+
110
+ (process.stdin as any).removeAllListeners = function(event?: string) {
111
+ if (event) {
112
+ delete listeners[event];
113
+ } else {
114
+ Object.keys(listeners).forEach(k => delete listeners[k]);
115
+ }
116
+ return this;
117
+ };
118
+
119
+ (process.stdin as any).removeListener = function(event: string, callback: Function) {
120
+ if (listeners[event]) {
121
+ listeners[event] = listeners[event].filter(fn => fn !== callback);
122
+ }
123
+ return this;
124
+ };
125
+
126
+ (process.stdin as any).resume = function() {
127
+ // Simulate data event
128
+ setImmediate(() => {
129
+ if (listeners['data']) {
130
+ listeners['data'].forEach(fn => fn(Buffer.from(stdinData!, 'utf-8')));
131
+ }
132
+ // Simulate end event
133
+ setImmediate(() => {
134
+ if (listeners['end']) {
135
+ listeners['end'].forEach(fn => fn());
136
+ }
137
+ });
138
+ });
139
+ return this;
140
+ };
141
+
142
+ try {
143
+ const parser = new DiracParser();
144
+ const ast = parser.parse(cleanContent);
145
+ const session = createSession({ ...this.config, filePath });
146
+ await integrate(session, ast);
147
+ const output = getOutput(session);
148
+ result.actualOutput = output;
149
+ } finally {
150
+ // Restore original methods
151
+ (process.stdin as any).on = originalOn;
152
+ (process.stdin as any).resume = originalResume;
153
+ (process.stdin as any).removeAllListeners = originalRemoveAllListeners;
154
+ (process.stdin as any).removeListener = originalRemoveListener;
155
+ }
156
+ } else {
157
+ // Normal test without stdin
158
+ const parser = new DiracParser();
159
+ const ast = parser.parse(cleanContent);
160
+ const session = createSession({ ...this.config, filePath });
161
+ await integrate(session, ast);
162
+ const output = getOutput(session);
163
+ result.actualOutput = output;
164
+ }
91
165
 
92
166
  if (metadata.expectError) {
93
167
  // Expected an error but got success
94
168
  result.passed = false;
95
- result.error = `Expected error but test succeeded. Output: ${output}`;
169
+ result.error = `Expected error but test succeeded. Output: ${result.actualOutput}`;
96
170
  } else if (metadata.expected !== undefined) {
97
171
  // Check if output matches expected
98
172
  // Normalize whitespace for comparison (collapse multiple spaces/newlines)
99
- const normalizedActual = output.replace(/\s+/g, ' ').trim();
173
+ const normalizedActual = result.actualOutput!.replace(/\s+/g, ' ').trim();
100
174
  const normalizedExpected = metadata.expected.replace(/\s+/g, ' ').trim();
101
175
 
102
176
  if (normalizedActual === normalizedExpected) {
@@ -0,0 +1,8 @@
1
+ <!-- TEST: input_stdin_all -->
2
+ <!-- EXPECT: hello from stdin -->
3
+ <dirac>
4
+ <defvar name="data">
5
+ <input source="stdin" mode="all"/>
6
+ </defvar>
7
+ <output><variable name="data"/></output>
8
+ </dirac>
@@ -0,0 +1 @@
1
+ hello from stdin