dirac-lang 0.1.24 → 0.1.25

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/package.json +13 -1
  4. package/.env.example +0 -8
  5. package/COMMUNITY.md +0 -465
  6. package/CONDITIONAL-TAGS.md +0 -172
  7. package/EXCEPTION-HANDLING.md +0 -156
  8. package/LIBRARIES.md +0 -172
  9. package/LLM-VALIDATION.md +0 -128
  10. package/NAMESPACES.md +0 -366
  11. package/PROMOTION.md +0 -257
  12. package/QUICKSTART-LIBRARY.md +0 -93
  13. package/TEST-COVERAGE.md +0 -113
  14. package/TESTING.md +0 -162
  15. package/config.test.yml +0 -5
  16. package/dirac-http/examples/demo.di +0 -9
  17. package/dirac-http/lib/index.di +0 -12
  18. package/examples/add-demo.di +0 -74
  19. package/examples/add.bk +0 -11
  20. package/examples/advanced-math-demo.di +0 -53
  21. package/examples/calculator.di +0 -32
  22. package/examples/compact-test.di +0 -6
  23. package/examples/comprehensive.bk +0 -29
  24. package/examples/defvar-variable-demo.di +0 -18
  25. package/examples/direct-call.di +0 -17
  26. package/examples/disk-analysis.di +0 -16
  27. package/examples/exception-demo.di +0 -82
  28. package/examples/executable-hello.di +0 -7
  29. package/examples/execute-demo.di +0 -38
  30. package/examples/file-manager.di +0 -77
  31. package/examples/file-stats.di +0 -18
  32. package/examples/hello.bk +0 -1
  33. package/examples/hello.di +0 -5
  34. package/examples/if-comparison.di +0 -91
  35. package/examples/if-cstyle-test.di +0 -149
  36. package/examples/if-vs-testif.di +0 -56
  37. package/examples/import-demo.di +0 -31
  38. package/examples/inline-test.bk +0 -7
  39. package/examples/llm-agent.di +0 -32
  40. package/examples/llm-basic.di +0 -12
  41. package/examples/llm-command-more.di +0 -6
  42. package/examples/llm-command-no-exec.di +0 -13
  43. package/examples/llm-command.di +0 -6
  44. package/examples/llm-complex.di +0 -141
  45. package/examples/llm-feedback-debug.di +0 -30
  46. package/examples/llm-feedback-demo.di +0 -19
  47. package/examples/llm-feedback-math.di +0 -22
  48. package/examples/llm-feedback-simple.di +0 -16
  49. package/examples/llm-feedback-sub.di +0 -22
  50. package/examples/llm-no-feedback.di +0 -10
  51. package/examples/llm-recursive.di +0 -31
  52. package/examples/llm-reflection-test.di +0 -19
  53. package/examples/llm-simple-test.di +0 -12
  54. package/examples/llm-subs.di +0 -132
  55. package/examples/llm-use-subs.di +0 -6
  56. package/examples/llm-validate-test.di +0 -18
  57. package/examples/loop.di +0 -12
  58. package/examples/math-test.di +0 -22
  59. package/examples/minimal-test.di +0 -13
  60. package/examples/mongodb-context-test.di +0 -27
  61. package/examples/mongodb-count-events.di +0 -8
  62. package/examples/mongodb-import-demo.di +0 -25
  63. package/examples/mongodb-simple-test.di +0 -18
  64. package/examples/nl-agent.di +0 -47
  65. package/examples/parameters-demo.di +0 -68
  66. package/examples/params-meta-test.di +0 -17
  67. package/examples/params-test.di +0 -10
  68. package/examples/recipe-chain.di +0 -38
  69. package/examples/recursive-llm.di +0 -44
  70. package/examples/sample-library/README.md +0 -152
  71. package/examples/sample-library/examples/demo.di +0 -34
  72. package/examples/sample-library/lib/index.di +0 -65
  73. package/examples/sample-library/package.json +0 -31
  74. package/examples/scope-test-nested.di +0 -60
  75. package/examples/scope-test.di +0 -55
  76. package/examples/seamless.di +0 -45
  77. package/examples/shell-test.bk +0 -10
  78. package/examples/simple-import.di +0 -13
  79. package/examples/simple-recursive.di +0 -26
  80. package/examples/story-builder.di +0 -45
  81. package/examples/subroutine.di +0 -23
  82. package/examples/system-llm.di +0 -21
  83. package/examples/system-simple.di +0 -3
  84. package/examples/system-test.di +0 -8
  85. package/examples/tag-check-test.di +0 -139
  86. package/examples/task-assistant.di +0 -27
  87. package/examples/test-if-demo.di +0 -110
  88. package/examples/test-parameters.di +0 -50
  89. package/examples/try-catch-test.di +0 -118
  90. package/examples/two-styles.di +0 -28
  91. package/examples/var-debug.di +0 -6
  92. package/examples/var-inline.di +0 -4
  93. package/examples/var-test2.di +0 -6
  94. package/examples/variable-replace.di +0 -25
  95. package/examples/variable-simple.di +0 -16
  96. package/examples/variable-test.di +0 -22
  97. package/examples/whitespace-test.di +0 -24
  98. package/filePath +0 -1
  99. package/greeting.txt +0 -1
  100. package/src/cli.ts +0 -140
  101. package/src/index.ts +0 -33
  102. package/src/llm/ollama.ts +0 -58
  103. package/src/runtime/braket-parser.ts +0 -234
  104. package/src/runtime/interpreter.ts +0 -203
  105. package/src/runtime/parser.ts +0 -155
  106. package/src/runtime/session.ts +0 -325
  107. package/src/tags/assign.ts +0 -37
  108. package/src/tags/attr.ts +0 -64
  109. package/src/tags/available-subroutines.ts +0 -70
  110. package/src/tags/call.ts +0 -259
  111. package/src/tags/catch.ts +0 -24
  112. package/src/tags/defvar.ts +0 -115
  113. package/src/tags/environment.ts +0 -21
  114. package/src/tags/eval.ts +0 -71
  115. package/src/tags/exception.ts +0 -20
  116. package/src/tags/execute.ts +0 -52
  117. package/src/tags/expr.ts +0 -128
  118. package/src/tags/foreach.ts +0 -170
  119. package/src/tags/if.ts +0 -191
  120. package/src/tags/import.ts +0 -135
  121. package/src/tags/index.ts +0 -41
  122. package/src/tags/input.ts +0 -182
  123. package/src/tags/llm.ts +0 -415
  124. package/src/tags/loop.ts +0 -43
  125. package/src/tags/mongodb.ts +0 -70
  126. package/src/tags/output.ts +0 -53
  127. package/src/tags/parameters.ts +0 -81
  128. package/src/tags/require_module.ts +0 -19
  129. package/src/tags/subroutine.ts +0 -75
  130. package/src/tags/system.ts +0 -93
  131. package/src/tags/tag-check.ts +0 -176
  132. package/src/tags/test-if.ts +0 -112
  133. package/src/tags/throw.ts +0 -26
  134. package/src/tags/try.ts +0 -19
  135. package/src/tags/variable.ts +0 -25
  136. package/src/test-runner.ts +0 -300
  137. package/src/types/index.ts +0 -128
  138. package/src/utils/llm-adapter.ts +0 -113
  139. package/src/utils/tag-validator.ts +0 -231
  140. package/test-available-extends.di +0 -28
  141. package/test-available-simple.di +0 -12
  142. package/test-available-subroutines.di +0 -16
  143. package/test-call.di +0 -9
  144. package/test-extend-basic.di +0 -17
  145. package/test-extend-chain.di +0 -26
  146. package/test-extend-debug.di +0 -17
  147. package/test-extend-debug2.di +0 -15
  148. package/test-extend-person.di +0 -17
  149. package/test-extend-simple.di +0 -11
  150. package/test-extend-zhi.di +0 -23
  151. package/test-extend.di +0 -19
  152. package/test-extend2.di +0 -26
  153. package/test-extend3-fixed.di +0 -23
  154. package/test-extend3-trouble.di +0 -23
  155. package/test-extend3.di +0 -21
  156. package/test-factorial.di +0 -19
  157. package/test-input-debug.di +0 -19
  158. package/test-nested-debug.di +0 -7
  159. package/test-nested-debug2.di +0 -8
  160. package/test-no-extend.di +0 -16
  161. package/test-simple-call.di +0 -7
  162. package/test-simple.di +0 -6
  163. package/tests/README.md +0 -69
  164. package/tests/assign-basic.test.di +0 -7
  165. package/tests/assign-from-eval.test.di +0 -7
  166. package/tests/available-subroutines-foreach.test.di +0 -32
  167. package/tests/basic-output.test.di +0 -5
  168. package/tests/call-basic.test.di +0 -11
  169. package/tests/call-with-output.test.di +0 -10
  170. package/tests/comments-before-content.test.di +0 -6
  171. package/tests/defvar-multiple.test.di +0 -8
  172. package/tests/environment-basic.test.di +0 -22
  173. package/tests/environment-nonexistent.test.di +0 -5
  174. package/tests/environment-with-defvar.test.di +0 -15
  175. package/tests/eval-basic.test.di +0 -6
  176. package/tests/eval-with-variables.test.di +0 -8
  177. package/tests/exception-basic.test.di +0 -10
  178. package/tests/expr-basic.test.di +0 -11
  179. package/tests/extend-basic.test.di +0 -19
  180. package/tests/extend-inheritance-chain.test.di +0 -26
  181. package/tests/extend-multiple-nested.test.di +0 -24
  182. package/tests/extend-self.test.di +0 -19
  183. package/tests/extend-with-parameters.test.di +0 -14
  184. package/tests/generate-dirac.test.di +0 -22
  185. package/tests/if-conditional.test.di +0 -17
  186. package/tests/if-else.test.di +0 -11
  187. package/tests/if-with-variables.test.di +0 -8
  188. package/tests/import-basic.test.di +0 -6
  189. package/tests/input-file-all.test.di +0 -5
  190. package/tests/input-file-line.test.di +0 -15
  191. package/tests/input-file-loop.test.di +0 -12
  192. package/tests/input-stdin-all.test.di +0 -8
  193. package/tests/input-stdin-all.txt +0 -1
  194. package/tests/llm-validate.test.di +0 -17
  195. package/tests/loop-basic.test.di +0 -9
  196. package/tests/loop-nested.test.di +0 -10
  197. package/tests/loop-with-eval.test.di +0 -8
  198. package/tests/no-root-element.test.di +0 -6
  199. package/tests/output-file.test.di +0 -19
  200. package/tests/output-multiple.test.di +0 -9
  201. package/tests/parameters-basic.test.di +0 -6
  202. package/tests/require-module-basic.test.di +0 -7
  203. package/tests/subroutine-basic.test.di +0 -9
  204. package/tests/subroutine-multiple-params.test.di +0 -10
  205. package/tests/subroutine-nested-calls.test.di +0 -32
  206. package/tests/subroutine-sequential-calls.test.di +0 -36
  207. package/tests/system-background.test.di +0 -39
  208. package/tests/system-basic.test.di +0 -5
  209. package/tests/tag-check.test.di +0 -27
  210. package/tests/test-if-basic.test.di +0 -8
  211. package/tests/test-input.txt +0 -3
  212. package/tests/try-catch-basic.test.di +0 -10
  213. package/tests/try-catch-eval-error.test.di +0 -10
  214. package/tests/variable-basic.test.di +0 -6
  215. package/tests/variable-interpolation.test.di +0 -7
  216. package/tools/create-library.sh +0 -175
  217. package/tsconfig.json +0 -19
  218. /package/{examples/lib → lib}/advanced-math.di +0 -0
  219. /package/{examples/lib → lib}/fileops.di +0 -0
  220. /package/{examples/lib → lib}/math.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
- }