dirac-browser 0.1.1

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.
Files changed (67) hide show
  1. package/README.md +88 -0
  2. package/dist/chatbox.d.ts +1 -0
  3. package/dist/chatbox.js +81 -0
  4. package/dist/index.d.ts +33 -0
  5. package/dist/index.js +39 -0
  6. package/dist/runtime/braket-parser.d.ts +44 -0
  7. package/dist/runtime/braket-parser.js +208 -0
  8. package/dist/runtime/interpreter.d.ts +6 -0
  9. package/dist/runtime/interpreter.js +110 -0
  10. package/dist/runtime/parser.d.ts +11 -0
  11. package/dist/runtime/parser.js +135 -0
  12. package/dist/runtime/session.d.ts +43 -0
  13. package/dist/runtime/session.js +171 -0
  14. package/dist/tags/assign.d.ts +6 -0
  15. package/dist/tags/assign.js +32 -0
  16. package/dist/tags/call.d.ts +6 -0
  17. package/dist/tags/call.js +130 -0
  18. package/dist/tags/defvar.d.ts +6 -0
  19. package/dist/tags/defvar.js +27 -0
  20. package/dist/tags/eval.d.ts +6 -0
  21. package/dist/tags/eval.js +55 -0
  22. package/dist/tags/execute.d.ts +6 -0
  23. package/dist/tags/execute.js +45 -0
  24. package/dist/tags/expr.d.ts +8 -0
  25. package/dist/tags/expr.js +107 -0
  26. package/dist/tags/if.d.ts +6 -0
  27. package/dist/tags/if.js +46 -0
  28. package/dist/tags/llm.d.ts +6 -0
  29. package/dist/tags/llm.js +73 -0
  30. package/dist/tags/loop.d.ts +6 -0
  31. package/dist/tags/loop.js +31 -0
  32. package/dist/tags/output.d.ts +6 -0
  33. package/dist/tags/output.js +19 -0
  34. package/dist/tags/parameters.d.ts +6 -0
  35. package/dist/tags/parameters.js +63 -0
  36. package/dist/tags/subroutine.d.ts +6 -0
  37. package/dist/tags/subroutine.js +41 -0
  38. package/dist/tags/variable.d.ts +6 -0
  39. package/dist/tags/variable.js +20 -0
  40. package/dist/types/index.d.ts +76 -0
  41. package/dist/types/index.js +5 -0
  42. package/dist/utils/llm-adapter.d.ts +22 -0
  43. package/dist/utils/llm-adapter.js +91 -0
  44. package/examples/llm-reflection-test.di +18 -0
  45. package/package.json +21 -0
  46. package/src/chatbox.ts +89 -0
  47. package/src/index.ts +47 -0
  48. package/src/runtime/braket-parser.ts +234 -0
  49. package/src/runtime/interpreter.ts +129 -0
  50. package/src/runtime/parser.ts +151 -0
  51. package/src/runtime/session.ts +209 -0
  52. package/src/tags/assign.ts +37 -0
  53. package/src/tags/call.ts +166 -0
  54. package/src/tags/defvar.ts +32 -0
  55. package/src/tags/eval.ts +65 -0
  56. package/src/tags/execute.ts +52 -0
  57. package/src/tags/expr.ts +128 -0
  58. package/src/tags/if.ts +58 -0
  59. package/src/tags/llm.ts +88 -0
  60. package/src/tags/loop.ts +43 -0
  61. package/src/tags/output.ts +23 -0
  62. package/src/tags/parameters.ts +77 -0
  63. package/src/tags/subroutine.ts +52 -0
  64. package/src/tags/variable.ts +27 -0
  65. package/src/types/index.ts +103 -0
  66. package/src/utils/llm-adapter.ts +118 -0
  67. package/tsconfig.json +18 -0
package/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # Dirac Browser
2
+
3
+ Browser-compatible version of the Dirac language interpreter with no Node.js dependencies.
4
+
5
+ ## Overview
6
+
7
+ `dirac-lang-browser` is a browser-safe implementation of the Dirac declarative execution language. It provides the same core functionality as `dirac-lang` but excludes Node.js-specific dependencies, making it suitable for client-side web applications.
8
+
9
+ ## Features
10
+
11
+ - ✅ Full Dirac language support (XML-based declarative execution)
12
+ - ✅ Subroutine composition with variable substitution
13
+ - ✅ Parameter passing with `{variable}` syntax
14
+ - ✅ Browser-compatible (no Node.js dependencies)
15
+ - ✅ TypeScript support
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install dirac-lang-browser
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ```typescript
26
+ import { execute } from 'dirac-lang-browser';
27
+
28
+ const script = `
29
+ <subroutine name="greet">
30
+ <parameters select="@name"/>
31
+ <eval>
32
+ 'Hello, ' + name + '!'
33
+ </eval>
34
+ </subroutine>
35
+
36
+ <call name="greet" name="World"/>
37
+ `;
38
+
39
+ const result = await execute(script);
40
+ console.log(result); // "Hello, World!"
41
+ ```
42
+
43
+ ## Recent Fixes
44
+
45
+ ### Variable Substitution in Nested Subroutine Calls (v0.1.0)
46
+
47
+ Fixed critical bug where variable substitution in nested `<call>` tags was not working correctly:
48
+
49
+ - ✅ Added support for `{var}` pattern in `substituteVariables()`
50
+ - ✅ Added attribute substitution in `executeCallInternal()` before parameter passing
51
+ - ✅ Enables proper subroutine composition
52
+
53
+ Example that now works:
54
+ ```xml
55
+ <subroutine name="set-background-color">
56
+ <parameters select="@color"/>
57
+ <eval>store.set('backgroundColor', color)</eval>
58
+ </subroutine>
59
+
60
+ <subroutine name="background">
61
+ <parameters select="@color"/>
62
+ <call name="set-background-color" color="{color}"/>
63
+ </subroutine>
64
+
65
+ <call name="background" color="red"/>
66
+ ```
67
+
68
+ ## Development
69
+
70
+ ```bash
71
+ # Install dependencies
72
+ npm install
73
+
74
+ # Build
75
+ npm run build
76
+
77
+ # Run tests
78
+ npm test
79
+ ```
80
+
81
+ ## License
82
+
83
+ MIT
84
+
85
+ ## Related Projects
86
+
87
+ - [dirac-lang](https://github.com/wangzhi63/dirac) - Node.js version with full features
88
+ - [dirac-angular-example](https://github.com/wangzhi63/dirac-angular-example) - Example Angular app with LLM integration
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Dirac Chatbox Web Component
3
+ * Usage: <dirac-chatbox resource="/assets/ui-services.dirac.xml"></dirac-chatbox>
4
+ */
5
+ import { execute, createSession } from './index.js';
6
+ class DiracChatbox extends HTMLElement {
7
+ constructor() {
8
+ super();
9
+ this.resourceUrl = '';
10
+ this.resourceLoaded = false;
11
+ this.shadow = this.attachShadow({ mode: 'open' });
12
+ this.render();
13
+ }
14
+ static get observedAttributes() {
15
+ return ['resource'];
16
+ }
17
+ attributeChangedCallback(name, oldValue, newValue) {
18
+ if (name === 'resource' && newValue) {
19
+ this.resourceUrl = newValue;
20
+ this.loadResource();
21
+ }
22
+ }
23
+ connectedCallback() {
24
+ if (this.getAttribute('resource')) {
25
+ this.resourceUrl = this.getAttribute('resource');
26
+ this.loadResource();
27
+ }
28
+ }
29
+ async loadResource() {
30
+ try {
31
+ const res = await fetch(this.resourceUrl);
32
+ const xml = await res.text();
33
+ this.session = createSession({});
34
+ await execute(xml, this.session.config); // Register subroutines
35
+ this.resourceLoaded = true;
36
+ }
37
+ catch (err) {
38
+ this.shadow.innerHTML = `<div style="color:red">Failed to load resource: ${err}</div>`;
39
+ }
40
+ }
41
+ render() {
42
+ this.shadow.innerHTML = `
43
+ <style>
44
+ .chatbox { border: 1px solid #ccc; padding: 1em; border-radius: 8px; width: 100%; max-width: 400px; font-family: sans-serif; }
45
+ .messages { min-height: 100px; margin-bottom: 1em; }
46
+ .input-row { display: flex; gap: 0.5em; }
47
+ input[type=text] { flex: 1; padding: 0.5em; border-radius: 4px; border: 1px solid #aaa; }
48
+ button { padding: 0.5em 1em; border-radius: 4px; border: none; background: #007bff; color: white; cursor: pointer; }
49
+ button:disabled { background: #aaa; }
50
+ </style>
51
+ <div class="chatbox">
52
+ <div class="messages"></div>
53
+ <form class="input-row">
54
+ <input type="text" placeholder="Type your message..." />
55
+ <button type="submit">Send</button>
56
+ </form>
57
+ </div>
58
+ `;
59
+ this.shadow.querySelector('form').addEventListener('submit', e => this.onSend(e));
60
+ }
61
+ async onSend(e) {
62
+ e.preventDefault();
63
+ const input = this.shadow.querySelector('input[type=text]');
64
+ const messages = this.shadow.querySelector('.messages');
65
+ const userMsg = input.value.trim();
66
+ if (!userMsg || !this.resourceLoaded)
67
+ return;
68
+ messages.innerHTML += `<div><b>You:</b> ${userMsg}</div>`;
69
+ input.value = '';
70
+ // Execute Dirac with <llm>userMsg</llm>
71
+ const script = `<llm>${userMsg}</llm>`;
72
+ try {
73
+ const result = await execute(script, this.session.config);
74
+ messages.innerHTML += `<div><b>Dirac:</b> ${result}</div>`;
75
+ }
76
+ catch (err) {
77
+ messages.innerHTML += `<div style="color:red"><b>Error:</b> ${err}</div>`;
78
+ }
79
+ }
80
+ }
81
+ customElements.define('dirac-chatbox', DiracChatbox);
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Dirac Language Browser Edition
3
+ * Browser-compatible interpreter without Node.js dependencies
4
+ */
5
+ export { DiracParser } from './runtime/parser.js';
6
+ export { createSession, getOutput, getAvailableSubroutines } from './runtime/session.js';
7
+ export { integrate } from './runtime/interpreter.js';
8
+ export { createLLMAdapter, executeUserCommand } from './utils/llm-adapter.js';
9
+ export type { DiracSession, DiracConfig, DiracElement, ParameterMetadata } from './types/index.js';
10
+ export type { LLMPromptGenerator } from './utils/llm-adapter.js';
11
+ import type { DiracConfig } from './types/index.js';
12
+ /**
13
+ * Execute Dirac source code in browser
14
+ *
15
+ * @param source - Dirac XML/HTML source code
16
+ * @param config - Configuration including customContext for injecting services
17
+ * @returns Promise resolving to output string
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const script = `
22
+ * <sequence>
23
+ * <defvar name="x"><eval>42</eval></defvar>
24
+ * <output><variable name="x"/></output>
25
+ * </sequence>
26
+ * `;
27
+ *
28
+ * const result = await execute(script, {
29
+ * customContext: { myService: serviceInstance }
30
+ * });
31
+ * ```
32
+ */
33
+ export declare function execute(source: string, config?: DiracConfig): Promise<string>;
package/dist/index.js ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Dirac Language Browser Edition
3
+ * Browser-compatible interpreter without Node.js dependencies
4
+ */
5
+ export { DiracParser } from './runtime/parser.js';
6
+ export { createSession, getOutput, getAvailableSubroutines } from './runtime/session.js';
7
+ export { integrate } from './runtime/interpreter.js';
8
+ export { createLLMAdapter, executeUserCommand } from './utils/llm-adapter.js';
9
+ import { DiracParser } from './runtime/parser.js';
10
+ import { createSession, getOutput } from './runtime/session.js';
11
+ import { integrate } from './runtime/interpreter.js';
12
+ /**
13
+ * Execute Dirac source code in browser
14
+ *
15
+ * @param source - Dirac XML/HTML source code
16
+ * @param config - Configuration including customContext for injecting services
17
+ * @returns Promise resolving to output string
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const script = `
22
+ * <sequence>
23
+ * <defvar name="x"><eval>42</eval></defvar>
24
+ * <output><variable name="x"/></output>
25
+ * </sequence>
26
+ * `;
27
+ *
28
+ * const result = await execute(script, {
29
+ * customContext: { myService: serviceInstance }
30
+ * });
31
+ * ```
32
+ */
33
+ export async function execute(source, config = {}) {
34
+ const parser = new DiracParser();
35
+ const session = createSession(config);
36
+ const ast = parser.parse(source);
37
+ await integrate(session, ast);
38
+ return getOutput(session);
39
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Bra-Ket Parser - Converts bra-ket notation to XML
3
+ *
4
+ * Syntax:
5
+ * - Bra (subroutine): <name| ... defines a subroutine
6
+ * - Ket (everything else): |tag attrs> ... can have children/content
7
+ * - Indentation: Defines scope (like Python/YAML)
8
+ *
9
+ * Examples:
10
+ * |output>Hello World → <output>Hello World</output>
11
+ * |variable name=x> → <variable name="x"/>
12
+ * <add| → <subroutine name="add">
13
+ * |output>test → <output>test</output>
14
+ * → </subroutine>
15
+ */
16
+ export declare class BraKetParser {
17
+ private lines;
18
+ private currentLine;
19
+ /**
20
+ * Parse bra-ket notation and compile to XML
21
+ */
22
+ parse(source: string): string;
23
+ /**
24
+ * Parse a block of lines at a given indentation level
25
+ */
26
+ private parseBlock;
27
+ /**
28
+ * Parse a single line into structured form
29
+ */
30
+ private parseLine;
31
+ /**
32
+ * Convert bra-ket attribute syntax to XML
33
+ * Examples:
34
+ * name=value → name="value"
35
+ * x=5 y=10 → x="5" y="10"
36
+ * select=@* → select="@*"
37
+ */
38
+ private convertAttributes;
39
+ /**
40
+ * Convert inline kets within text content
41
+ * Example: "Hello |variable name=x> world" → "Hello <variable name="x"/> world"
42
+ */
43
+ private convertInlineKets;
44
+ }
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Bra-Ket Parser - Converts bra-ket notation to XML
3
+ *
4
+ * Syntax:
5
+ * - Bra (subroutine): <name| ... defines a subroutine
6
+ * - Ket (everything else): |tag attrs> ... can have children/content
7
+ * - Indentation: Defines scope (like Python/YAML)
8
+ *
9
+ * Examples:
10
+ * |output>Hello World → <output>Hello World</output>
11
+ * |variable name=x> → <variable name="x"/>
12
+ * <add| → <subroutine name="add">
13
+ * |output>test → <output>test</output>
14
+ * → </subroutine>
15
+ */
16
+ export class BraKetParser {
17
+ constructor() {
18
+ this.lines = [];
19
+ this.currentLine = 0;
20
+ }
21
+ /**
22
+ * Parse bra-ket notation and compile to XML
23
+ */
24
+ parse(source) {
25
+ this.lines = source.split('\n');
26
+ this.currentLine = 0;
27
+ const xml = ['<dirac>'];
28
+ this.parseBlock(xml, -1);
29
+ xml.push('</dirac>');
30
+ return xml.join('\n');
31
+ }
32
+ /**
33
+ * Parse a block of lines at a given indentation level
34
+ */
35
+ parseBlock(output, parentIndent) {
36
+ while (this.currentLine < this.lines.length) {
37
+ const line = this.parseLine(this.lines[this.currentLine]);
38
+ // Empty lines are preserved as-is
39
+ if (line.type === 'empty') {
40
+ this.currentLine++;
41
+ continue;
42
+ }
43
+ // If indent is less than or equal to parent, we're done with this block
44
+ if (line.indent <= parentIndent) {
45
+ break;
46
+ }
47
+ // Bra: <name| defines a subroutine
48
+ if (line.type === 'bra') {
49
+ const attrs = line.attrs ? ` ${this.convertAttributes(line.attrs)}` : '';
50
+ output.push(`${' '.repeat(line.indent)}<subroutine name="${line.tag}"${attrs}>`);
51
+ this.currentLine++;
52
+ this.parseBlock(output, line.indent);
53
+ output.push(`${' '.repeat(line.indent)}</subroutine>`);
54
+ continue;
55
+ }
56
+ // Ket: |tag attrs>
57
+ if (line.type === 'ket') {
58
+ const indent = ' '.repeat(line.indent);
59
+ const attrs = line.attrs ? ` ${this.convertAttributes(line.attrs)}` : '';
60
+ // Check if next line is more indented (has children/content)
61
+ const nextLine = this.currentLine + 1 < this.lines.length
62
+ ? this.parseLine(this.lines[this.currentLine + 1])
63
+ : null;
64
+ if (nextLine && nextLine.indent > line.indent && nextLine.type !== 'empty') {
65
+ // Has children - opening tag
66
+ output.push(`${indent}<${line.tag}${attrs}>`);
67
+ this.currentLine++;
68
+ this.parseBlock(output, line.indent);
69
+ output.push(`${indent}</${line.tag}>`);
70
+ }
71
+ else {
72
+ // Self-closing or inline text
73
+ if (line.text) {
74
+ // Inline text with embedded kets
75
+ const content = this.convertInlineKets(line.text);
76
+ output.push(`${indent}<${line.tag}${attrs}>${content}</${line.tag}>`);
77
+ }
78
+ else {
79
+ // Self-closing
80
+ output.push(`${indent}<${line.tag}${attrs}/>`);
81
+ }
82
+ this.currentLine++;
83
+ }
84
+ continue;
85
+ }
86
+ // Plain text content
87
+ if (line.type === 'text') {
88
+ const indent = ' '.repeat(line.indent);
89
+ const content = this.convertInlineKets(line.text || '');
90
+ output.push(`${indent}${content}`);
91
+ this.currentLine++;
92
+ continue;
93
+ }
94
+ }
95
+ }
96
+ /**
97
+ * Parse a single line into structured form
98
+ */
99
+ parseLine(raw) {
100
+ // Count leading spaces for indentation
101
+ const match = raw.match(/^(\s*)(.*)/);
102
+ const indent = match ? Math.floor(match[1].length / 2) : 0;
103
+ const content = match ? match[2] : '';
104
+ // Empty line
105
+ if (!content.trim()) {
106
+ return { indent, type: 'empty', raw };
107
+ }
108
+ // Bra: <name| or <name attrs|
109
+ const braMatch = content.match(/^<([a-zA-Z_][a-zA-Z0-9_-]*)\s*([^|]*)\|$/);
110
+ if (braMatch) {
111
+ return {
112
+ indent,
113
+ type: 'bra',
114
+ tag: braMatch[1],
115
+ attrs: braMatch[2].trim() || undefined,
116
+ raw
117
+ };
118
+ }
119
+ // Ket: |tag> or |tag attrs> or |tag>text
120
+ const ketMatch = content.match(/^\|([a-zA-Z_][a-zA-Z0-9_-]*)\s*([^>]*?)>\s*(.*)/);
121
+ if (ketMatch) {
122
+ return {
123
+ indent,
124
+ type: 'ket',
125
+ tag: ketMatch[1],
126
+ attrs: ketMatch[2].trim() || undefined,
127
+ text: ketMatch[3] || undefined,
128
+ raw
129
+ };
130
+ }
131
+ // Plain text
132
+ return {
133
+ indent,
134
+ type: 'text',
135
+ text: content,
136
+ raw
137
+ };
138
+ }
139
+ /**
140
+ * Convert bra-ket attribute syntax to XML
141
+ * Examples:
142
+ * name=value → name="value"
143
+ * x=5 y=10 → x="5" y="10"
144
+ * select=@* → select="@*"
145
+ */
146
+ convertAttributes(attrs) {
147
+ if (!attrs)
148
+ return '';
149
+ // Split by spaces but respect quoted strings
150
+ const parts = [];
151
+ let current = '';
152
+ let inQuotes = false;
153
+ let quoteChar = '';
154
+ for (let i = 0; i < attrs.length; i++) {
155
+ const char = attrs[i];
156
+ if ((char === '"' || char === "'") && (i === 0 || attrs[i - 1] !== '\\')) {
157
+ if (!inQuotes) {
158
+ inQuotes = true;
159
+ quoteChar = char;
160
+ current += char;
161
+ }
162
+ else if (char === quoteChar) {
163
+ inQuotes = false;
164
+ current += char;
165
+ }
166
+ else {
167
+ current += char;
168
+ }
169
+ }
170
+ else if (char === ' ' && !inQuotes) {
171
+ if (current.trim()) {
172
+ parts.push(current.trim());
173
+ current = '';
174
+ }
175
+ }
176
+ else {
177
+ current += char;
178
+ }
179
+ }
180
+ if (current.trim()) {
181
+ parts.push(current.trim());
182
+ }
183
+ // Convert each attribute
184
+ return parts.map(part => {
185
+ const match = part.match(/^([a-zA-Z_][a-zA-Z0-9_-]*)=(.+)$/);
186
+ if (!match)
187
+ return part;
188
+ const [, name, value] = match;
189
+ // Already quoted
190
+ if ((value.startsWith('"') && value.endsWith('"')) ||
191
+ (value.startsWith("'") && value.endsWith("'"))) {
192
+ return `${name}=${value}`;
193
+ }
194
+ // Quote it
195
+ return `${name}="${value}"`;
196
+ }).join(' ');
197
+ }
198
+ /**
199
+ * Convert inline kets within text content
200
+ * Example: "Hello |variable name=x> world" → "Hello <variable name="x"/> world"
201
+ */
202
+ convertInlineKets(text) {
203
+ return text.replace(/\|([a-zA-Z_][a-zA-Z0-9_-]*)\s*([^>]*?)>/g, (match, tag, attrs) => {
204
+ const attrStr = attrs.trim() ? ` ${this.convertAttributes(attrs.trim())}` : '';
205
+ return `<${tag}${attrStr}/>`;
206
+ });
207
+ }
208
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Core interpreter - Browser edition (no Node.js dependencies)
3
+ */
4
+ import type { DiracElement, DiracSession } from '../types/index.js';
5
+ export declare function integrate(session: DiracSession, element: DiracElement): Promise<void>;
6
+ export declare function integrateChildren(session: DiracSession, element: DiracElement): Promise<void>;
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Core interpreter - Browser edition (no Node.js dependencies)
3
+ */
4
+ import { substituteVariables, emit, getSubroutine } from './session.js';
5
+ import { executeDefvar } from '../tags/defvar.js';
6
+ import { executeVariable } from '../tags/variable.js';
7
+ import { executeAssign } from '../tags/assign.js';
8
+ import { executeOutput } from '../tags/output.js';
9
+ import { executeSubroutine } from '../tags/subroutine.js';
10
+ import { executeCall } from '../tags/call.js';
11
+ import { executeLoop } from '../tags/loop.js';
12
+ import { executeIf } from '../tags/if.js';
13
+ import { executeEval } from '../tags/eval.js';
14
+ import { executeExecute } from '../tags/execute.js';
15
+ import { executeParameters } from '../tags/parameters.js';
16
+ import { executeExpr } from '../tags/expr.js';
17
+ import { executeLLM } from '../tags/llm.js';
18
+ export async function integrate(session, element) {
19
+ // Check execution limits
20
+ if (session.limits.currentDepth >= session.limits.maxDepth) {
21
+ throw new Error('Maximum execution depth exceeded');
22
+ }
23
+ session.limits.currentDepth++;
24
+ try {
25
+ // Handle text nodes
26
+ if (element.text && !element.tag) {
27
+ const substituted = substituteVariables(session, element.text);
28
+ emit(session, substituted);
29
+ return;
30
+ }
31
+ // Check control flow
32
+ if (session.isReturn || session.isBreak) {
33
+ return;
34
+ }
35
+ // Dispatch to tag handlers
36
+ switch (element.tag.toLowerCase()) {
37
+ case 'defvar':
38
+ executeDefvar(session, element);
39
+ break;
40
+ case 'variable':
41
+ executeVariable(session, element);
42
+ break;
43
+ case 'assign':
44
+ executeAssign(session, element);
45
+ break;
46
+ case 'output':
47
+ await executeOutput(session, element);
48
+ break;
49
+ case 'subroutine':
50
+ executeSubroutine(session, element);
51
+ break;
52
+ case 'call':
53
+ await executeCall(session, element);
54
+ break;
55
+ case 'loop':
56
+ await executeLoop(session, element);
57
+ break;
58
+ case 'if':
59
+ await executeIf(session, element);
60
+ break;
61
+ case 'eval':
62
+ await executeEval(session, element);
63
+ break;
64
+ case 'execute':
65
+ await executeExecute(session, element);
66
+ break;
67
+ case 'parameters':
68
+ await executeParameters(session, element);
69
+ break;
70
+ case 'expr':
71
+ await executeExpr(session, element);
72
+ break;
73
+ // Browser-incompatible tags
74
+ case 'import':
75
+ console.warn('[dirac-browser] <import> tag not supported in browser (requires fs)');
76
+ break;
77
+ case 'system':
78
+ console.warn('[dirac-browser] <system> tag not supported in browser (requires child_process)');
79
+ break;
80
+ case 'llm':
81
+ await executeLLM(session, element);
82
+ break;
83
+ default:
84
+ // Unknown tag - check if it's a subroutine name
85
+ const subroutine = getSubroutine(session, element.tag);
86
+ if (subroutine) {
87
+ // Treat unknown tag as subroutine call
88
+ await executeCall(session, element);
89
+ }
90
+ else {
91
+ // Really unknown - just process children
92
+ for (const child of element.children) {
93
+ await integrate(session, child);
94
+ if (session.isReturn || session.isBreak)
95
+ break;
96
+ }
97
+ }
98
+ }
99
+ }
100
+ finally {
101
+ session.limits.currentDepth--;
102
+ }
103
+ }
104
+ export async function integrateChildren(session, element) {
105
+ for (const child of element.children) {
106
+ await integrate(session, child);
107
+ if (session.isReturn || session.isBreak)
108
+ break;
109
+ }
110
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * XML Parser for Dirac (.di files)
3
+ */
4
+ import type { DiracElement } from '../types/index.js';
5
+ export declare class DiracParser {
6
+ private parser;
7
+ constructor();
8
+ parse(source: string): DiracElement;
9
+ private convertOrderedToElement;
10
+ private convertToElement;
11
+ }