@rhost/testkit 1.5.1 → 1.5.2

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 (157) hide show
  1. package/node_modules/@ursamu/mushcode/.github/workflows/publish.yml +36 -0
  2. package/node_modules/@ursamu/mushcode/LICENSE +21 -0
  3. package/node_modules/@ursamu/mushcode/README.md +110 -0
  4. package/node_modules/@ursamu/mushcode/_dist/mod.d.ts +36 -0
  5. package/node_modules/@ursamu/mushcode/_dist/mod.d.ts.map +1 -0
  6. package/node_modules/@ursamu/mushcode/_dist/parser/mod.d.ts +41 -0
  7. package/node_modules/@ursamu/mushcode/_dist/parser/mod.d.ts.map +1 -0
  8. package/node_modules/@ursamu/mushcode/_dist/src/analyze/commands.d.ts +15 -0
  9. package/node_modules/@ursamu/mushcode/_dist/src/analyze/commands.d.ts.map +1 -0
  10. package/node_modules/@ursamu/mushcode/_dist/src/analyze/deps.d.ts +18 -0
  11. package/node_modules/@ursamu/mushcode/_dist/src/analyze/deps.d.ts.map +1 -0
  12. package/node_modules/@ursamu/mushcode/_dist/src/analyze/mod.d.ts +20 -0
  13. package/node_modules/@ursamu/mushcode/_dist/src/analyze/mod.d.ts.map +1 -0
  14. package/node_modules/@ursamu/mushcode/_dist/src/analyze/tags.d.ts +6 -0
  15. package/node_modules/@ursamu/mushcode/_dist/src/analyze/tags.d.ts.map +1 -0
  16. package/node_modules/@ursamu/mushcode/_dist/src/eval/context.d.ts +85 -0
  17. package/node_modules/@ursamu/mushcode/_dist/src/eval/context.d.ts.map +1 -0
  18. package/node_modules/@ursamu/mushcode/_dist/src/eval/engine.d.ts +48 -0
  19. package/node_modules/@ursamu/mushcode/_dist/src/eval/engine.d.ts.map +1 -0
  20. package/node_modules/@ursamu/mushcode/_dist/src/eval/mod.d.ts +26 -0
  21. package/node_modules/@ursamu/mushcode/_dist/src/eval/mod.d.ts.map +1 -0
  22. package/node_modules/@ursamu/mushcode/_dist/src/eval/stdlib/mod.d.ts +3 -0
  23. package/node_modules/@ursamu/mushcode/_dist/src/eval/stdlib/mod.d.ts.map +1 -0
  24. package/node_modules/@ursamu/mushcode/_dist/src/lint/mod.d.ts +38 -0
  25. package/node_modules/@ursamu/mushcode/_dist/src/lint/mod.d.ts.map +1 -0
  26. package/node_modules/@ursamu/mushcode/_dist/src/print/mod.d.ts +18 -0
  27. package/node_modules/@ursamu/mushcode/_dist/src/print/mod.d.ts.map +1 -0
  28. package/node_modules/@ursamu/mushcode/_dist/src/print/printer.d.ts +15 -0
  29. package/node_modules/@ursamu/mushcode/_dist/src/print/printer.d.ts.map +1 -0
  30. package/node_modules/@ursamu/mushcode/_dist/src/traverse/mod.d.ts +19 -0
  31. package/node_modules/@ursamu/mushcode/_dist/src/traverse/mod.d.ts.map +1 -0
  32. package/node_modules/@ursamu/mushcode/_dist/src/traverse/transform.d.ts +27 -0
  33. package/node_modules/@ursamu/mushcode/_dist/src/traverse/transform.d.ts.map +1 -0
  34. package/node_modules/@ursamu/mushcode/_dist/src/traverse/walk.d.ts +27 -0
  35. package/node_modules/@ursamu/mushcode/_dist/src/traverse/walk.d.ts.map +1 -0
  36. package/node_modules/@ursamu/mushcode/deno.json +26 -0
  37. package/node_modules/@ursamu/mushcode/deno.lock +42 -0
  38. package/node_modules/@ursamu/mushcode/docs/analyze.md +145 -0
  39. package/node_modules/@ursamu/mushcode/docs/eval.md +312 -0
  40. package/node_modules/@ursamu/mushcode/docs/lint.md +152 -0
  41. package/node_modules/@ursamu/mushcode/docs/parser.md +196 -0
  42. package/node_modules/@ursamu/mushcode/docs/print.md +84 -0
  43. package/node_modules/@ursamu/mushcode/docs/stdlib.md +418 -0
  44. package/node_modules/@ursamu/mushcode/docs/traverse.md +167 -0
  45. package/node_modules/@ursamu/mushcode/grammar/mux-softcode.pegjs +781 -0
  46. package/node_modules/@ursamu/mushcode/mod.js +44 -0
  47. package/node_modules/@ursamu/mushcode/mod.js.map +1 -0
  48. package/node_modules/@ursamu/mushcode/mod.ts +63 -0
  49. package/node_modules/@ursamu/mushcode/package.json +38 -0
  50. package/node_modules/@ursamu/mushcode/parser/mod.js +47 -0
  51. package/node_modules/@ursamu/mushcode/parser/mod.js.map +1 -0
  52. package/node_modules/@ursamu/mushcode/parser/mod.ts +99 -0
  53. package/node_modules/@ursamu/mushcode/parser/mux-softcode.js +3833 -0
  54. package/node_modules/@ursamu/mushcode/parser/mux-softcode.mjs +3837 -0
  55. package/node_modules/@ursamu/mushcode/src/analyze/commands.js +29 -0
  56. package/node_modules/@ursamu/mushcode/src/analyze/commands.js.map +1 -0
  57. package/node_modules/@ursamu/mushcode/src/analyze/commands.ts +46 -0
  58. package/node_modules/@ursamu/mushcode/src/analyze/deps.js +45 -0
  59. package/node_modules/@ursamu/mushcode/src/analyze/deps.js.map +1 -0
  60. package/node_modules/@ursamu/mushcode/src/analyze/deps.ts +51 -0
  61. package/node_modules/@ursamu/mushcode/src/analyze/mod.js +18 -0
  62. package/node_modules/@ursamu/mushcode/src/analyze/mod.js.map +1 -0
  63. package/node_modules/@ursamu/mushcode/src/analyze/mod.ts +20 -0
  64. package/node_modules/@ursamu/mushcode/src/analyze/tags.js +11 -0
  65. package/node_modules/@ursamu/mushcode/src/analyze/tags.js.map +1 -0
  66. package/node_modules/@ursamu/mushcode/src/analyze/tags.ts +11 -0
  67. package/node_modules/@ursamu/mushcode/src/eval/context.js +22 -0
  68. package/node_modules/@ursamu/mushcode/src/eval/context.js.map +1 -0
  69. package/node_modules/@ursamu/mushcode/src/eval/context.ts +177 -0
  70. package/node_modules/@ursamu/mushcode/src/eval/engine.js +238 -0
  71. package/node_modules/@ursamu/mushcode/src/eval/engine.js.map +1 -0
  72. package/node_modules/@ursamu/mushcode/src/eval/engine.ts +276 -0
  73. package/node_modules/@ursamu/mushcode/src/eval/mod.js +25 -0
  74. package/node_modules/@ursamu/mushcode/src/eval/mod.js.map +1 -0
  75. package/node_modules/@ursamu/mushcode/src/eval/mod.ts +31 -0
  76. package/node_modules/@ursamu/mushcode/src/eval/stdlib/compare.js +56 -0
  77. package/node_modules/@ursamu/mushcode/src/eval/stdlib/compare.js.map +1 -0
  78. package/node_modules/@ursamu/mushcode/src/eval/stdlib/compare.ts +16 -0
  79. package/node_modules/@ursamu/mushcode/src/eval/stdlib/db.js +91 -0
  80. package/node_modules/@ursamu/mushcode/src/eval/stdlib/db.js.map +1 -0
  81. package/node_modules/@ursamu/mushcode/src/eval/stdlib/db.ts +104 -0
  82. package/node_modules/@ursamu/mushcode/src/eval/stdlib/iter.js +91 -0
  83. package/node_modules/@ursamu/mushcode/src/eval/stdlib/iter.js.map +1 -0
  84. package/node_modules/@ursamu/mushcode/src/eval/stdlib/iter.ts +98 -0
  85. package/node_modules/@ursamu/mushcode/src/eval/stdlib/logic.js +79 -0
  86. package/node_modules/@ursamu/mushcode/src/eval/stdlib/logic.js.map +1 -0
  87. package/node_modules/@ursamu/mushcode/src/eval/stdlib/logic.ts +84 -0
  88. package/node_modules/@ursamu/mushcode/src/eval/stdlib/math.js +120 -0
  89. package/node_modules/@ursamu/mushcode/src/eval/stdlib/math.js.map +1 -0
  90. package/node_modules/@ursamu/mushcode/src/eval/stdlib/math.ts +115 -0
  91. package/node_modules/@ursamu/mushcode/src/eval/stdlib/mod.js +17 -0
  92. package/node_modules/@ursamu/mushcode/src/eval/stdlib/mod.js.map +1 -0
  93. package/node_modules/@ursamu/mushcode/src/eval/stdlib/mod.ts +19 -0
  94. package/node_modules/@ursamu/mushcode/src/eval/stdlib/register.js +28 -0
  95. package/node_modules/@ursamu/mushcode/src/eval/stdlib/register.js.map +1 -0
  96. package/node_modules/@ursamu/mushcode/src/eval/stdlib/register.ts +31 -0
  97. package/node_modules/@ursamu/mushcode/src/eval/stdlib/string.js +153 -0
  98. package/node_modules/@ursamu/mushcode/src/eval/stdlib/string.js.map +1 -0
  99. package/node_modules/@ursamu/mushcode/src/eval/stdlib/string.ts +154 -0
  100. package/node_modules/@ursamu/mushcode/src/lint/builtin_arities.js +212 -0
  101. package/node_modules/@ursamu/mushcode/src/lint/builtin_arities.js.map +1 -0
  102. package/node_modules/@ursamu/mushcode/src/lint/builtin_arities.ts +68 -0
  103. package/node_modules/@ursamu/mushcode/src/lint/mod.js +60 -0
  104. package/node_modules/@ursamu/mushcode/src/lint/mod.js.map +1 -0
  105. package/node_modules/@ursamu/mushcode/src/lint/mod.ts +96 -0
  106. package/node_modules/@ursamu/mushcode/src/lint/rules/arg_count.js +37 -0
  107. package/node_modules/@ursamu/mushcode/src/lint/rules/arg_count.js.map +1 -0
  108. package/node_modules/@ursamu/mushcode/src/lint/rules/arg_count.ts +44 -0
  109. package/node_modules/@ursamu/mushcode/src/lint/rules/iter_var_outside_iter.js +55 -0
  110. package/node_modules/@ursamu/mushcode/src/lint/rules/iter_var_outside_iter.js.map +1 -0
  111. package/node_modules/@ursamu/mushcode/src/lint/rules/iter_var_outside_iter.ts +60 -0
  112. package/node_modules/@ursamu/mushcode/src/lint/rules/missing_wildcard.js +31 -0
  113. package/node_modules/@ursamu/mushcode/src/lint/rules/missing_wildcard.js.map +1 -0
  114. package/node_modules/@ursamu/mushcode/src/lint/rules/missing_wildcard.ts +40 -0
  115. package/node_modules/@ursamu/mushcode/src/lint/rules/register_before_set.js +59 -0
  116. package/node_modules/@ursamu/mushcode/src/lint/rules/register_before_set.js.map +1 -0
  117. package/node_modules/@ursamu/mushcode/src/lint/rules/register_before_set.ts +64 -0
  118. package/node_modules/@ursamu/mushcode/src/print/lock_printer.js +43 -0
  119. package/node_modules/@ursamu/mushcode/src/print/lock_printer.js.map +1 -0
  120. package/node_modules/@ursamu/mushcode/src/print/lock_printer.ts +41 -0
  121. package/node_modules/@ursamu/mushcode/src/print/mod.js +17 -0
  122. package/node_modules/@ursamu/mushcode/src/print/mod.js.map +1 -0
  123. package/node_modules/@ursamu/mushcode/src/print/mod.ts +18 -0
  124. package/node_modules/@ursamu/mushcode/src/print/printer.js +91 -0
  125. package/node_modules/@ursamu/mushcode/src/print/printer.js.map +1 -0
  126. package/node_modules/@ursamu/mushcode/src/print/printer.ts +132 -0
  127. package/node_modules/@ursamu/mushcode/src/traverse/child_slots.js +129 -0
  128. package/node_modules/@ursamu/mushcode/src/traverse/child_slots.js.map +1 -0
  129. package/node_modules/@ursamu/mushcode/src/traverse/child_slots.ts +51 -0
  130. package/node_modules/@ursamu/mushcode/src/traverse/mod.js +17 -0
  131. package/node_modules/@ursamu/mushcode/src/traverse/mod.js.map +1 -0
  132. package/node_modules/@ursamu/mushcode/src/traverse/mod.ts +19 -0
  133. package/node_modules/@ursamu/mushcode/src/traverse/transform.js +70 -0
  134. package/node_modules/@ursamu/mushcode/src/traverse/transform.js.map +1 -0
  135. package/node_modules/@ursamu/mushcode/src/traverse/transform.ts +84 -0
  136. package/node_modules/@ursamu/mushcode/src/traverse/walk.js +55 -0
  137. package/node_modules/@ursamu/mushcode/src/traverse/walk.js.map +1 -0
  138. package/node_modules/@ursamu/mushcode/src/traverse/walk.ts +82 -0
  139. package/node_modules/@ursamu/mushcode/tests/01-literals.test.ts +105 -0
  140. package/node_modules/@ursamu/mushcode/tests/02-substitutions.test.ts +145 -0
  141. package/node_modules/@ursamu/mushcode/tests/03-function-calls.test.ts +184 -0
  142. package/node_modules/@ursamu/mushcode/tests/04-eval-blocks.test.ts +110 -0
  143. package/node_modules/@ursamu/mushcode/tests/05-braced-strings.test.ts +119 -0
  144. package/node_modules/@ursamu/mushcode/tests/06-commands.test.ts +222 -0
  145. package/node_modules/@ursamu/mushcode/tests/07-dollar-patterns.test.ts +156 -0
  146. package/node_modules/@ursamu/mushcode/tests/08-lock-expressions.test.ts +159 -0
  147. package/node_modules/@ursamu/mushcode/tests/09-edge-cases.test.ts +162 -0
  148. package/node_modules/@ursamu/mushcode/tests/10-regression.test.ts +211 -0
  149. package/node_modules/@ursamu/mushcode/tests/11-tags.test.ts +357 -0
  150. package/node_modules/@ursamu/mushcode/tests/12-locations.test.ts +162 -0
  151. package/node_modules/@ursamu/mushcode/tests/13-eval.test.ts +389 -0
  152. package/node_modules/@ursamu/mushcode/tests/analyze.test.ts +194 -0
  153. package/node_modules/@ursamu/mushcode/tests/helpers.ts +69 -0
  154. package/node_modules/@ursamu/mushcode/tests/lint.test.ts +232 -0
  155. package/node_modules/@ursamu/mushcode/tests/print.test.ts +204 -0
  156. package/node_modules/@ursamu/mushcode/tests/traverse.test.ts +211 -0
  157. package/package.json +4 -1
@@ -0,0 +1,29 @@
1
+ import { findAll } from "../traverse/walk.js";
2
+ import { print } from "../print/mod.js";
3
+ /**
4
+ * Extract all DollarPattern and ListenPattern nodes from the tree, returning
5
+ * a flat list with the printed pattern text for easy display.
6
+ *
7
+ * Scans the entire tree so it works on CommandList roots and AttributeSet
8
+ * values alike.
9
+ */ export function extractCommands(root) {
10
+ const entries = [];
11
+ for (const node of findAll(root, "DollarPattern")){
12
+ entries.push({
13
+ type: "dollar",
14
+ patternText: print(node.pattern),
15
+ pattern: node.pattern,
16
+ action: node.action
17
+ });
18
+ }
19
+ for (const node of findAll(root, "ListenPattern")){
20
+ entries.push({
21
+ type: "listen",
22
+ patternText: print(node.pattern),
23
+ pattern: node.pattern,
24
+ action: node.action
25
+ });
26
+ }
27
+ return entries;
28
+ }
29
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.js","sources":["./commands.ts"],"names":[],"mappings":"AACA,SAAS,OAAO,8BAAsC;AACtD,SAAS,KAAK,0BAAoC;AAclD;;;;;;CAMC,GACD,OAAO,SAAS,gBAAgB,IAAa;EAC3C,MAAM,UAA0B,EAAE;EAElC,KAAK,MAAM,QAAQ,QAAQ,MAAM,iBAAkB;IACjD,QAAQ,IAAI,CAAC;MACX,MAAa;MACb,aAAa,MAAM,KAAK,OAAO;MAC/B,SAAa,KAAK,OAAO;MACzB,QAAa,KAAK,MAAM;IAC1B;EACF;EAEA,KAAK,MAAM,QAAQ,QAAQ,MAAM,iBAAkB;IACjD,QAAQ,IAAI,CAAC;MACX,MAAa;MACb,aAAa,MAAM,KAAK,OAAO;MAC/B,SAAa,KAAK,OAAO;MACzB,QAAa,KAAK,MAAM;IAC1B;EACF;EAEA,OAAO;AACT"}
@@ -0,0 +1,46 @@
1
+ import type { ASTNode } from "../../parser/mod.ts";
2
+ import { findAll } from "../traverse/walk.js";
3
+ import { print } from "../print/mod.js";
4
+
5
+ /** A `$command` or `^listen` pattern extracted from the AST. */
6
+ export interface PatternEntry {
7
+ /** Whether this is a `$command` or `^listen` trigger. */
8
+ type: "dollar" | "listen";
9
+ /** Printed form of the pattern for display (e.g., "+finger *"). */
10
+ patternText: string;
11
+ /** The raw pattern node (Pattern or PatternAlts). */
12
+ pattern: ASTNode;
13
+ /** The action to execute when the pattern matches. */
14
+ action: ASTNode;
15
+ }
16
+
17
+ /**
18
+ * Extract all DollarPattern and ListenPattern nodes from the tree, returning
19
+ * a flat list with the printed pattern text for easy display.
20
+ *
21
+ * Scans the entire tree so it works on CommandList roots and AttributeSet
22
+ * values alike.
23
+ */
24
+ export function extractCommands(root: ASTNode): PatternEntry[] {
25
+ const entries: PatternEntry[] = [];
26
+
27
+ for (const node of findAll(root, "DollarPattern")) {
28
+ entries.push({
29
+ type: "dollar",
30
+ patternText: print(node.pattern as ASTNode),
31
+ pattern: node.pattern as ASTNode,
32
+ action: node.action as ASTNode,
33
+ });
34
+ }
35
+
36
+ for (const node of findAll(root, "ListenPattern")) {
37
+ entries.push({
38
+ type: "listen",
39
+ patternText: print(node.pattern as ASTNode),
40
+ pattern: node.pattern as ASTNode,
41
+ action: node.action as ASTNode,
42
+ });
43
+ }
44
+
45
+ return entries;
46
+ }
@@ -0,0 +1,45 @@
1
+ import { findAll } from "../traverse/walk.js";
2
+ import { print } from "../print/mod.js";
3
+ /**
4
+ * Extract dependency edges from the tree: u() calls, @trigger commands, and
5
+ * get()/v() attribute reads.
6
+ *
7
+ * Targets are the printed form of the first argument (for function calls) or
8
+ * the object slot (for @trigger). Dynamic targets (eval blocks) are included
9
+ * as-printed — the caller decides how to interpret them.
10
+ */ export function extractDeps(root) {
11
+ const deps = [];
12
+ for (const node of findAll(root, "FunctionCall")){
13
+ const name = node.name.toLowerCase();
14
+ const args = node.args;
15
+ if (args.length === 0) continue;
16
+ const target = print(args[0]);
17
+ if (name === "u") {
18
+ deps.push({
19
+ type: "u",
20
+ target
21
+ });
22
+ } else if (name === "get") {
23
+ deps.push({
24
+ type: "get",
25
+ target
26
+ });
27
+ } else if (name === "v") {
28
+ deps.push({
29
+ type: "get",
30
+ target
31
+ });
32
+ }
33
+ }
34
+ for (const node of findAll(root, "AtCommand")){
35
+ const name = node.name.toLowerCase();
36
+ if (name !== "trigger") continue;
37
+ if (!node.object) continue;
38
+ deps.push({
39
+ type: "trigger",
40
+ target: print(node.object)
41
+ });
42
+ }
43
+ return deps;
44
+ }
45
+ //# sourceMappingURL=deps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deps.js","sources":["./deps.ts"],"names":[],"mappings":"AACA,SAAS,OAAO,8BAAsC;AACtD,SAAS,KAAK,0BAAoC;AAclD;;;;;;;CAOC,GACD,OAAO,SAAS,YAAY,IAAa;EACvC,MAAM,OAAmB,EAAE;EAE3B,KAAK,MAAM,QAAQ,QAAQ,MAAM,gBAAiB;IAChD,MAAM,OAAO,AAAC,KAAK,IAAI,CAAY,WAAW;IAC9C,MAAM,OAAQ,KAAK,IAAI;IACvB,IAAI,KAAK,MAAM,KAAK,GAAG;IACvB,MAAM,SAAS,MAAM,IAAI,CAAC,EAAE;IAE5B,IAAI,SAAS,KAAK;MAChB,KAAK,IAAI,CAAC;QAAE,MAAM;QAAK;MAAO;IAChC,OAAO,IAAI,SAAS,OAAO;MACzB,KAAK,IAAI,CAAC;QAAE,MAAM;QAAO;MAAO;IAClC,OAAO,IAAI,SAAS,KAAK;MACvB,KAAK,IAAI,CAAC;QAAE,MAAM;QAAO;MAAO;IAClC;EACF;EAEA,KAAK,MAAM,QAAQ,QAAQ,MAAM,aAAc;IAC7C,MAAM,OAAO,AAAC,KAAK,IAAI,CAAY,WAAW;IAC9C,IAAI,SAAS,WAAW;IACxB,IAAI,CAAC,KAAK,MAAM,EAAE;IAClB,KAAK,IAAI,CAAC;MAAE,MAAM;MAAW,QAAQ,MAAM,KAAK,MAAM;IAAa;EACrE;EAEA,OAAO;AACT"}
@@ -0,0 +1,51 @@
1
+ import type { ASTNode } from "../../parser/mod.ts";
2
+ import { findAll } from "../traverse/walk.js";
3
+ import { print } from "../print/mod.js";
4
+
5
+ /** A single dependency edge found in the softcode: a `u()` call, `@trigger`, or `get()`/`v()` read. */
6
+ export interface DepEntry {
7
+ /**
8
+ * "u" — u(attr, …) call (attribute function invocation)
9
+ * "trigger" — @trigger obj/attr=arg
10
+ * "get" — get(obj/attr) or v(attr) read
11
+ */
12
+ type: "u" | "trigger" | "get";
13
+ /** Printed target, e.g. "me/FN_FINGER", "#weather/ATTR", "[tag(db)]/ATTR". */
14
+ target: string;
15
+ }
16
+
17
+ /**
18
+ * Extract dependency edges from the tree: u() calls, @trigger commands, and
19
+ * get()/v() attribute reads.
20
+ *
21
+ * Targets are the printed form of the first argument (for function calls) or
22
+ * the object slot (for @trigger). Dynamic targets (eval blocks) are included
23
+ * as-printed — the caller decides how to interpret them.
24
+ */
25
+ export function extractDeps(root: ASTNode): DepEntry[] {
26
+ const deps: DepEntry[] = [];
27
+
28
+ for (const node of findAll(root, "FunctionCall")) {
29
+ const name = (node.name as string).toLowerCase();
30
+ const args = node.args as ASTNode[];
31
+ if (args.length === 0) continue;
32
+ const target = print(args[0]);
33
+
34
+ if (name === "u") {
35
+ deps.push({ type: "u", target });
36
+ } else if (name === "get") {
37
+ deps.push({ type: "get", target });
38
+ } else if (name === "v") {
39
+ deps.push({ type: "get", target });
40
+ }
41
+ }
42
+
43
+ for (const node of findAll(root, "AtCommand")) {
44
+ const name = (node.name as string).toLowerCase();
45
+ if (name !== "trigger") continue;
46
+ if (!node.object) continue;
47
+ deps.push({ type: "trigger", target: print(node.object as ASTNode) });
48
+ }
49
+
50
+ return deps;
51
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @module
3
+ * Structural analysis of softcode: extract `$command`/`^listen` patterns,
4
+ * dependency edges (`u()`, `@trigger`, `get()`), and `#tagname` references.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { parse } from "@ursamu/mushcode/parse";
9
+ * import { extractCommands } from "@ursamu/mushcode/analyze";
10
+ *
11
+ * const ast = parse("$+finger *:@pemit %#=[u(me/FN_FINGER,%0)]");
12
+ * const cmds = extractCommands(ast);
13
+ * console.log(cmds[0].patternText); // "+finger *"
14
+ * ```
15
+ */ export { extractCommands } from "./commands.js";
16
+ export { extractDeps } from "./deps.js";
17
+ export { extractTagRefs } from "./tags.js";
18
+ //# sourceMappingURL=mod.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.js","sources":["./mod.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;CAcC,GAED,SAAS,eAAe,wBAAgD;AAExE,SAAS,WAAW,oBAAgD;AACpE,SAAS,cAAc,oBAA6C"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @module
3
+ * Structural analysis of softcode: extract `$command`/`^listen` patterns,
4
+ * dependency edges (`u()`, `@trigger`, `get()`), and `#tagname` references.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { parse } from "@ursamu/mushcode/parse";
9
+ * import { extractCommands } from "@ursamu/mushcode/analyze";
10
+ *
11
+ * const ast = parse("$+finger *:@pemit %#=[u(me/FN_FINGER,%0)]");
12
+ * const cmds = extractCommands(ast);
13
+ * console.log(cmds[0].patternText); // "+finger *"
14
+ * ```
15
+ */
16
+ export type { PatternEntry } from "./commands.js";
17
+ export { extractCommands } from "./commands.js";
18
+ export type { DepEntry } from "./deps.js";
19
+ export { extractDeps } from "./deps.js";
20
+ export { extractTagRefs } from "./tags.js";
@@ -0,0 +1,11 @@
1
+ import { findAll } from "../traverse/walk.js";
2
+ /**
3
+ * Return a deduplicated, sorted list of every tag name referenced by a `#tagname`
4
+ * TagRef node anywhere in the tree.
5
+ */ export function extractTagRefs(root) {
6
+ const names = findAll(root, "TagRef").map((n)=>n.name);
7
+ return [
8
+ ...new Set(names)
9
+ ].sort();
10
+ }
11
+ //# sourceMappingURL=tags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tags.js","sources":["./tags.ts"],"names":[],"mappings":"AACA,SAAS,OAAO,8BAAqC;AAErD;;;CAGC,GACD,OAAO,SAAS,eAAe,IAAa;EAC1C,MAAM,QAAQ,QAAQ,MAAM,UAAU,GAAG,CAAC,CAAA,IAAK,EAAE,IAAI;EACrD,OAAO;OAAI,IAAI,IAAI;GAAO,CAAC,IAAI;AACjC"}
@@ -0,0 +1,11 @@
1
+ import type { ASTNode } from "../../parser/mod.ts";
2
+ import { findAll } from "../traverse/walk.js";
3
+
4
+ /**
5
+ * Return a deduplicated, sorted list of every tag name referenced by a `#tagname`
6
+ * TagRef node anywhere in the tree.
7
+ */
8
+ export function extractTagRefs(root: ASTNode): string[] {
9
+ const names = findAll(root, "TagRef").map(n => n.name as string);
10
+ return [...new Set(names)].sort();
11
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Create a default {@link EvalContext} with safe fallback values.
3
+ *
4
+ * Provide at minimum `enactor` and `executor` (usually the same UUID for
5
+ * top-level evaluations). All other fields default to safe empty values and a
6
+ * recursion limit of 100.
7
+ *
8
+ * @example
9
+ * const ctx = makeContext({ enactor: "player-uuid", executor: "player-uuid" });
10
+ */ export function makeContext(partial) {
11
+ return {
12
+ caller: null,
13
+ args: [],
14
+ registers: new Map(),
15
+ iterStack: [],
16
+ depth: 0,
17
+ maxDepth: 100,
18
+ maxOutputLen: 65_536,
19
+ ...partial
20
+ };
21
+ }
22
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sources":["./context.ts"],"names":[],"mappings":"AA6DA;;;;;;;;;CASC,GACD,OAAO,SAAS,YACd,OAAyE;EAEzE,OAAO;IACL,QAAW;IACX,MAAW,EAAE;IACb,WAAW,IAAI;IACf,WAAW,EAAE;IACb,OAAc;IACd,UAAc;IACd,cAAc;IACd,GAAG,OAAO;EACZ;AACF"}
@@ -0,0 +1,177 @@
1
+ import type { ASTNode } from "../../parser/mod.ts";
2
+
3
+ // ── Iteration state ───────────────────────────────────────────────────────────
4
+
5
+ /** One frame on the iteration stack — pushed by iter(), map(), @dolist, etc. */
6
+ export interface IterFrame {
7
+ item: string; // ## — current element value
8
+ index: number; // #@ — current position (1-based)
9
+ }
10
+
11
+ // ── Custom substitution handlers ──────────────────────────────────────────────
12
+
13
+ /** A custom substitution handler registered via `EvalEngine.registerSub()`. */
14
+ export type SubHandlerFn = (code: string, ctx: EvalContext) => Promise<string> | string;
15
+
16
+ // ── Command fallback handler ──────────────────────────────────────────────────
17
+
18
+ /**
19
+ * A fallback handler called when an `@command` is executed but no specific
20
+ * handler is registered for that command name.
21
+ */
22
+ export type CommandFallbackFn = (
23
+ name: string,
24
+ switches: string[],
25
+ object: string | null,
26
+ value: string | null,
27
+ ctx: EvalContext,
28
+ engine: IEvalEngine,
29
+ ) => Promise<void>;
30
+
31
+ // ── Evaluation context ────────────────────────────────────────────────────────
32
+
33
+ /**
34
+ * Runtime state threaded through every eval call.
35
+ *
36
+ * `registers` is intentionally mutable — `setq()` writes to it and subsequent
37
+ * reads within the same attribute eval see the updated value.
38
+ */
39
+ export interface EvalContext {
40
+ /** UUID of the enacting object — %# */
41
+ enactor: string;
42
+ /** UUID of the executing object — %! */
43
+ executor: string;
44
+ /** UUID of the calling object — %@ (null at the top level) */
45
+ caller: string | null;
46
+ /** Positional arguments — %0 through %9 */
47
+ args: string[];
48
+ /** Named registers — %q<name>. setq() mutates this map. */
49
+ registers: Map<string, string>;
50
+ /** Iteration stack — ## and #@ resolve from iterStack[0] */
51
+ iterStack: IterFrame[];
52
+ /** Current recursion depth (incremented on each u() call) */
53
+ depth: number;
54
+ /** Maximum allowed recursion depth before returning #-1 error */
55
+ maxDepth: number;
56
+ /** Maximum total output length per evalString call (default 65 536) */
57
+ maxOutputLen: number;
58
+ /** Optional cancellation signal */
59
+ signal?: AbortSignal;
60
+ }
61
+
62
+ /**
63
+ * Create a default {@link EvalContext} with safe fallback values.
64
+ *
65
+ * Provide at minimum `enactor` and `executor` (usually the same UUID for
66
+ * top-level evaluations). All other fields default to safe empty values and a
67
+ * recursion limit of 100.
68
+ *
69
+ * @example
70
+ * const ctx = makeContext({ enactor: "player-uuid", executor: "player-uuid" });
71
+ */
72
+ export function makeContext(
73
+ partial: Partial<EvalContext> & Pick<EvalContext, "enactor" | "executor">,
74
+ ): EvalContext {
75
+ return {
76
+ caller: null,
77
+ args: [],
78
+ registers: new Map(),
79
+ iterStack: [],
80
+ depth: 0,
81
+ maxDepth: 100,
82
+ maxOutputLen: 65_536,
83
+ ...partial,
84
+ };
85
+ }
86
+
87
+ // ── Thunks (lazy arg evaluation) ──────────────────────────────────────────────
88
+
89
+ /**
90
+ * A lazily-evaluated function argument.
91
+ * Call it to evaluate the underlying AST node in the current context.
92
+ * Pass a partial context override (e.g. `{ iterStack: [...] }`) to temporarily
93
+ * change evaluation state — used by iter() to set ## and #@.
94
+ */
95
+ export type EvalThunk = (ctxOverride?: Partial<EvalContext>) => Promise<string>;
96
+
97
+ // ── Database accessor ─────────────────────────────────────────────────────────
98
+
99
+ /**
100
+ * Minimal read-only interface to the game database.
101
+ * Implement this in the host application and pass it to EvalEngine.
102
+ */
103
+ export interface ObjectAccessor {
104
+ /** Read a named attribute from an object. Returns `null` if the attribute is absent. */
105
+ getAttr(objectId: string, attr: string): Promise<string | null>;
106
+ /** Resolve a target expression (`"me"`, `"#uuid"`, `"Name"`) to an object UUID. Returns `null` if not found. */
107
+ resolveTarget(from: string, expr: string): Promise<string | null>;
108
+ /** Return the display name of an object. */
109
+ getName(objectId: string): Promise<string>;
110
+ /** Return `true` if the object has the named flag. */
111
+ hasFlag(objectId: string, flag: string): Promise<boolean>;
112
+ }
113
+
114
+ // ── Function and command registrations ───────────────────────────────────────
115
+
116
+ /**
117
+ * A registered softcode function.
118
+ *
119
+ * When `eval` is "eager" (default), all arguments are evaluated before `exec`
120
+ * is called and `args` contains `string[]`.
121
+ *
122
+ * When `eval` is "lazy", `args` contains `EvalThunk[]`. The function calls
123
+ * only the thunks it needs (e.g. `if()` evaluates only the taken branch).
124
+ */
125
+ export interface FunctionImpl {
126
+ /** Argument evaluation strategy. `"eager"` (default) pre-evaluates all args; `"lazy"` passes thunks. */
127
+ eval?: "eager" | "lazy";
128
+ /** Minimum number of arguments required; fewer returns a `#-1` error. */
129
+ minArgs: number;
130
+ /** Maximum number of arguments accepted; more returns a `#-1` error. Use `Infinity` for variadic. */
131
+ maxArgs: number;
132
+ /** The function implementation. Receives `string[]` when eager, `EvalThunk[]` when lazy. */
133
+ exec: (
134
+ args: string[] | EvalThunk[],
135
+ ctx: EvalContext,
136
+ engine: IEvalEngine,
137
+ ) => Promise<string> | string;
138
+ }
139
+
140
+ /** A registered `@command` handler (e.g. `@pemit`, `@trigger`). */
141
+ export interface CommandImpl {
142
+ /** Execute the command. `switches` are the `/switch` tokens; `object` and `value` are the two sides of `=`. */
143
+ exec: (
144
+ switches: string[],
145
+ object: string | null,
146
+ value: string | null,
147
+ ctx: EvalContext,
148
+ engine: IEvalEngine,
149
+ ) => Promise<void>;
150
+ }
151
+
152
+ // ── Engine interface (forward declaration for use in FunctionImpl/CommandImpl) ─
153
+
154
+ /** Public interface of EvalEngine, used in function/command signatures. */
155
+ export interface IEvalEngine {
156
+ /** The host-provided database accessor used by DB stdlib functions. */
157
+ readonly accessor: ObjectAccessor;
158
+ /** Register a softcode function (e.g. `add`, `u`) by name. */
159
+ registerFunction(name: string, impl: FunctionImpl): this;
160
+ /** Register a softcode `@command` handler by name. */
161
+ registerCommand(name: string, impl: CommandImpl): this;
162
+ /**
163
+ * Register a custom `%<code>` substitution handler.
164
+ * Custom handlers are checked before built-in substitutions.
165
+ */
166
+ registerSub(match: string | ((code: string) => boolean), fn: SubHandlerFn): this;
167
+ /**
168
+ * Register a fallback handler for `@commands` with no specific handler registered.
169
+ */
170
+ registerCommandFallback(fn: CommandFallbackFn): this;
171
+ /** Evaluate an AST node to a string. */
172
+ eval(node: ASTNode, ctx: EvalContext): Promise<string>;
173
+ /** Execute a node for its side effects (commands). */
174
+ exec(node: ASTNode, ctx: EvalContext): Promise<void>;
175
+ /** Parse and evaluate a raw softcode string. */
176
+ evalString(source: string, ctx: EvalContext): Promise<string>;
177
+ }