dirac-lang 0.1.24 → 0.1.26

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 (221) hide show
  1. package/dist/cli.js +13 -1
  2. package/lib/index.di +9 -0
  3. package/{examples/lib → lib}/math.di +3 -3
  4. package/package.json +13 -1
  5. package/.env.example +0 -8
  6. package/COMMUNITY.md +0 -465
  7. package/CONDITIONAL-TAGS.md +0 -172
  8. package/EXCEPTION-HANDLING.md +0 -156
  9. package/LIBRARIES.md +0 -172
  10. package/LLM-VALIDATION.md +0 -128
  11. package/NAMESPACES.md +0 -366
  12. package/PROMOTION.md +0 -257
  13. package/QUICKSTART-LIBRARY.md +0 -93
  14. package/TEST-COVERAGE.md +0 -113
  15. package/TESTING.md +0 -162
  16. package/config.test.yml +0 -5
  17. package/dirac-http/examples/demo.di +0 -9
  18. package/dirac-http/lib/index.di +0 -12
  19. package/examples/add-demo.di +0 -74
  20. package/examples/add.bk +0 -11
  21. package/examples/advanced-math-demo.di +0 -53
  22. package/examples/calculator.di +0 -32
  23. package/examples/compact-test.di +0 -6
  24. package/examples/comprehensive.bk +0 -29
  25. package/examples/defvar-variable-demo.di +0 -18
  26. package/examples/direct-call.di +0 -17
  27. package/examples/disk-analysis.di +0 -16
  28. package/examples/exception-demo.di +0 -82
  29. package/examples/executable-hello.di +0 -7
  30. package/examples/execute-demo.di +0 -38
  31. package/examples/file-manager.di +0 -77
  32. package/examples/file-stats.di +0 -18
  33. package/examples/hello.bk +0 -1
  34. package/examples/hello.di +0 -5
  35. package/examples/if-comparison.di +0 -91
  36. package/examples/if-cstyle-test.di +0 -149
  37. package/examples/if-vs-testif.di +0 -56
  38. package/examples/import-demo.di +0 -31
  39. package/examples/inline-test.bk +0 -7
  40. package/examples/llm-agent.di +0 -32
  41. package/examples/llm-basic.di +0 -12
  42. package/examples/llm-command-more.di +0 -6
  43. package/examples/llm-command-no-exec.di +0 -13
  44. package/examples/llm-command.di +0 -6
  45. package/examples/llm-complex.di +0 -141
  46. package/examples/llm-feedback-debug.di +0 -30
  47. package/examples/llm-feedback-demo.di +0 -19
  48. package/examples/llm-feedback-math.di +0 -22
  49. package/examples/llm-feedback-simple.di +0 -16
  50. package/examples/llm-feedback-sub.di +0 -22
  51. package/examples/llm-no-feedback.di +0 -10
  52. package/examples/llm-recursive.di +0 -31
  53. package/examples/llm-reflection-test.di +0 -19
  54. package/examples/llm-simple-test.di +0 -12
  55. package/examples/llm-subs.di +0 -132
  56. package/examples/llm-use-subs.di +0 -6
  57. package/examples/llm-validate-test.di +0 -18
  58. package/examples/loop.di +0 -12
  59. package/examples/math-test.di +0 -22
  60. package/examples/minimal-test.di +0 -13
  61. package/examples/mongodb-context-test.di +0 -27
  62. package/examples/mongodb-count-events.di +0 -8
  63. package/examples/mongodb-import-demo.di +0 -25
  64. package/examples/mongodb-simple-test.di +0 -18
  65. package/examples/nl-agent.di +0 -47
  66. package/examples/parameters-demo.di +0 -68
  67. package/examples/params-meta-test.di +0 -17
  68. package/examples/params-test.di +0 -10
  69. package/examples/recipe-chain.di +0 -38
  70. package/examples/recursive-llm.di +0 -44
  71. package/examples/sample-library/README.md +0 -152
  72. package/examples/sample-library/examples/demo.di +0 -34
  73. package/examples/sample-library/lib/index.di +0 -65
  74. package/examples/sample-library/package.json +0 -31
  75. package/examples/scope-test-nested.di +0 -60
  76. package/examples/scope-test.di +0 -55
  77. package/examples/seamless.di +0 -45
  78. package/examples/shell-test.bk +0 -10
  79. package/examples/simple-import.di +0 -13
  80. package/examples/simple-recursive.di +0 -26
  81. package/examples/story-builder.di +0 -45
  82. package/examples/subroutine.di +0 -23
  83. package/examples/system-llm.di +0 -21
  84. package/examples/system-simple.di +0 -3
  85. package/examples/system-test.di +0 -8
  86. package/examples/tag-check-test.di +0 -139
  87. package/examples/task-assistant.di +0 -27
  88. package/examples/test-if-demo.di +0 -110
  89. package/examples/test-parameters.di +0 -50
  90. package/examples/try-catch-test.di +0 -118
  91. package/examples/two-styles.di +0 -28
  92. package/examples/var-debug.di +0 -6
  93. package/examples/var-inline.di +0 -4
  94. package/examples/var-test2.di +0 -6
  95. package/examples/variable-replace.di +0 -25
  96. package/examples/variable-simple.di +0 -16
  97. package/examples/variable-test.di +0 -22
  98. package/examples/whitespace-test.di +0 -24
  99. package/filePath +0 -1
  100. package/greeting.txt +0 -1
  101. package/src/cli.ts +0 -140
  102. package/src/index.ts +0 -33
  103. package/src/llm/ollama.ts +0 -58
  104. package/src/runtime/braket-parser.ts +0 -234
  105. package/src/runtime/interpreter.ts +0 -203
  106. package/src/runtime/parser.ts +0 -155
  107. package/src/runtime/session.ts +0 -325
  108. package/src/tags/assign.ts +0 -37
  109. package/src/tags/attr.ts +0 -64
  110. package/src/tags/available-subroutines.ts +0 -70
  111. package/src/tags/call.ts +0 -259
  112. package/src/tags/catch.ts +0 -24
  113. package/src/tags/defvar.ts +0 -115
  114. package/src/tags/environment.ts +0 -21
  115. package/src/tags/eval.ts +0 -71
  116. package/src/tags/exception.ts +0 -20
  117. package/src/tags/execute.ts +0 -52
  118. package/src/tags/expr.ts +0 -128
  119. package/src/tags/foreach.ts +0 -170
  120. package/src/tags/if.ts +0 -191
  121. package/src/tags/import.ts +0 -135
  122. package/src/tags/index.ts +0 -41
  123. package/src/tags/input.ts +0 -182
  124. package/src/tags/llm.ts +0 -415
  125. package/src/tags/loop.ts +0 -43
  126. package/src/tags/mongodb.ts +0 -70
  127. package/src/tags/output.ts +0 -53
  128. package/src/tags/parameters.ts +0 -81
  129. package/src/tags/require_module.ts +0 -19
  130. package/src/tags/subroutine.ts +0 -75
  131. package/src/tags/system.ts +0 -93
  132. package/src/tags/tag-check.ts +0 -176
  133. package/src/tags/test-if.ts +0 -112
  134. package/src/tags/throw.ts +0 -26
  135. package/src/tags/try.ts +0 -19
  136. package/src/tags/variable.ts +0 -25
  137. package/src/test-runner.ts +0 -300
  138. package/src/types/index.ts +0 -128
  139. package/src/utils/llm-adapter.ts +0 -113
  140. package/src/utils/tag-validator.ts +0 -231
  141. package/test-available-extends.di +0 -28
  142. package/test-available-simple.di +0 -12
  143. package/test-available-subroutines.di +0 -16
  144. package/test-call.di +0 -9
  145. package/test-extend-basic.di +0 -17
  146. package/test-extend-chain.di +0 -26
  147. package/test-extend-debug.di +0 -17
  148. package/test-extend-debug2.di +0 -15
  149. package/test-extend-person.di +0 -17
  150. package/test-extend-simple.di +0 -11
  151. package/test-extend-zhi.di +0 -23
  152. package/test-extend.di +0 -19
  153. package/test-extend2.di +0 -26
  154. package/test-extend3-fixed.di +0 -23
  155. package/test-extend3-trouble.di +0 -23
  156. package/test-extend3.di +0 -21
  157. package/test-factorial.di +0 -19
  158. package/test-input-debug.di +0 -19
  159. package/test-nested-debug.di +0 -7
  160. package/test-nested-debug2.di +0 -8
  161. package/test-no-extend.di +0 -16
  162. package/test-simple-call.di +0 -7
  163. package/test-simple.di +0 -6
  164. package/tests/README.md +0 -69
  165. package/tests/assign-basic.test.di +0 -7
  166. package/tests/assign-from-eval.test.di +0 -7
  167. package/tests/available-subroutines-foreach.test.di +0 -32
  168. package/tests/basic-output.test.di +0 -5
  169. package/tests/call-basic.test.di +0 -11
  170. package/tests/call-with-output.test.di +0 -10
  171. package/tests/comments-before-content.test.di +0 -6
  172. package/tests/defvar-multiple.test.di +0 -8
  173. package/tests/environment-basic.test.di +0 -22
  174. package/tests/environment-nonexistent.test.di +0 -5
  175. package/tests/environment-with-defvar.test.di +0 -15
  176. package/tests/eval-basic.test.di +0 -6
  177. package/tests/eval-with-variables.test.di +0 -8
  178. package/tests/exception-basic.test.di +0 -10
  179. package/tests/expr-basic.test.di +0 -11
  180. package/tests/extend-basic.test.di +0 -19
  181. package/tests/extend-inheritance-chain.test.di +0 -26
  182. package/tests/extend-multiple-nested.test.di +0 -24
  183. package/tests/extend-self.test.di +0 -19
  184. package/tests/extend-with-parameters.test.di +0 -14
  185. package/tests/generate-dirac.test.di +0 -22
  186. package/tests/if-conditional.test.di +0 -17
  187. package/tests/if-else.test.di +0 -11
  188. package/tests/if-with-variables.test.di +0 -8
  189. package/tests/import-basic.test.di +0 -6
  190. package/tests/input-file-all.test.di +0 -5
  191. package/tests/input-file-line.test.di +0 -15
  192. package/tests/input-file-loop.test.di +0 -12
  193. package/tests/input-stdin-all.test.di +0 -8
  194. package/tests/input-stdin-all.txt +0 -1
  195. package/tests/llm-validate.test.di +0 -17
  196. package/tests/loop-basic.test.di +0 -9
  197. package/tests/loop-nested.test.di +0 -10
  198. package/tests/loop-with-eval.test.di +0 -8
  199. package/tests/no-root-element.test.di +0 -6
  200. package/tests/output-file.test.di +0 -19
  201. package/tests/output-multiple.test.di +0 -9
  202. package/tests/parameters-basic.test.di +0 -6
  203. package/tests/require-module-basic.test.di +0 -7
  204. package/tests/subroutine-basic.test.di +0 -9
  205. package/tests/subroutine-multiple-params.test.di +0 -10
  206. package/tests/subroutine-nested-calls.test.di +0 -32
  207. package/tests/subroutine-sequential-calls.test.di +0 -36
  208. package/tests/system-background.test.di +0 -39
  209. package/tests/system-basic.test.di +0 -5
  210. package/tests/tag-check.test.di +0 -27
  211. package/tests/test-if-basic.test.di +0 -8
  212. package/tests/test-input.txt +0 -3
  213. package/tests/try-catch-basic.test.di +0 -10
  214. package/tests/try-catch-eval-error.test.di +0 -10
  215. package/tests/variable-basic.test.di +0 -6
  216. package/tests/variable-interpolation.test.di +0 -7
  217. package/tools/create-library.sh +0 -175
  218. package/tsconfig.json +0 -19
  219. /package/{examples/lib → lib}/advanced-math.di +0 -0
  220. /package/{examples/lib → lib}/fileops.di +0 -0
  221. /package/{examples/lib → lib}/mongodb.di +0 -0
@@ -1,203 +0,0 @@
1
- /**
2
- * Core interpreter - maps to mask_integrate in MASK
3
- */
4
-
5
- import type { DiracElement, DiracSession } from '../types/index.js';
6
- import { substituteVariables, emit, getSubroutine } from './session.js';
7
- import { executeDefvar } from '../tags/defvar.js';
8
- import { executeVariable } from '../tags/variable.js';
9
- import { executeAssign } from '../tags/assign.js';
10
- import { executeOutput } from '../tags/output.js';
11
- import { executeSubroutine } from '../tags/subroutine.js';
12
- import { executeCall } from '../tags/call.js';
13
- import { executeLoop } from '../tags/loop.js';
14
- import { executeIf } from '../tags/if.js';
15
- import { executeLLM } from '../tags/llm.js';
16
- import { executeEval } from '../tags/eval.js';
17
- import { executeExecute } from '../tags/execute.js';
18
- import { executeImport } from '../tags/import.js';
19
- import { executeParameters } from '../tags/parameters.js';
20
- import { executeExpr } from '../tags/expr.js';
21
- import { executeSystem } from '../tags/system.js';
22
- import { executeRequireModule } from '../tags/require_module.js';
23
- import { executeTagCheck } from '../tags/tag-check.js';
24
- import { executeThrow } from '../tags/throw.js';
25
- import { executeTry } from '../tags/try.js';
26
- import { executeCatch } from '../tags/catch.js';
27
- import { executeException } from '../tags/exception.js';
28
- import { executeTestIf } from '../tags/test-if.js';
29
- import { executeAvailableSubroutines } from '../tags/available-subroutines.js';
30
- import { executeForeach } from '../tags/foreach.js';
31
- import { executeAttr } from '../tags/attr.js';
32
- import { executeEnvironment } from '../tags/environment.js';
33
- import { executeInput } from '../tags/input.js';
34
-
35
- export async function integrate(session: DiracSession, element: DiracElement): Promise<void> {
36
- // Check execution limits
37
- if (session.limits.currentDepth >= session.limits.maxDepth) {
38
- throw new Error('Maximum execution depth exceeded');
39
- }
40
-
41
- session.limits.currentDepth++;
42
-
43
- try {
44
- // Handle text nodes
45
- if (element.text && !element.tag) {
46
- const substituted = substituteVariables(session, element.text);
47
- emit(session, substituted);
48
- return;
49
- }
50
-
51
- // Check control flow
52
- if (session.isReturn || session.isBreak) {
53
- return;
54
- }
55
-
56
- // Dispatch to tag handlers
57
- switch (element.tag.toLowerCase()) {
58
- case 'defvar':
59
- await executeDefvar(session, element);
60
- break;
61
-
62
- case 'variable':
63
- await executeVariable(session, element);
64
- break;
65
-
66
- case 'assign':
67
- await executeAssign(session, element);
68
- break;
69
-
70
- case 'output':
71
- await executeOutput(session, element);
72
- break;
73
-
74
- case 'subroutine':
75
- await executeSubroutine(session, element);
76
- break;
77
-
78
- case 'call':
79
- await executeCall(session, element);
80
- break;
81
-
82
- case 'loop':
83
- await executeLoop(session, element);
84
- break;
85
-
86
- case 'if':
87
- await executeIf(session, element);
88
- break;
89
-
90
- case 'llm':
91
- await executeLLM(session, element);
92
- break;
93
-
94
- case 'eval':
95
- await executeEval(session, element);
96
- break;
97
-
98
- case 'execute':
99
- await executeExecute(session, element);
100
- break;
101
-
102
- case 'import':
103
- await executeImport(session, element);
104
- break;
105
-
106
- case 'parameters': {
107
- const result = await executeParameters(session, element);
108
- if (typeof result === 'string') {
109
- emit(session, result);
110
- }
111
- break;
112
- }
113
-
114
- case 'expr':
115
- await executeExpr(session, element);
116
- break;
117
-
118
- case 'system':
119
- await executeSystem(session, element);
120
- break;
121
-
122
- case 'tag-check':
123
- await executeTagCheck(session, element);
124
- break;
125
-
126
- case 'throw':
127
- await executeThrow(session, element);
128
- break;
129
-
130
- case 'try':
131
- await executeTry(session, element);
132
- break;
133
-
134
- case 'catch':
135
- await executeCatch(session, element);
136
- break;
137
-
138
- case 'exception':
139
- await executeException(session, element);
140
- break;
141
-
142
- case 'test-if':
143
- await executeTestIf(session, element);
144
- break;
145
-
146
- case 'available-subroutines':
147
- await executeAvailableSubroutines(session, element);
148
- break;
149
-
150
- case 'foreach':
151
- await executeForeach(session, element);
152
- break;
153
-
154
- case 'attr':
155
- await executeAttr(session, element);
156
- break;
157
-
158
- case 'environment':
159
- await executeEnvironment(session, element);
160
- break;
161
-
162
- case 'input':
163
- await executeInput(session, element);
164
- break;
165
-
166
- case 'require_module':
167
- await executeRequireModule(session, element);
168
- break;
169
-
170
- case 'dirac':
171
- case 'DIRAC-ROOT':
172
- // Container tags - just execute children
173
- for (const child of element.children) {
174
- await integrate(session, child);
175
- if (session.isReturn || session.isBreak) break;
176
- }
177
- break;
178
-
179
- default:
180
- // Unknown tag - check if it's a subroutine name
181
- const subroutine = getSubroutine(session, element.tag);
182
- if (subroutine) {
183
- // Treat unknown tag as subroutine call
184
- await executeCall(session, element);
185
- } else {
186
- // Really unknown - just process children
187
- for (const child of element.children) {
188
- await integrate(session, child);
189
- if (session.isReturn || session.isBreak) break;
190
- }
191
- }
192
- }
193
- } finally {
194
- session.limits.currentDepth--;
195
- }
196
- }
197
-
198
- export async function integrateChildren(session: DiracSession, element: DiracElement): Promise<void> {
199
- for (const child of element.children) {
200
- await integrate(session, child);
201
- if (session.isReturn || session.isBreak) break;
202
- }
203
- }
@@ -1,155 +0,0 @@
1
- /**
2
- * XML Parser for Dirac (.di files)
3
- */
4
-
5
- import { XMLParser } from 'fast-xml-parser';
6
- import type { DiracElement } from '../types/index.js';
7
-
8
- export class DiracParser {
9
- private parser: XMLParser;
10
-
11
- constructor() {
12
- this.parser = new XMLParser({
13
- ignoreAttributes: false,
14
- attributeNamePrefix: '@_',
15
- trimValues: false, // Preserve whitespace in mixed content
16
- parseAttributeValue: false,
17
- parseTagValue: false,
18
- textNodeName: '#text',
19
- cdataPropName: '#cdata',
20
- preserveOrder: true, // Preserve element order!
21
- commentPropName: '#comment',
22
- });
23
- }
24
-
25
- parse(source: string): DiracElement {
26
- // Strip shebang line if present
27
- if (source.startsWith('#!')) {
28
- source = source.replace(/^#!.*\n/, '');
29
- }
30
-
31
- // Always wrap in DIRAC-ROOT to ensure valid XML with single root
32
- // This allows files with comments, multiple elements, or no root
33
- source = `<DIRAC-ROOT>\n${source}\n</DIRAC-ROOT>`;
34
-
35
- const result = this.parser.parse(source);
36
- // With preserveOrder, result is an array
37
- if (!Array.isArray(result) || result.length === 0) {
38
- throw new Error('Empty or invalid XML');
39
- }
40
-
41
- // Find the first non-comment element
42
- for (const item of result) {
43
- if (!item['#comment']) {
44
- return this.convertOrderedToElement(item);
45
- }
46
- }
47
-
48
- throw new Error('No root element found');
49
- }
50
-
51
- private convertOrderedToElement(obj: any): DiracElement {
52
- // obj is like { "tagname": [...children], ":@": {...attributes} }
53
- const tagName = Object.keys(obj).find(k => k !== ':@' && k !== '#comment');
54
-
55
- if (!tagName) {
56
- throw new Error('Invalid element structure');
57
- }
58
-
59
- const element: DiracElement = {
60
- tag: tagName,
61
- attributes: {},
62
- children: [],
63
- };
64
-
65
- // Extract attributes
66
- if (obj[':@']) {
67
- for (const [key, value] of Object.entries(obj[':@'])) {
68
- if (key.startsWith('@_')) {
69
- element.attributes[key.slice(2)] = value as string;
70
- }
71
- }
72
- }
73
-
74
- // Extract children
75
- const children = obj[tagName];
76
- if (Array.isArray(children)) {
77
- for (const child of children) {
78
- if (child['#text']) {
79
- // Text node - add as child AND to element.text for backward compat
80
- element.children.push({
81
- tag: '',
82
- text: child['#text'],
83
- attributes: {},
84
- children: []
85
- });
86
- // Also set element.text if not set (for simple text-only elements)
87
- if (!element.text) {
88
- element.text = child['#text'];
89
- } else {
90
- element.text += child['#text'];
91
- }
92
- } else if (child['#comment']) {
93
- // Skip comments
94
- continue;
95
- } else {
96
- // Child element
97
- element.children.push(this.convertOrderedToElement(child));
98
- }
99
- }
100
- }
101
-
102
- return element;
103
- }
104
-
105
- // Old method - no longer used
106
- private convertToElement(obj: any, tagName?: string): DiracElement {
107
- if (!tagName) {
108
- // Root level - find the actual tag
109
- const keys = Object.keys(obj);
110
- if (keys.length === 0) {
111
- throw new Error('Empty XML');
112
- }
113
- tagName = keys[0];
114
- obj = obj[tagName];
115
- }
116
-
117
- const element: DiracElement = {
118
- tag: tagName,
119
- attributes: {},
120
- children: [],
121
- };
122
-
123
- if (typeof obj === 'string') {
124
- element.text = obj;
125
- return element;
126
- }
127
-
128
- if (!obj) {
129
- return element;
130
- }
131
-
132
- // Extract attributes and children
133
- for (const key of Object.keys(obj)) {
134
- const value = obj[key];
135
-
136
- if (key === '#text') {
137
- element.text = value;
138
- } else if (key.startsWith('@_')) {
139
- // Attribute
140
- element.attributes[key.slice(2)] = value;
141
- } else {
142
- // Child element
143
- if (Array.isArray(value)) {
144
- for (const item of value) {
145
- element.children.push(this.convertToElement(item, key));
146
- }
147
- } else {
148
- element.children.push(this.convertToElement(value, key));
149
- }
150
- }
151
- }
152
-
153
- return element;
154
- }
155
- }
@@ -1,325 +0,0 @@
1
- // Substitute both $var and ${var} in a string using session variables
2
- export function substituteAttribute(session: DiracSession, value: any): string {
3
- if (typeof value !== 'string') return value;
4
- return value
5
- .replace(/\$\{(\w+)\}/g, (match, varName) => {
6
- const v = getVariable(session, varName);
7
- return v !== undefined ? String(v) : match;
8
- })
9
- .replace(/\$(\w+)/g, (match, varName) => {
10
- const v = getVariable(session, varName);
11
- return v !== undefined ? String(v) : match;
12
- });
13
- }
14
- /**
15
- * Session management - maps to MASK session functions
16
- */
17
-
18
- import Anthropic from '@anthropic-ai/sdk';
19
- import OpenAI from 'openai';
20
- import { OllamaProvider } from '../llm/ollama.js';
21
- import type { DiracSession, DiracConfig, Variable, Subroutine, DiracElement } from '../types/index.js';
22
-
23
- export function createSession(config: DiracConfig = {}): DiracSession {
24
- const anthropicKey = process.env.ANTHROPIC_API_KEY;
25
- const openaiKey = config.apiKey || process.env.OPENAI_API_KEY;
26
- const llmProvider = config.llmProvider || process.env.LLM_PROVIDER;
27
- const ollamaModel = config.llmModel || process.env.LLM_MODEL || 'llama2';
28
-
29
- let llmClient: any;
30
- switch (llmProvider) {
31
- case 'ollama':
32
- llmClient = new OllamaProvider({ model: ollamaModel });
33
- break;
34
- case 'anthropic':
35
- if (!anthropicKey) throw new Error('ANTHROPIC_API_KEY required for Anthropic provider');
36
- llmClient = new Anthropic({ apiKey: anthropicKey });
37
- break;
38
- case 'openai':
39
- if (!openaiKey) throw new Error('OPENAI_API_KEY required for OpenAI provider');
40
- llmClient = new OpenAI({ apiKey: openaiKey });
41
- break;
42
- default:
43
- throw new Error('No valid LLM provider configured. Set llmProvider in config or LLM_PROVIDER env.');
44
- }
45
- return {
46
- variables: [],
47
- subroutines: [],
48
- varBoundary: 0,
49
- subBoundary: 0,
50
- parameterStack: [],
51
- exceptions: [],
52
- currentException: {
53
- size: 0,
54
- exceptions: [],
55
- },
56
- output: [],
57
- llmClient,
58
- limits: {
59
- maxLLMCalls: config.maxLLMCalls || 100,
60
- currentLLMCalls: 0,
61
- maxDepth: config.maxDepth || 50,
62
- currentDepth: 0,
63
- },
64
- isReturn: false,
65
- isBreak: false,
66
- skipSubroutineRegistration: false,
67
- debug: config.debug || false,
68
- };
69
- }
70
-
71
- // Variable management (maps to var_info functions in MASK)
72
-
73
- export function setVariable(session: DiracSession, name: string, value: any, visible: boolean = false): void {
74
- session.variables.push({
75
- name,
76
- value,
77
- visible,
78
- boundary: session.varBoundary,
79
- passby: 'value',
80
- });
81
- }
82
-
83
- export function getVariable(session: DiracSession, name: string): any {
84
- // Search from end (most recent) to beginning
85
- for (let i = session.variables.length - 1; i >= 0; i--) {
86
- if (session.variables[i].name === name) {
87
- return session.variables[i].value;
88
- }
89
- }
90
- return undefined;
91
- }
92
-
93
- export function hasVariable(session: DiracSession, name: string): boolean {
94
- return session.variables.some(v => v.name === name);
95
- }
96
-
97
- /**
98
- * Set boundary marker for local variables
99
- * Maps to var_info_set_boundary in MASK
100
- */
101
- export function setBoundary(session: DiracSession): number {
102
- const oldBoundary = session.varBoundary;
103
- session.varBoundary = session.variables.length;
104
- return oldBoundary;
105
- }
106
-
107
- /**
108
- * Pop variables back to boundary (cleanup local scope)
109
- * Maps to var_info_pop_to_boundary in MASK
110
- */
111
- export function popToBoundary(session: DiracSession): void {
112
- session.variables = session.variables.slice(0, session.varBoundary);
113
- }
114
-
115
- /**
116
- * Clean private variables but keep visible ones
117
- * Maps to var_info_clean_to_boundary in MASK
118
- */
119
- export function cleanToBoundary(session: DiracSession): void {
120
- const kept: Variable[] = [];
121
-
122
- for (let i = 0; i < session.varBoundary; i++) {
123
- kept.push(session.variables[i]);
124
- }
125
-
126
- for (let i = session.varBoundary; i < session.variables.length; i++) {
127
- if (session.variables[i].visible) {
128
- kept.push(session.variables[i]);
129
- }
130
- }
131
-
132
- session.variables = kept;
133
- session.varBoundary = kept.length;
134
- }
135
-
136
- // Subroutine management (maps to subroutine functions in MASK)
137
-
138
- export function registerSubroutine(
139
- session: DiracSession,
140
- name: string,
141
- element: DiracElement,
142
- description?: string,
143
- parameters?: any[],
144
- meta?: Record<string, string>
145
- ): void {
146
- session.subroutines.push({
147
- name,
148
- element,
149
- boundary: session.subBoundary,
150
- description,
151
- parameters,
152
- meta,
153
- });
154
- }
155
-
156
- export function getSubroutine(session: DiracSession, name: string): DiracElement | undefined {
157
- // Search from end (most recent) to beginning
158
- for (let i = session.subroutines.length - 1; i >= 0; i--) {
159
- if (session.subroutines[i].name === name) {
160
- return session.subroutines[i].element;
161
- }
162
- }
163
- return undefined;
164
- }
165
-
166
- export function getParentSubroutine(
167
- session: DiracSession,
168
- name: string,
169
- currentElement?: DiracElement
170
- ): DiracElement | undefined {
171
- // Search from end, finding parent of currentElement
172
- // If currentElement provided, skip until we find it, then return next match
173
- // If not provided, just return most recent
174
-
175
- let foundCurrent = currentElement === undefined;
176
-
177
- for (let i = session.subroutines.length - 1; i >= 0; i--) {
178
- if (session.subroutines[i].name === name) {
179
- if (!foundCurrent) {
180
- // Check if this is the current element
181
- if (session.subroutines[i].element === currentElement) {
182
- foundCurrent = true;
183
- continue; // Skip current, look for parent
184
- }
185
- continue; // Not current yet, keep searching
186
- }
187
- // Found current, this is the parent
188
- return session.subroutines[i].element;
189
- }
190
- }
191
- return undefined;
192
- }
193
-
194
- export function setSubroutineBoundary(session: DiracSession): number {
195
- const oldBoundary = session.subBoundary;
196
- session.subBoundary = session.subroutines.length;
197
- return oldBoundary;
198
- }
199
-
200
- export function popSubroutinesToBoundary(session: DiracSession): void {
201
- session.subroutines = session.subroutines.slice(0, session.subBoundary);
202
- }
203
-
204
- export function cleanSubroutinesToBoundary(session: DiracSession): void {
205
- // For now, same as pop (visibility not implemented for subroutines yet)
206
- popSubroutinesToBoundary(session);
207
- }
208
-
209
- // Variable substitution (maps to var_replace functions in MASK)
210
-
211
- export function substituteVariables(session: DiracSession, text: string): string {
212
- // Decode HTML entities only; do NOT substitute variables globally
213
- return text
214
- .replace(/&#10;/g, '\n')
215
- .replace(/&#13;/g, '\r')
216
- .replace(/&#9;/g, '\t')
217
- .replace(/&lt;/g, '<')
218
- .replace(/&gt;/g, '>')
219
- .replace(/&amp;/g, '&')
220
- .replace(/&quot;/g, '"')
221
- .replace(/&apos;/g, "'");
222
- }
223
-
224
- // Output management
225
-
226
- export function emit(session: DiracSession, content: string): void {
227
- session.output.push(content);
228
- }
229
-
230
- export function getOutput(session: DiracSession): string {
231
- return session.output.join('');
232
- }
233
-
234
- // Parameter stack (for subroutine calls)
235
-
236
- export function pushParameters(session: DiracSession, params: DiracElement[]): void {
237
- session.parameterStack.push(params);
238
- }
239
-
240
- export function popParameters(session: DiracSession): DiracElement[] | undefined {
241
- return session.parameterStack.pop();
242
- }
243
-
244
- export function getCurrentParameters(session: DiracSession): DiracElement[] | undefined {
245
- return session.parameterStack[session.parameterStack.length - 1];
246
- }
247
-
248
- // Reflection/Introspection API
249
-
250
- export function getAvailableSubroutines(session: DiracSession): Array<{
251
- name: string;
252
- description?: string;
253
- parameters?: Array<{
254
- name: string;
255
- type?: string;
256
- required?: boolean;
257
- description?: string;
258
- enum?: string[];
259
- }>;
260
- }> {
261
- return session.subroutines.map(sub => ({
262
- name: sub.name,
263
- description: sub.description,
264
- parameters: sub.parameters,
265
- meta: sub.meta,
266
- }));
267
- }
268
-
269
- // Exception handling (for try/catch/throw)
270
-
271
- export function throwException(session: DiracSession, name: string, dom: DiracElement): void {
272
- session.exceptions.push({
273
- name,
274
- dom,
275
- isBoundary: 0,
276
- });
277
- }
278
-
279
- export function setExceptionBoundary(session: DiracSession): void {
280
- const size = session.exceptions.length;
281
- if (size === 0) return;
282
- const top = session.exceptions[size - 1];
283
- top.isBoundary++;
284
- }
285
-
286
- export function unsetExceptionBoundary(session: DiracSession): void {
287
- const size = session.exceptions.length;
288
- if (size === 0) return;
289
- for (let i = size - 1; i >= 0; i--) {
290
- const exception = session.exceptions[i];
291
- if (exception.isBoundary > 0) {
292
- exception.isBoundary--;
293
- break;
294
- }
295
- }
296
- }
297
-
298
- export function lookupException(session: DiracSession, name: string): number {
299
- const size = session.exceptions.length;
300
- if (size === 0) return 0;
301
-
302
- let count = 0;
303
- for (let i = size - 1; i >= 0; i--) {
304
- const exception = session.exceptions[i];
305
- if (exception.isBoundary > 0) break; // Stop at boundary
306
-
307
- if (exception.name === name) {
308
- // Add to current exception list
309
- session.currentException.exceptions.push(exception.dom);
310
- session.currentException.size++;
311
- count++;
312
- }
313
- }
314
-
315
- return count;
316
- }
317
-
318
- export function flushCurrentException(session: DiracSession): void {
319
- session.currentException.size = 0;
320
- session.currentException.exceptions = [];
321
- }
322
-
323
- export function getCurrentExceptions(session: DiracSession): DiracElement[] {
324
- return session.currentException.exceptions;
325
- }