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,37 +0,0 @@
1
- /**
2
- * <assign> tag - assign value to existing variable
3
- * Maps to mask_tag_assign in MASK
4
- */
5
-
6
- import type { DiracSession, DiracElement } from '../types/index.js';
7
- import { getVariable, setVariable, substituteVariables } from '../runtime/session.js';
8
-
9
- export function executeAssign(session: DiracSession, element: DiracElement): void {
10
- const name = element.attributes.name;
11
- const valueAttr = element.attributes.value;
12
-
13
- if (!name) {
14
- throw new Error('<assign> requires name attribute');
15
- }
16
-
17
- // Get value
18
- let value: any;
19
- if (valueAttr !== undefined) {
20
- value = substituteVariables(session, valueAttr);
21
- } else if (element.text) {
22
- value = substituteVariables(session, element.text);
23
- } else {
24
- value = '';
25
- }
26
-
27
- // Find existing variable and update it
28
- for (let i = session.variables.length - 1; i >= 0; i--) {
29
- if (session.variables[i].name === name) {
30
- session.variables[i].value = value;
31
- return;
32
- }
33
- }
34
-
35
- // Variable not found - create it (same as MASK behavior)
36
- setVariable(session, name, value, false);
37
- }
package/src/tags/attr.ts DELETED
@@ -1,64 +0,0 @@
1
- /**
2
- * <attr> tag - extract attribute value from XML item
3
- * Usage: <attr name="description" from="$sub" />
4
- * or: <attr name="param-format" from="$sub" />
5
- */
6
-
7
- import type { DiracSession, DiracElement } from '../types/index.js';
8
- import { getVariable, substituteVariables } from '../runtime/session.js';
9
-
10
- export async function executeAttr(session: DiracSession, element: DiracElement): Promise<void> {
11
- const nameAttr = element.attributes.name;
12
- const fromAttr = element.attributes.from;
13
-
14
- if (!nameAttr) {
15
- throw new Error('<attr> requires "name" attribute');
16
- }
17
-
18
- if (!fromAttr) {
19
- throw new Error('<attr> requires "from" attribute');
20
- }
21
-
22
- // Get the XML item from variable
23
- let item: any;
24
-
25
- if (fromAttr.startsWith('$')) {
26
- const varName = fromAttr.substring(1);
27
- item = getVariable(session, varName);
28
- } else {
29
- // Try substitution
30
- const substituted = substituteVariables(session, fromAttr);
31
- item = getVariable(session, substituted);
32
- }
33
-
34
- if (!item) {
35
- // No output if item not found
36
- return;
37
- }
38
-
39
- // Extract the attribute value
40
- let value = '';
41
-
42
- if (typeof item === 'object') {
43
- // If it's a structured XML item (from foreach)
44
- if (item.attributes && typeof item.attributes === 'object') {
45
- value = item.attributes[nameAttr] || '';
46
- }
47
- // If it's a direct object with the attribute
48
- else if (item[nameAttr] !== undefined) {
49
- value = String(item[nameAttr]);
50
- }
51
- } else if (typeof item === 'string') {
52
- // If it's a string, try to parse as XML and extract
53
- value = extractAttrFromXml(item, nameAttr);
54
- }
55
-
56
- session.output.push(value);
57
- }
58
-
59
- function extractAttrFromXml(xml: string, attrName: string): string {
60
- // Simple regex-based extraction for single-element XML
61
- const regex = new RegExp(`${attrName}="([^"]*)"`, 'i');
62
- const match = xml.match(regex);
63
- return match ? match[1] : '';
64
- }
@@ -1,70 +0,0 @@
1
- /**
2
- * <available-subroutines> tag - list available nested subroutines
3
- * Returns all subroutines within current call boundary with their metadata
4
- */
5
-
6
- import type { DiracSession, DiracElement } from '../types/index.js';
7
-
8
- export async function executeAvailableSubroutines(
9
- session: DiracSession,
10
- element: DiracElement
11
- ): Promise<void> {
12
- // Get all subroutines from current boundary to top of stack
13
- const availableSubroutines = new Map<string, DiracElement>();
14
-
15
- // Get the name of the currently executing subroutine from the boundary
16
- const currentSubroutineName = session.subBoundary < session.subroutines.length
17
- ? session.subroutines[session.subBoundary].name
18
- : null;
19
-
20
- // Read from top of stack (most recent) backwards to boundary
21
- // This ensures we get the latest definition (handles extends override)
22
- for (let i = session.subroutines.length - 1; i >= session.subBoundary; i--) {
23
- const sub = session.subroutines[i];
24
-
25
- // Skip the currently executing subroutine itself
26
- if (sub.name === currentSubroutineName) {
27
- continue;
28
- }
29
-
30
- // Only add if not already seen (first occurrence wins)
31
- if (!availableSubroutines.has(sub.name)) {
32
- availableSubroutines.set(sub.name, sub.element);
33
- }
34
- }
35
-
36
- // Generate structured output with container
37
- session.output.push('<subroutines>');
38
-
39
- for (const [name, subElement] of availableSubroutines) {
40
- const attrs: string[] = [`name="${escapeXml(name)}"`];
41
-
42
- // Add description if available
43
- const description = subElement.attributes.description;
44
- if (description) {
45
- attrs.push(`description="${escapeXml(description)}"`);
46
- }
47
-
48
- // Add all param-* attributes with their definitions
49
- for (const [attrName, attrValue] of Object.entries(subElement.attributes)) {
50
- if (attrName.startsWith('param-')) {
51
- attrs.push(`${attrName}="${escapeXml(attrValue)}"`);
52
- }
53
- }
54
-
55
- // Build the output tag
56
- const attrString = attrs.join(' ');
57
- session.output.push(` <subroutine ${attrString} />`);
58
- }
59
-
60
- session.output.push('</subroutines>');
61
- }
62
-
63
- function escapeXml(text: string): string {
64
- return text
65
- .replace(/&/g, '&amp;')
66
- .replace(/</g, '&lt;')
67
- .replace(/>/g, '&gt;')
68
- .replace(/"/g, '&quot;')
69
- .replace(/'/g, '&apos;');
70
- }
package/src/tags/call.ts DELETED
@@ -1,259 +0,0 @@
1
- // Utility: Substitute both $var and ${var} in a string using session variables
2
- import { substituteAttribute } from '../runtime/session.js';
3
-
4
- /**
5
- * <call> tag - invoke subroutine
6
- * Maps to mask_call_integrate in MASK
7
- */
8
-
9
- import type { DiracSession, DiracElement } from '../types/index.js';
10
- import {
11
- getSubroutine,
12
- getParentSubroutine,
13
- setBoundary,
14
- popToBoundary,
15
- cleanToBoundary,
16
- pushParameters,
17
- popParameters,
18
- substituteVariables,
19
- setVariable,
20
- getVariable,
21
- } from '../runtime/session.js';
22
- import { integrateChildren } from '../runtime/interpreter.js';
23
-
24
- export async function executeCall(session: DiracSession, element: DiracElement): Promise<void> {
25
- // Support both <call name="FOO" /> and direct <FOO /> syntax
26
- // For <call> tag, use name/subroutine attribute
27
- // For direct syntax, use element.tag
28
- let name: string;
29
-
30
- if (element.tag === 'call') {
31
- // Explicit <call> tag - use name or subroutine attribute
32
- name = element.attributes.name || element.attributes.subroutine || '';
33
- } else {
34
- // Direct tag syntax - use tag name itself, ignore name attribute
35
- name = element.tag;
36
- }
37
-
38
- if (!name) {
39
- throw new Error('<call> requires name or subroutine attribute');
40
- }
41
-
42
- const subroutine = getSubroutine(session, name);
43
- if (!subroutine) {
44
- throw new Error(`Subroutine '${name}' not found`);
45
- }
46
-
47
- // Handle extension (parent subroutine) using recursive descent
48
- const extendAttr = subroutine.attributes.extend;
49
- const extendsAttr = subroutine.attributes.extends;
50
-
51
- if (extendAttr !== undefined || extendsAttr !== undefined) {
52
- // This subroutine extends another - use recursive descent to build stack
53
- const baseSubroutine = await registerExtendChain(session, subroutine, name);
54
- // Execute the ultimate base subroutine with extend flag set
55
- await executeCallInternal(session, baseSubroutine, element, true);
56
- } else {
57
- // No extension - normal subroutine call
58
- await executeCallInternal(session, subroutine, element, false);
59
- }
60
- }
61
-
62
- /**
63
- * Recursive descent for extend mechanism:
64
- * 1. Recursively descend to ultimate parent (no extend)
65
- * 2. Register base's nested subroutines
66
- * 3. As recursion unwinds, register each level's subroutines (latest on top of stack)
67
- * 4. Return the ultimate base to be executed
68
- */
69
- async function registerExtendChain(
70
- session: DiracSession,
71
- subroutine: DiracElement,
72
- currentName: string
73
- ): Promise<DiracElement> {
74
- const { executeSubroutine } = await import('./subroutine.js');
75
-
76
- // Determine parent name
77
- const extendsAttr = subroutine.attributes.extends;
78
- let parentName: string;
79
-
80
- if (extendsAttr) {
81
- // extends="parentName" - use explicit parent name
82
- parentName = extendsAttr;
83
- } else {
84
- // extend (no value) - use same name, search for earlier definition
85
- parentName = currentName;
86
- }
87
-
88
- // Get parent, passing current subroutine if using same name
89
- const parent = getParentSubroutine(session, parentName, parentName === currentName ? subroutine : undefined);
90
-
91
- if (!parent) {
92
- // No parent found - shouldn't happen, but handle gracefully
93
- return subroutine;
94
- }
95
-
96
- // Check if parent also extends
97
- const parentExtendAttr = parent.attributes.extend;
98
- const parentExtendsAttr = parent.attributes.extends;
99
-
100
- let baseSubroutine: DiracElement;
101
-
102
- if (parentExtendAttr !== undefined || parentExtendsAttr !== undefined) {
103
- // Parent extends - recursively process parent first
104
- baseSubroutine = await registerExtendChain(session, parent, parentName);
105
- } else {
106
- // Parent doesn't extend - this is the ultimate base
107
- // Register base's nested subroutines (bottom of stack)
108
- for (const child of parent.children) {
109
- if (child.tag === 'subroutine') {
110
- executeSubroutine(session, child);
111
- }
112
- }
113
- baseSubroutine = parent;
114
- }
115
-
116
- // After parent chain is processed, register current level's nested subroutines
117
- // These go on top and override parent's definitions
118
- for (const child of subroutine.children) {
119
- if (child.tag === 'subroutine') {
120
- executeSubroutine(session, child);
121
- }
122
- }
123
-
124
- return baseSubroutine;
125
- }
126
-
127
- async function executeCallInternal(
128
- session: DiracSession,
129
- subroutine: DiracElement,
130
- callElement: DiracElement,
131
- isExtendExecution: boolean = false
132
- ): Promise<void> {
133
- // Set boundary for local scope
134
- const oldBoundary = setBoundary(session);
135
- const wasReturn = session.isReturn;
136
- session.isReturn = false;
137
-
138
- // Track current subroutine name for available-subroutines
139
- const oldSubroutineName = session.currentSubroutineName;
140
- session.currentSubroutineName = callElement.tag;
141
-
142
- // For extend execution, skip subroutine registration during body execution
143
- const oldSkipFlag = session.skipSubroutineRegistration;
144
- if (isExtendExecution) {
145
- session.skipSubroutineRegistration = true;
146
- }
147
-
148
- // Substitute variables in call element attributes before pushing to parameter stack
149
- const substitutedElement: DiracElement = {
150
- tag: callElement.tag,
151
- attributes: {},
152
- children: callElement.children
153
- };
154
-
155
- // Utility: Substitute both $var and ${var} in a string using session variables
156
- for (const [key, value] of Object.entries(callElement.attributes)) {
157
- substitutedElement.attributes[key] = substituteAttribute(session, value);
158
- }
159
-
160
- // Push caller element onto parameter stack for <parameters select="*|@*|@attr"/> access
161
- pushParameters(session, [substitutedElement]);
162
-
163
- try {
164
- // 1. Set variables from <param-*> attributes if not already set in this boundary
165
- for (const [attrName, attrValue] of Object.entries(subroutine.attributes)) {
166
- if (attrName.startsWith('param-')) {
167
- const paramName = attrName.substring(6);
168
- // Check if variable exists in current boundary
169
- const alreadySet = session.variables.slice(session.varBoundary).some(v => v.name === paramName);
170
- if (!alreadySet) {
171
- // Priority: call attribute > param-* default > empty string
172
- let value = '';
173
- if (callElement.attributes && callElement.attributes[paramName] !== undefined) {
174
- value = substituteAttribute(session, callElement.attributes[paramName]);
175
- } else {
176
- // Always treat last colon-separated part as default value (if >3 fields)
177
- const parts = attrValue.split(':');
178
- if (parts.length > 3) {
179
- value = parts[parts.length - 1];
180
- }
181
- }
182
- setVariable(session, paramName, value, false);
183
- }
184
- }
185
- }
186
-
187
- // 2. Bind parameters from <parameters> if present
188
- const paramElements = callElement.children.filter(c => c.tag === 'parameters');
189
- if (paramElements.length > 0) {
190
- await bindParameters(session, subroutine, paramElements[0]);
191
- }
192
-
193
- // 3. Execute subroutine body
194
- await integrateChildren(session, subroutine);
195
-
196
- } finally {
197
- // Restore skip flag
198
- session.skipSubroutineRegistration = oldSkipFlag;
199
-
200
- // Pop parameter stack
201
- popParameters(session);
202
-
203
- // Clean up scope (keep visible variables) BEFORE restoring boundary
204
- cleanToBoundary(session);
205
- session.varBoundary = oldBoundary;
206
- session.isReturn = wasReturn;
207
- }
208
- }
209
-
210
- async function bindParameters(
211
- session: DiracSession,
212
- subroutine: DiracElement,
213
- callParams: DiracElement
214
- ): Promise<void> {
215
- // Find <parameters> definition in subroutine
216
- const paramDef = subroutine.children.find(c => c.tag === 'parameters');
217
- if (!paramDef) {
218
- return; // No parameters defined
219
- }
220
-
221
- // Get variable definitions from parameter declaration
222
- const paramVars = paramDef.children.filter(c => c.tag === 'variable');
223
- const callVars = callParams.children.filter(c => c.tag === 'variable');
224
-
225
- // Bind each parameter
226
- for (let i = 0; i < paramVars.length; i++) {
227
- const paramVar = paramVars[i];
228
- const callVar = callVars[i];
229
-
230
- const paramName = paramVar.attributes.name;
231
- const passby = paramVar.attributes.passby || 'value';
232
-
233
- if (!paramName) continue;
234
-
235
- let value: any;
236
-
237
- if (callVar) {
238
- // Get value from call site
239
- const callValue = callVar.attributes.value;
240
- if (callValue) {
241
- if (passby === 'ref') {
242
- // Pass by reference - store variable name
243
- setVariable(session, paramName, getVariable(session, callValue), false);
244
- session.variables[session.variables.length - 1].passby = 'ref';
245
- session.variables[session.variables.length - 1].refName = callValue;
246
- } else {
247
- // Pass by value
248
- value = substituteVariables(session, callValue);
249
- setVariable(session, paramName, value, false);
250
- }
251
- }
252
- } else {
253
- // No value provided - use default if available
254
- const defaultValue = paramVar.attributes.default || '';
255
- value = substituteVariables(session, defaultValue);
256
- setVariable(session, paramName, value, false);
257
- }
258
- }
259
- }
package/src/tags/catch.ts DELETED
@@ -1,24 +0,0 @@
1
- /**
2
- * <catch> tag - catches exceptions by name
3
- * Maps to mask_catch_integrate in MASK
4
- */
5
-
6
- import type { DiracSession, DiracElement } from '../types/index.js';
7
- import { lookupException, flushCurrentException } from '../runtime/session.js';
8
-
9
- export async function executeCatch(session: DiracSession, element: DiracElement): Promise<void> {
10
- // Get exception name from 'name' attribute (default to "exception")
11
- const exceptionName = element.attributes?.name || 'exception';
12
-
13
- // Look up matching exceptions between current position and last boundary
14
- const caughtCount = lookupException(session, exceptionName);
15
-
16
- // If exceptions were caught, execute the catch block
17
- if (caughtCount > 0) {
18
- const { integrateChildren } = await import('../runtime/interpreter.js');
19
- await integrateChildren(session, element);
20
- }
21
-
22
- // Flush current exceptions after processing
23
- flushCurrentException(session);
24
- }
@@ -1,115 +0,0 @@
1
- /**
2
- * <defvar> tag - define variable
3
- * Maps to mask_tag_defvar in MASK
4
- */
5
-
6
-
7
- import type { DiracSession, DiracElement } from '../types/index.js';
8
- import { setVariable, substituteVariables } from '../runtime/session.js';
9
- import { integrate } from '../runtime/interpreter.js';
10
- import { executeParameters } from './parameters.js';
11
-
12
- export async function executeDefvar(session: DiracSession, element: DiracElement): Promise<void> {
13
- const name = element.attributes.name;
14
- const valueAttr = element.attributes.value;
15
- const visibleAttr = element.attributes.visible || 'false';
16
- const literal = 'literal' in element.attributes;
17
- const trimAttr = element.attributes.trim;
18
- const trim = trimAttr !== 'false'; // Trim by default unless explicitly set to false
19
-
20
- if (!name) {
21
- throw new Error('<defvar> requires name attribute');
22
- }
23
-
24
- // Determine visibility
25
- const visible = visibleAttr === 'true' || visibleAttr === 'variable' || visibleAttr === 'both';
26
-
27
- let value: any;
28
- if (valueAttr !== undefined) {
29
- value = substituteVariables(session, valueAttr);
30
- } else if (literal) {
31
- // Literal mode: serialize children to XML text without executing
32
- if (element.children && element.children.length > 0) {
33
- value = serializeToXml(element.children);
34
- } else if (element.text) {
35
- value = substituteVariables(session, element.text);
36
- } else {
37
- value = '';
38
- }
39
- } else if (element.children && element.children.length > 0) {
40
- // If the first child is a <parameters> tag, call and assign its return value
41
- if (element.children.length === 1 && element.children[0].tag && element.children[0].tag.toLowerCase() === 'parameters') {
42
- value = await executeParameters(session, element.children[0]);
43
- } else {
44
- // Otherwise, execute all children and capture output
45
- const prevOutput = session.output;
46
- session.output = [];
47
- for (const child of element.children) {
48
- await integrate(session, child);
49
- }
50
- value = session.output.join('');
51
- session.output = prevOutput;
52
- }
53
- } else if (element.text) {
54
- value = substituteVariables(session, element.text);
55
- } else {
56
- value = '';
57
- }
58
-
59
- // Apply trim if requested
60
- if (trim && typeof value === 'string') {
61
- value = value.trim();
62
- }
63
-
64
- setVariable(session, name, value, visible);
65
- }
66
-
67
- function serializeToXml(children: DiracElement[]): string {
68
- let xml = '';
69
-
70
- for (const child of children) {
71
- if (!child.tag || child.tag === '') {
72
- // Text node
73
- xml += child.text || '';
74
- } else {
75
- // Element node
76
- xml += `<${child.tag}`;
77
-
78
- // Add attributes
79
- for (const [attrName, attrValue] of Object.entries(child.attributes)) {
80
- xml += ` ${attrName}="${escapeXml(attrValue)}"`;
81
- }
82
-
83
- // Self-closing or with children
84
- if (child.children.length === 0 && !child.text) {
85
- xml += ' />';
86
- } else {
87
- xml += '>';
88
-
89
- // Only add text content if there are no children
90
- // (if there are children, text is stored in text node children)
91
- if (child.text && child.children.length === 0) {
92
- xml += escapeXml(child.text);
93
- }
94
-
95
- // Add children (which may include text nodes)
96
- if (child.children.length > 0) {
97
- xml += serializeToXml(child.children);
98
- }
99
-
100
- xml += `</${child.tag}>`;
101
- }
102
- }
103
- }
104
-
105
- return xml;
106
- }
107
-
108
- function escapeXml(text: string): string {
109
- return text
110
- .replace(/&/g, '&amp;')
111
- .replace(/</g, '&lt;')
112
- .replace(/>/g, '&gt;')
113
- .replace(/"/g, '&quot;')
114
- .replace(/'/g, '&apos;');
115
- }
@@ -1,21 +0,0 @@
1
- /**
2
- * <environment> tag - read environment variables
3
- * Usage: <environment name="VAR_NAME" />
4
- */
5
-
6
- import type { DiracSession, DiracElement } from '../types/index.js';
7
- import { emit } from '../runtime/session.js';
8
-
9
- export async function executeEnvironment(session: DiracSession, element: DiracElement): Promise<void> {
10
- const name = element.attributes.name;
11
-
12
- if (!name) {
13
- throw new Error('<environment> requires name attribute');
14
- }
15
-
16
- // Get environment variable value
17
- const value = process.env[name] || '';
18
-
19
- // Emit the value to output
20
- emit(session, value);
21
- }
package/src/tags/eval.ts DELETED
@@ -1,71 +0,0 @@
1
- /**
2
- * <eval> tag - evaluate JavaScript expression
3
- * Maps to mask_tag_eval in MASK (but for JS, not C)
4
- */
5
-
6
- import type { DiracSession, DiracElement } from '../types/index.js';
7
- import { setVariable, getVariable, substituteVariables } from '../runtime/session.js';
8
-
9
- // AsyncFunction constructor
10
- const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
11
-
12
- export async function executeEval(session: DiracSession, element: DiracElement): Promise<void> {
13
- const name = element.attributes.name;
14
- const exprAttr = element.attributes.expr;
15
-
16
- // Get expression as-is (do not replace ${var})
17
- let expr: string;
18
- if (exprAttr) {
19
- expr = exprAttr;
20
- } else if (element.text) {
21
- expr = element.text;
22
- } else {
23
- throw new Error('<eval> requires expr attribute or text content');
24
- }
25
-
26
- if (session.debug) {
27
- console.error(`[EVAL] Code after substitution:\n${expr}\n`);
28
- }
29
-
30
- try {
31
- // Build context object with all variables
32
- const context: Record<string, any> = {};
33
- for (const v of session.variables) {
34
- context[v.name] = v.value;
35
- }
36
-
37
- // Add Node.js modules to context
38
- const { default: fs } = await import('fs');
39
- const { default: path } = await import('path');
40
- const { fileURLToPath } = await import('url');
41
- context.fs = fs;
42
- context.path = path;
43
- context.__dirname = process.cwd(); // ESM doesn't have __dirname, use cwd
44
-
45
- // Add helper to get current parameters from stack
46
- context.getParams = () => {
47
- const params = session.parameterStack[session.parameterStack.length - 1];
48
- return params && params[0] ? params[0] : null;
49
- };
50
-
51
- // Add session object for orchestration (reserved identifier in eval context)
52
- context.session = session;
53
-
54
- let result: any;
55
- // Execute as async function to support top-level await
56
- const func = new AsyncFunction(...Object.keys(context), expr);
57
- result = await func(...Object.values(context));
58
-
59
- if (session.debug) {
60
- console.error(`[EVAL] Result: ${JSON.stringify(result)}`);
61
- }
62
-
63
- // Store result if name provided
64
- if (name) {
65
- setVariable(session, name, result, false);
66
- }
67
-
68
- } catch (error) {
69
- throw new Error(`Eval error: ${error instanceof Error ? error.message : String(error)}`);
70
- }
71
- }
@@ -1,20 +0,0 @@
1
- /**
2
- * <exception> tag - outputs currently caught exceptions
3
- * Maps to mask_exception_integrate in MASK
4
- * Used inside <catch> blocks to access exception content
5
- */
6
-
7
- import type { DiracSession, DiracElement } from '../types/index.js';
8
- import { getCurrentExceptions } from '../runtime/session.js';
9
-
10
- export async function executeException(session: DiracSession, element: DiracElement): Promise<void> {
11
- // Get the currently caught exceptions
12
- const exceptions = getCurrentExceptions(session);
13
-
14
- // Process each exception DOM element's children
15
- const { integrateChildren } = await import('../runtime/interpreter.js');
16
- for (const exceptionDom of exceptions) {
17
- // Execute the children of the exception (the exception content)
18
- await integrateChildren(session, exceptionDom);
19
- }
20
- }