@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.
- package/node_modules/@ursamu/mushcode/.github/workflows/publish.yml +36 -0
- package/node_modules/@ursamu/mushcode/LICENSE +21 -0
- package/node_modules/@ursamu/mushcode/README.md +110 -0
- package/node_modules/@ursamu/mushcode/_dist/mod.d.ts +36 -0
- package/node_modules/@ursamu/mushcode/_dist/mod.d.ts.map +1 -0
- package/node_modules/@ursamu/mushcode/_dist/parser/mod.d.ts +41 -0
- package/node_modules/@ursamu/mushcode/_dist/parser/mod.d.ts.map +1 -0
- package/node_modules/@ursamu/mushcode/_dist/src/analyze/commands.d.ts +15 -0
- package/node_modules/@ursamu/mushcode/_dist/src/analyze/commands.d.ts.map +1 -0
- package/node_modules/@ursamu/mushcode/_dist/src/analyze/deps.d.ts +18 -0
- package/node_modules/@ursamu/mushcode/_dist/src/analyze/deps.d.ts.map +1 -0
- package/node_modules/@ursamu/mushcode/_dist/src/analyze/mod.d.ts +20 -0
- package/node_modules/@ursamu/mushcode/_dist/src/analyze/mod.d.ts.map +1 -0
- package/node_modules/@ursamu/mushcode/_dist/src/analyze/tags.d.ts +6 -0
- package/node_modules/@ursamu/mushcode/_dist/src/analyze/tags.d.ts.map +1 -0
- package/node_modules/@ursamu/mushcode/_dist/src/eval/context.d.ts +85 -0
- package/node_modules/@ursamu/mushcode/_dist/src/eval/context.d.ts.map +1 -0
- package/node_modules/@ursamu/mushcode/_dist/src/eval/engine.d.ts +48 -0
- package/node_modules/@ursamu/mushcode/_dist/src/eval/engine.d.ts.map +1 -0
- package/node_modules/@ursamu/mushcode/_dist/src/eval/mod.d.ts +26 -0
- package/node_modules/@ursamu/mushcode/_dist/src/eval/mod.d.ts.map +1 -0
- package/node_modules/@ursamu/mushcode/_dist/src/eval/stdlib/mod.d.ts +3 -0
- package/node_modules/@ursamu/mushcode/_dist/src/eval/stdlib/mod.d.ts.map +1 -0
- package/node_modules/@ursamu/mushcode/_dist/src/lint/mod.d.ts +38 -0
- package/node_modules/@ursamu/mushcode/_dist/src/lint/mod.d.ts.map +1 -0
- package/node_modules/@ursamu/mushcode/_dist/src/print/mod.d.ts +18 -0
- package/node_modules/@ursamu/mushcode/_dist/src/print/mod.d.ts.map +1 -0
- package/node_modules/@ursamu/mushcode/_dist/src/print/printer.d.ts +15 -0
- package/node_modules/@ursamu/mushcode/_dist/src/print/printer.d.ts.map +1 -0
- package/node_modules/@ursamu/mushcode/_dist/src/traverse/mod.d.ts +19 -0
- package/node_modules/@ursamu/mushcode/_dist/src/traverse/mod.d.ts.map +1 -0
- package/node_modules/@ursamu/mushcode/_dist/src/traverse/transform.d.ts +27 -0
- package/node_modules/@ursamu/mushcode/_dist/src/traverse/transform.d.ts.map +1 -0
- package/node_modules/@ursamu/mushcode/_dist/src/traverse/walk.d.ts +27 -0
- package/node_modules/@ursamu/mushcode/_dist/src/traverse/walk.d.ts.map +1 -0
- package/node_modules/@ursamu/mushcode/deno.json +26 -0
- package/node_modules/@ursamu/mushcode/deno.lock +42 -0
- package/node_modules/@ursamu/mushcode/docs/analyze.md +145 -0
- package/node_modules/@ursamu/mushcode/docs/eval.md +312 -0
- package/node_modules/@ursamu/mushcode/docs/lint.md +152 -0
- package/node_modules/@ursamu/mushcode/docs/parser.md +196 -0
- package/node_modules/@ursamu/mushcode/docs/print.md +84 -0
- package/node_modules/@ursamu/mushcode/docs/stdlib.md +418 -0
- package/node_modules/@ursamu/mushcode/docs/traverse.md +167 -0
- package/node_modules/@ursamu/mushcode/grammar/mux-softcode.pegjs +781 -0
- package/node_modules/@ursamu/mushcode/mod.js +44 -0
- package/node_modules/@ursamu/mushcode/mod.js.map +1 -0
- package/node_modules/@ursamu/mushcode/mod.ts +63 -0
- package/node_modules/@ursamu/mushcode/package.json +38 -0
- package/node_modules/@ursamu/mushcode/parser/mod.js +47 -0
- package/node_modules/@ursamu/mushcode/parser/mod.js.map +1 -0
- package/node_modules/@ursamu/mushcode/parser/mod.ts +99 -0
- package/node_modules/@ursamu/mushcode/parser/mux-softcode.js +3833 -0
- package/node_modules/@ursamu/mushcode/parser/mux-softcode.mjs +3837 -0
- package/node_modules/@ursamu/mushcode/src/analyze/commands.js +29 -0
- package/node_modules/@ursamu/mushcode/src/analyze/commands.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/analyze/commands.ts +46 -0
- package/node_modules/@ursamu/mushcode/src/analyze/deps.js +45 -0
- package/node_modules/@ursamu/mushcode/src/analyze/deps.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/analyze/deps.ts +51 -0
- package/node_modules/@ursamu/mushcode/src/analyze/mod.js +18 -0
- package/node_modules/@ursamu/mushcode/src/analyze/mod.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/analyze/mod.ts +20 -0
- package/node_modules/@ursamu/mushcode/src/analyze/tags.js +11 -0
- package/node_modules/@ursamu/mushcode/src/analyze/tags.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/analyze/tags.ts +11 -0
- package/node_modules/@ursamu/mushcode/src/eval/context.js +22 -0
- package/node_modules/@ursamu/mushcode/src/eval/context.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/eval/context.ts +177 -0
- package/node_modules/@ursamu/mushcode/src/eval/engine.js +238 -0
- package/node_modules/@ursamu/mushcode/src/eval/engine.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/eval/engine.ts +276 -0
- package/node_modules/@ursamu/mushcode/src/eval/mod.js +25 -0
- package/node_modules/@ursamu/mushcode/src/eval/mod.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/eval/mod.ts +31 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/compare.js +56 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/compare.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/compare.ts +16 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/db.js +91 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/db.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/db.ts +104 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/iter.js +91 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/iter.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/iter.ts +98 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/logic.js +79 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/logic.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/logic.ts +84 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/math.js +120 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/math.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/math.ts +115 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/mod.js +17 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/mod.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/mod.ts +19 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/register.js +28 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/register.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/register.ts +31 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/string.js +153 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/string.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/eval/stdlib/string.ts +154 -0
- package/node_modules/@ursamu/mushcode/src/lint/builtin_arities.js +212 -0
- package/node_modules/@ursamu/mushcode/src/lint/builtin_arities.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/lint/builtin_arities.ts +68 -0
- package/node_modules/@ursamu/mushcode/src/lint/mod.js +60 -0
- package/node_modules/@ursamu/mushcode/src/lint/mod.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/lint/mod.ts +96 -0
- package/node_modules/@ursamu/mushcode/src/lint/rules/arg_count.js +37 -0
- package/node_modules/@ursamu/mushcode/src/lint/rules/arg_count.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/lint/rules/arg_count.ts +44 -0
- package/node_modules/@ursamu/mushcode/src/lint/rules/iter_var_outside_iter.js +55 -0
- package/node_modules/@ursamu/mushcode/src/lint/rules/iter_var_outside_iter.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/lint/rules/iter_var_outside_iter.ts +60 -0
- package/node_modules/@ursamu/mushcode/src/lint/rules/missing_wildcard.js +31 -0
- package/node_modules/@ursamu/mushcode/src/lint/rules/missing_wildcard.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/lint/rules/missing_wildcard.ts +40 -0
- package/node_modules/@ursamu/mushcode/src/lint/rules/register_before_set.js +59 -0
- package/node_modules/@ursamu/mushcode/src/lint/rules/register_before_set.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/lint/rules/register_before_set.ts +64 -0
- package/node_modules/@ursamu/mushcode/src/print/lock_printer.js +43 -0
- package/node_modules/@ursamu/mushcode/src/print/lock_printer.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/print/lock_printer.ts +41 -0
- package/node_modules/@ursamu/mushcode/src/print/mod.js +17 -0
- package/node_modules/@ursamu/mushcode/src/print/mod.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/print/mod.ts +18 -0
- package/node_modules/@ursamu/mushcode/src/print/printer.js +91 -0
- package/node_modules/@ursamu/mushcode/src/print/printer.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/print/printer.ts +132 -0
- package/node_modules/@ursamu/mushcode/src/traverse/child_slots.js +129 -0
- package/node_modules/@ursamu/mushcode/src/traverse/child_slots.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/traverse/child_slots.ts +51 -0
- package/node_modules/@ursamu/mushcode/src/traverse/mod.js +17 -0
- package/node_modules/@ursamu/mushcode/src/traverse/mod.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/traverse/mod.ts +19 -0
- package/node_modules/@ursamu/mushcode/src/traverse/transform.js +70 -0
- package/node_modules/@ursamu/mushcode/src/traverse/transform.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/traverse/transform.ts +84 -0
- package/node_modules/@ursamu/mushcode/src/traverse/walk.js +55 -0
- package/node_modules/@ursamu/mushcode/src/traverse/walk.js.map +1 -0
- package/node_modules/@ursamu/mushcode/src/traverse/walk.ts +82 -0
- package/node_modules/@ursamu/mushcode/tests/01-literals.test.ts +105 -0
- package/node_modules/@ursamu/mushcode/tests/02-substitutions.test.ts +145 -0
- package/node_modules/@ursamu/mushcode/tests/03-function-calls.test.ts +184 -0
- package/node_modules/@ursamu/mushcode/tests/04-eval-blocks.test.ts +110 -0
- package/node_modules/@ursamu/mushcode/tests/05-braced-strings.test.ts +119 -0
- package/node_modules/@ursamu/mushcode/tests/06-commands.test.ts +222 -0
- package/node_modules/@ursamu/mushcode/tests/07-dollar-patterns.test.ts +156 -0
- package/node_modules/@ursamu/mushcode/tests/08-lock-expressions.test.ts +159 -0
- package/node_modules/@ursamu/mushcode/tests/09-edge-cases.test.ts +162 -0
- package/node_modules/@ursamu/mushcode/tests/10-regression.test.ts +211 -0
- package/node_modules/@ursamu/mushcode/tests/11-tags.test.ts +357 -0
- package/node_modules/@ursamu/mushcode/tests/12-locations.test.ts +162 -0
- package/node_modules/@ursamu/mushcode/tests/13-eval.test.ts +389 -0
- package/node_modules/@ursamu/mushcode/tests/analyze.test.ts +194 -0
- package/node_modules/@ursamu/mushcode/tests/helpers.ts +69 -0
- package/node_modules/@ursamu/mushcode/tests/lint.test.ts +232 -0
- package/node_modules/@ursamu/mushcode/tests/print.test.ts +204 -0
- package/node_modules/@ursamu/mushcode/tests/traverse.test.ts +211 -0
- package/package.json +4 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: Publish to JSR
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
|
|
14
|
+
- uses: denoland/setup-deno@v2
|
|
15
|
+
with:
|
|
16
|
+
deno-version: v2.x
|
|
17
|
+
|
|
18
|
+
- name: Run tests
|
|
19
|
+
run: deno task test
|
|
20
|
+
|
|
21
|
+
publish:
|
|
22
|
+
needs: test
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
permissions:
|
|
25
|
+
contents: read
|
|
26
|
+
id-token: write # required for JSR OIDC publishing
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v4
|
|
30
|
+
|
|
31
|
+
- uses: denoland/setup-deno@v2
|
|
32
|
+
with:
|
|
33
|
+
deno-version: v2.x
|
|
34
|
+
|
|
35
|
+
- name: Publish to JSR
|
|
36
|
+
run: deno publish
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 UrsaMU Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# @ursamu/mushcode
|
|
2
|
+
|
|
3
|
+
A MUX/RhostMUSH softcode toolkit for Deno and JSR. Parses softcode into an AST,
|
|
4
|
+
evaluates it, lints it for common mistakes, prints it back to canonical text, and
|
|
5
|
+
extracts structural information from it.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { parse, EvalEngine, lint, print, walk } from "jsr:@ursamu/mushcode";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Sub-path imports are available for tree-shaking:
|
|
14
|
+
|
|
15
|
+
| Import path | Exports |
|
|
16
|
+
|--------------------------|--------------------------------------------------------------------------------------------|
|
|
17
|
+
| `jsr:@ursamu/mushcode` | everything below, combined |
|
|
18
|
+
| `…/parse` | `parse`, `ParseError`, `ASTNode`, `SourceLocation`, `NodeType`, `StartRule` |
|
|
19
|
+
| `…/traverse` | `walk`, `transform`, `findAll`, `findFirst`, `findFirstOrNull` |
|
|
20
|
+
| `…/print` | `print`, `PrintOptions`, `PrintMode` |
|
|
21
|
+
| `…/lint` | `lint`, `RULES`, `Diagnostic`, `Severity`, `LintOptions`, `RuleId` |
|
|
22
|
+
| `…/analyze` | `extractCommands`, `extractDeps`, `extractTagRefs`, `PatternEntry`, `DepEntry` |
|
|
23
|
+
| `…/eval` | `EvalEngine`, `makeContext`, `registerStdlib`, `ObjectAccessor`, `EvalContext`, and more |
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
### Parse
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { parse, ParseError } from "jsr:@ursamu/mushcode";
|
|
31
|
+
|
|
32
|
+
const ast = parse("$+finger *:@pemit %#=[u(me/FN_FINGER,%0)]");
|
|
33
|
+
console.log(ast.type); // "DollarPattern"
|
|
34
|
+
|
|
35
|
+
// Lock expressions use the second argument
|
|
36
|
+
const lock = parse("flag^WIZARD|attr^STAFF:1", "LockExpr");
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Traverse
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { parse, findAll } from "jsr:@ursamu/mushcode";
|
|
43
|
+
|
|
44
|
+
const ast = parse("[add(1,[mul(2,3)])]");
|
|
45
|
+
const calls = findAll(ast, "FunctionCall");
|
|
46
|
+
console.log(calls.map(n => n.name)); // ["add", "mul"]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Print
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { parse, print } from "jsr:@ursamu/mushcode";
|
|
53
|
+
|
|
54
|
+
const ast = parse("@pemit %#=Hello;@pemit %#=World");
|
|
55
|
+
console.log(print(ast, { mode: "pretty" }));
|
|
56
|
+
// @pemit %#=Hello
|
|
57
|
+
// @pemit %#=World
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Lint
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { parse, lint } from "jsr:@ursamu/mushcode";
|
|
64
|
+
|
|
65
|
+
const ast = parse("$finger:@pemit %#=[u(me/FN)]");
|
|
66
|
+
const diags = lint(ast);
|
|
67
|
+
diags.forEach(d => console.log(`[${d.severity}] ${d.rule}: ${d.message}`));
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Analyze
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { parse, extractCommands } from "jsr:@ursamu/mushcode";
|
|
74
|
+
|
|
75
|
+
const ast = parse("$+finger *:@pemit %#=[u(me/FN_FINGER,%0)]");
|
|
76
|
+
const cmds = extractCommands(ast);
|
|
77
|
+
console.log(cmds[0].patternText); // "+finger *"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Evaluate
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { EvalEngine, makeContext, registerStdlib } from "jsr:@ursamu/mushcode";
|
|
84
|
+
|
|
85
|
+
const engine = new EvalEngine({
|
|
86
|
+
async getAttr(id, attr) { return null; },
|
|
87
|
+
async resolveTarget(from, expr) { return expr === "me" ? from : null; },
|
|
88
|
+
async getName(id) { return "Tester"; },
|
|
89
|
+
async hasFlag(id, flag) { return false; },
|
|
90
|
+
});
|
|
91
|
+
registerStdlib(engine);
|
|
92
|
+
|
|
93
|
+
const ctx = makeContext({ enactor: "player-uuid", executor: "player-uuid" });
|
|
94
|
+
const result = await engine.evalString("[add(1,2)] [capstr(hello)]", ctx);
|
|
95
|
+
console.log(result); // "3 Hello"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Documentation
|
|
99
|
+
|
|
100
|
+
- [Parser](docs/parser.md) — `parse()`, AST node types, source locations
|
|
101
|
+
- [Traverse](docs/traverse.md) — `walk()`, `transform()`, `findAll()`, `findFirst()`
|
|
102
|
+
- [Print](docs/print.md) — `print()`, compact and pretty modes
|
|
103
|
+
- [Lint](docs/lint.md) — `lint()`, built-in rules, custom rule selection
|
|
104
|
+
- [Analyze](docs/analyze.md) — `extractCommands()`, `extractDeps()`, `extractTagRefs()`
|
|
105
|
+
- [Eval](docs/eval.md) — `EvalEngine`, `makeContext()`, `ObjectAccessor`
|
|
106
|
+
- [Stdlib](docs/stdlib.md) — all built-in softcode functions
|
|
107
|
+
|
|
108
|
+
## License
|
|
109
|
+
|
|
110
|
+
MIT
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* Full-featured MUX/RhostMUSH softcode toolkit: parser, AST traversal,
|
|
4
|
+
* canonical printer, static linter, dependency analyzer, and evaluator.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { parse, lint, print, EvalEngine, makeContext, registerStdlib } from "@ursamu/mushcode";
|
|
9
|
+
*
|
|
10
|
+
* const ast = parse("$+finger *:@pemit %#=[u(me/FN_FINGER,%0)]");
|
|
11
|
+
* const diags = lint(ast);
|
|
12
|
+
* console.log(print(ast)); // "$+finger *:@pemit %#=[u(me/FN_FINGER,%0)]"
|
|
13
|
+
*
|
|
14
|
+
* const engine = new EvalEngine({
|
|
15
|
+
* getAttr: async (_id, _attr) => null,
|
|
16
|
+
* resolveTarget: async (_from, expr) => expr === "me" ? "player-uuid" : null,
|
|
17
|
+
* getName: async (_id) => "Tester",
|
|
18
|
+
* hasFlag: async (_id, _flag) => false,
|
|
19
|
+
* });
|
|
20
|
+
* registerStdlib(engine);
|
|
21
|
+
* const result = await engine.evalString("[add(1,2)]", makeContext({ enactor: "player-uuid", executor: "player-uuid" }));
|
|
22
|
+
* console.log(result); // "3"
|
|
23
|
+
* ```
|
|
24
|
+
*/ export { parse, ParseError } from "./parser/mod.js";
|
|
25
|
+
export type { ASTNode, NodeType, StartRule, SourceLocation, SourcePosition } from "./parser/mod.js";
|
|
26
|
+
export { walk, transform, findAll, findFirst, findFirstOrNull } from "./src/traverse/mod.js";
|
|
27
|
+
export type { Visitor, Transformer } from "./src/traverse/mod.js";
|
|
28
|
+
export { print } from "./src/print/mod.js";
|
|
29
|
+
export type { PrintOptions, PrintMode } from "./src/print/mod.js";
|
|
30
|
+
export { lint, RULES } from "./src/lint/mod.js";
|
|
31
|
+
export type { Diagnostic, Severity, LintOptions, RuleId } from "./src/lint/mod.js";
|
|
32
|
+
export { extractCommands, extractDeps, extractTagRefs } from "./src/analyze/mod.js";
|
|
33
|
+
export type { PatternEntry, DepEntry } from "./src/analyze/mod.js";
|
|
34
|
+
export { EvalEngine, makeContext, registerStdlib } from "./src/eval/mod.js";
|
|
35
|
+
export type { EvalContext, EvalThunk, ObjectAccessor, IEvalEngine, FunctionImpl, CommandImpl, IterFrame } from "./src/eval/mod.js";
|
|
36
|
+
//# sourceMappingURL=mod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sources":["../mod.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;CAuBC,GAWD,SAAS,KAAK,EAAE,UAAU,0BAAiD;AAC3E,cAAc,OAAO,EAAE,QAAQ,EAAE,SAAS,EAC5B,cAAc,EAAE,cAAc,0BAA+B;AAG3E,SAAS,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,eAAe,gCACoB;AACjF,cAAc,OAAO,EAAE,WAAW,gCAA+C;AAGjF,SAAS,KAAK,6BAAgE;AAC9E,cAAc,YAAY,EAAE,SAAS,6BAAyC;AAG9E,SAAS,IAAI,EAAE,KAAK,4BAAyD;AAC7E,cAAc,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,4BACsB;AAG7E,SAAS,eAAe,EAAE,WAAW,EAAE,cAAc,+BAC2B;AAChF,cAAc,YAAY,EAAE,QAAQ,+BAA4C;AAGhF,SAAS,UAAU,EAAE,WAAW,EAAE,cAAc,4BAA6B;AAC7E,cACE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,WAAW,EACnD,YAAY,EAAE,WAAW,EAAE,SAAS,4BACuC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** Union of every node `type` string the parser can produce. */ export type NodeType = "Literal" | "Escape" | "Substitution" | "SpecialVar" | "Wildcard" | "EvalBlock" | "BracedString" | "Text" | "Arg" | "FunctionCall" | "DollarPattern" | "ListenPattern" | "PatternAlts" | "Pattern" | "CommandList" | "AtCommand" | "AttributeSet" | "UserCommand" | "TagRef" | "LockOr" | "LockAnd" | "LockNot" | "LockMe" | "LockDbref" | "LockFlagCheck" | "LockTypeCheck" | "LockAttrCheck" | "LockPlayerName";
|
|
2
|
+
/** A character offset, line number (1-based), and column (1-based) in source text. */ export interface SourcePosition {
|
|
3
|
+
/** Zero-based byte offset from the start of the source string. */ offset: number;
|
|
4
|
+
/** One-based line number. */ line: number;
|
|
5
|
+
/** One-based column number within the line. */ column: number;
|
|
6
|
+
}
|
|
7
|
+
/** The start and end {@link SourcePosition} of an AST node in the original source. */ export interface SourceLocation {
|
|
8
|
+
/** Position of the first character of the node. */ start: SourcePosition;
|
|
9
|
+
/** Position one past the last character of the node. */ end: SourcePosition;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A generic AST node. Every node has a `type` discriminant string and an
|
|
13
|
+
* optional `loc` source location. Additional properties are node-specific
|
|
14
|
+
* (e.g. `value` on Literal, `name` on FunctionCall).
|
|
15
|
+
*/ export type ASTNode = {
|
|
16
|
+
type: string;
|
|
17
|
+
loc?: SourceLocation;
|
|
18
|
+
[key: string]: any;
|
|
19
|
+
};
|
|
20
|
+
/** Thrown when the parser encounters a syntax error in the softcode input. */ export declare class ParseError extends Error {
|
|
21
|
+
readonly location?: {
|
|
22
|
+
line: number;
|
|
23
|
+
column: number;
|
|
24
|
+
offset: number;
|
|
25
|
+
};
|
|
26
|
+
constructor(message: string, location?: {
|
|
27
|
+
line: number;
|
|
28
|
+
column: number;
|
|
29
|
+
offset: number;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/** Which top-level grammar rule to use as the parse entry point. */ export type StartRule = "Start" | "LockExpr";
|
|
33
|
+
/**
|
|
34
|
+
* Parse a raw softcode string and return its AST root node.
|
|
35
|
+
*
|
|
36
|
+
* @param text The softcode source to parse.
|
|
37
|
+
* @param startRule Grammar entry point — `"Start"` for normal softcode (default),
|
|
38
|
+
* `"LockExpr"` for lock-expression strings.
|
|
39
|
+
* @throws {@link ParseError} on syntax errors.
|
|
40
|
+
*/ export declare function parse(text: string, startRule?: StartRule): ASTNode;
|
|
41
|
+
//# sourceMappingURL=mod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sources":["../../parser/mod.ts"],"names":[],"mappings":"AA2BA,8DAA8D,GAC9D,YAAY,WACR,YAAY,WAAW,iBAAiB,eAAe,aACvD,cAAc,iBAAiB,SAAS,QACxC,iBAAiB,kBAAkB,kBACnC,gBAAgB,YAChB,gBAAgB,cAAc,iBAAiB,gBAC/C,WACA,WAAW,YAAY,YAAY,WAAW,cAC9C,kBAAkB,kBAAkB,kBAAkB;AAE1D,oFAAoF,GACpF,iBAAiB;EACf,gEAAgE,GAChE,QAAQ,MAAM;EACd,2BAA2B,GAC3B,MAAQ,MAAM;EACd,6CAA6C,GAC7C,QAAQ,MAAM;;AAGhB,oFAAoF,GACpF,iBAAiB;EACf,iDAAiD,GACjD,OAAO;EACP,sDAAsD,GACtD,KAAO;;AAGT;;;;CAIC,GAED,YAAY;EAAY,MAAM,MAAM;EAAE,MAAM;GAAiB,KAAK,MAAM,GAAG,GAAG;;AAE9E,4EAA4E,GAC5E,OAAO,cAAM,mBAAmB;WAGZ;IAAa,MAAM,MAAM;IAAE,QAAQ,MAAM;IAAE,QAAQ,MAAM;;EAF3E,YACE,SAAS,MAAM,EACf,AAAgB;IAAa,MAAM,MAAM;IAAE,QAAQ,MAAM;IAAE,QAAQ,MAAM;GAAE;AAK/E;AAEA,kEAAkE,GAClE,YAAY,YAAY,UAAU;AAElC;;;;;;;CAOC,GACD,OAAO,iBAAS,MAAM,MAAM,MAAM,EAAE,YAAW,SAAmB,GAAG"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ASTNode } from "../../parser/mod.js";
|
|
2
|
+
/** A `$command` or `^listen` pattern extracted from the AST. */ export interface PatternEntry {
|
|
3
|
+
/** Whether this is a `$command` or `^listen` trigger. */ type: "dollar" | "listen";
|
|
4
|
+
/** Printed form of the pattern for display (e.g., "+finger *"). */ patternText: string;
|
|
5
|
+
/** The raw pattern node (Pattern or PatternAlts). */ pattern: ASTNode;
|
|
6
|
+
/** The action to execute when the pattern matches. */ action: ASTNode;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Extract all DollarPattern and ListenPattern nodes from the tree, returning
|
|
10
|
+
* a flat list with the printed pattern text for easy display.
|
|
11
|
+
*
|
|
12
|
+
* Scans the entire tree so it works on CommandList roots and AttributeSet
|
|
13
|
+
* values alike.
|
|
14
|
+
*/ export declare function extractCommands(root: ASTNode): PatternEntry[];
|
|
15
|
+
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sources":["../../../src/analyze/commands.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,8BAA+B;AAIpD,8DAA8D,GAC9D,iBAAiB;EACf,uDAAuD,GACvD,MAAa,WAAW;EACxB,iEAAiE,GACjE,aAAa,MAAM;EACnB,mDAAmD,GACnD,SAAa;EACb,oDAAoD,GACpD,QAAa;;AAGf;;;;;;CAMC,GACD,OAAO,iBAAS,gBAAgB,MAAM,OAAO,GAAG"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ASTNode } from "../../parser/mod.js";
|
|
2
|
+
/** A single dependency edge found in the softcode: a `u()` call, `@trigger`, or `get()`/`v()` read. */ export interface DepEntry {
|
|
3
|
+
/**
|
|
4
|
+
* "u" — u(attr, …) call (attribute function invocation)
|
|
5
|
+
* "trigger" — @trigger obj/attr=arg
|
|
6
|
+
* "get" — get(obj/attr) or v(attr) read
|
|
7
|
+
*/ type: "u" | "trigger" | "get";
|
|
8
|
+
/** Printed target, e.g. "me/FN_FINGER", "#weather/ATTR", "[tag(db)]/ATTR". */ target: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Extract dependency edges from the tree: u() calls, @trigger commands, and
|
|
12
|
+
* get()/v() attribute reads.
|
|
13
|
+
*
|
|
14
|
+
* Targets are the printed form of the first argument (for function calls) or
|
|
15
|
+
* the object slot (for @trigger). Dynamic targets (eval blocks) are included
|
|
16
|
+
* as-printed — the caller decides how to interpret them.
|
|
17
|
+
*/ export declare function extractDeps(root: ASTNode): DepEntry[];
|
|
18
|
+
//# sourceMappingURL=deps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deps.d.ts","sources":["../../../src/analyze/deps.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,8BAA+B;AAIpD,qGAAqG,GACrG,iBAAiB;EACf;;;;GAIC,GACD,MAAQ,MAAM,YAAY;EAC1B,4EAA4E,GAC5E,QAAQ,MAAM;;AAGhB;;;;;;;CAOC,GACD,OAAO,iBAAS,YAAY,MAAM,OAAO,GAAG"}
|
|
@@ -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
|
+
*/ export type { PatternEntry } from "./commands.js";
|
|
16
|
+
export { extractCommands } from "./commands.js";
|
|
17
|
+
export type { DepEntry } from "./deps.js";
|
|
18
|
+
export { extractDeps } from "./deps.js";
|
|
19
|
+
export { extractTagRefs } from "./tags.js";
|
|
20
|
+
//# sourceMappingURL=mod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sources":["../../../src/analyze/mod.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;CAcC,GACD,cAAc,YAAY,wBAA6C;AACvE,SAAS,eAAe,wBAAgD;AACxE,cAAc,QAAQ,oBAA8C;AACpE,SAAS,WAAW,oBAAgD;AACpE,SAAS,cAAc,oBAA6C"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ASTNode } from "../../parser/mod.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 declare function extractTagRefs(root: ASTNode): string[];
|
|
6
|
+
//# sourceMappingURL=tags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tags.d.ts","sources":["../../../src/analyze/tags.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,8BAA8B;AAGnD;;;CAGC,GACD,OAAO,iBAAS,eAAe,MAAM,OAAO,GAAG,MAAM"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { ASTNode } from "../../parser/mod.js";
|
|
2
|
+
/** One frame on the iteration stack — pushed by iter(), map(), @dolist, etc. */ export interface IterFrame {
|
|
3
|
+
item: string;
|
|
4
|
+
index: number;
|
|
5
|
+
}
|
|
6
|
+
/** A custom substitution handler registered via `EvalEngine.registerSub()`. */ export type SubHandlerFn = (code: string, ctx: EvalContext) => Promise<string> | string;
|
|
7
|
+
/**
|
|
8
|
+
* A fallback handler called when an `@command` is executed but no specific
|
|
9
|
+
* handler is registered for that command name.
|
|
10
|
+
*/ export type CommandFallbackFn = (name: string, switches: string[], object: string | null, value: string | null, ctx: EvalContext, engine: IEvalEngine) => Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Runtime state threaded through every eval call.
|
|
13
|
+
*
|
|
14
|
+
* `registers` is intentionally mutable — `setq()` writes to it and subsequent
|
|
15
|
+
* reads within the same attribute eval see the updated value.
|
|
16
|
+
*/ export interface EvalContext {
|
|
17
|
+
/** UUID of the enacting object — %# */ enactor: string;
|
|
18
|
+
/** UUID of the executing object — %! */ executor: string;
|
|
19
|
+
/** UUID of the calling object — %@ (null at the top level) */ caller: string | null;
|
|
20
|
+
/** Positional arguments — %0 through %9 */ args: string[];
|
|
21
|
+
/** Named registers — %q<name>. setq() mutates this map. */ registers: Map<string, string>;
|
|
22
|
+
/** Iteration stack — ## and #@ resolve from iterStack[0] */ iterStack: IterFrame[];
|
|
23
|
+
/** Current recursion depth (incremented on each u() call) */ depth: number;
|
|
24
|
+
/** Maximum allowed recursion depth before returning #-1 error */ maxDepth: number;
|
|
25
|
+
/** Maximum total output length per evalString call (default 65 536) */ maxOutputLen: number;
|
|
26
|
+
/** Optional cancellation signal */ signal?: AbortSignal;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create a default {@link EvalContext} with safe fallback values.
|
|
30
|
+
*
|
|
31
|
+
* Provide at minimum `enactor` and `executor` (usually the same UUID for
|
|
32
|
+
* top-level evaluations). All other fields default to safe empty values and a
|
|
33
|
+
* recursion limit of 100.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* const ctx = makeContext({ enactor: "player-uuid", executor: "player-uuid" });
|
|
37
|
+
*/ export declare function makeContext(partial: Partial<EvalContext> & Pick<EvalContext, "enactor" | "executor">): EvalContext;
|
|
38
|
+
/**
|
|
39
|
+
* A lazily-evaluated function argument.
|
|
40
|
+
* Call it to evaluate the underlying AST node in the current context.
|
|
41
|
+
* Pass a partial context override (e.g. `{ iterStack: [...] }`) to temporarily
|
|
42
|
+
* change evaluation state — used by iter() to set ## and #@.
|
|
43
|
+
*/ export type EvalThunk = (ctxOverride?: Partial<EvalContext>) => Promise<string>;
|
|
44
|
+
/**
|
|
45
|
+
* Minimal read-only interface to the game database.
|
|
46
|
+
* Implement this in the host application and pass it to EvalEngine.
|
|
47
|
+
*/ export interface ObjectAccessor {
|
|
48
|
+
/** Read a named attribute from an object. Returns `null` if the attribute is absent. */ getAttr(objectId: string, attr: string): Promise<string | null>;
|
|
49
|
+
/** Resolve a target expression (`"me"`, `"#uuid"`, `"Name"`) to an object UUID. Returns `null` if not found. */ resolveTarget(from: string, expr: string): Promise<string | null>;
|
|
50
|
+
/** Return the display name of an object. */ getName(objectId: string): Promise<string>;
|
|
51
|
+
/** Return `true` if the object has the named flag. */ hasFlag(objectId: string, flag: string): Promise<boolean>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A registered softcode function.
|
|
55
|
+
*
|
|
56
|
+
* When `eval` is "eager" (default), all arguments are evaluated before `exec`
|
|
57
|
+
* is called and `args` contains `string[]`.
|
|
58
|
+
*
|
|
59
|
+
* When `eval` is "lazy", `args` contains `EvalThunk[]`. The function calls
|
|
60
|
+
* only the thunks it needs (e.g. `if()` evaluates only the taken branch).
|
|
61
|
+
*/ export interface FunctionImpl {
|
|
62
|
+
/** Argument evaluation strategy. `"eager"` (default) pre-evaluates all args; `"lazy"` passes thunks. */ eval?: "eager" | "lazy";
|
|
63
|
+
/** Minimum number of arguments required; fewer returns a `#-1` error. */ minArgs: number;
|
|
64
|
+
/** Maximum number of arguments accepted; more returns a `#-1` error. Use `Infinity` for variadic. */ maxArgs: number;
|
|
65
|
+
/** The function implementation. Receives `string[]` when eager, `EvalThunk[]` when lazy. */ exec: (args: string[] | EvalThunk[], ctx: EvalContext, engine: IEvalEngine) => Promise<string> | string;
|
|
66
|
+
}
|
|
67
|
+
/** A registered `@command` handler (e.g. `@pemit`, `@trigger`). */ export interface CommandImpl {
|
|
68
|
+
/** Execute the command. `switches` are the `/switch` tokens; `object` and `value` are the two sides of `=`. */ exec: (switches: string[], object: string | null, value: string | null, ctx: EvalContext, engine: IEvalEngine) => Promise<void>;
|
|
69
|
+
}
|
|
70
|
+
/** Public interface of EvalEngine, used in function/command signatures. */ export interface IEvalEngine {
|
|
71
|
+
/** The host-provided database accessor used by DB stdlib functions. */ readonly accessor: ObjectAccessor;
|
|
72
|
+
/** Register a softcode function (e.g. `add`, `u`) by name. */ registerFunction(name: string, impl: FunctionImpl): this;
|
|
73
|
+
/** Register a softcode `@command` handler by name. */ registerCommand(name: string, impl: CommandImpl): this;
|
|
74
|
+
/**
|
|
75
|
+
* Register a custom `%<code>` substitution handler.
|
|
76
|
+
* Custom handlers are checked before built-in substitutions.
|
|
77
|
+
*/ registerSub(match: string | ((code: string) => boolean), fn: SubHandlerFn): this;
|
|
78
|
+
/**
|
|
79
|
+
* Register a fallback handler for `@commands` with no specific handler registered.
|
|
80
|
+
*/ registerCommandFallback(fn: CommandFallbackFn): this;
|
|
81
|
+
/** Evaluate an AST node to a string. */ eval(node: ASTNode, ctx: EvalContext): Promise<string>;
|
|
82
|
+
/** Execute a node for its side effects (commands). */ exec(node: ASTNode, ctx: EvalContext): Promise<void>;
|
|
83
|
+
/** Parse and evaluate a raw softcode string. */ evalString(source: string, ctx: EvalContext): Promise<string>;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sources":["../../../src/eval/context.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,8BAA8B;AAInD,8EAA8E,GAC9E,iBAAiB;EACf,MAAO,MAAM;EACb,OAAO,MAAM;;AAKf,6EAA6E,GAC7E,YAAY,gBAAgB,MAAM,MAAM,EAAE,KAAK,gBAAgB,QAAQ,MAAM,IAAI,MAAM;AAIvF;;;CAGC,GACD,YAAY,qBACV,MAAU,MAAM,EAChB,UAAU,MAAM,IAChB,QAAU,MAAM,GAAG,IAAI,EACvB,OAAU,MAAM,GAAG,IAAI,EACvB,KAAU,aACV,QAAU,gBACP,QAAQ,IAAI;AAIjB;;;;;CAKC,GACD,iBAAiB;EACf,qCAAqC,GACrC,SAAW,MAAM;EACjB,sCAAsC,GACtC,UAAW,MAAM;EACjB,4DAA4D,GAC5D,QAAW,MAAM,GAAG,IAAI;EACxB,yCAAyC,GACzC,MAAW,MAAM;EACjB,0DAA0D,GAC1D,WAAW,IAAI,MAAM,EAAE,MAAM;EAC7B,0DAA0D,GAC1D,WAAW;EACX,2DAA2D,GAC3D,OAAW,MAAM;EACjB,+DAA+D,GAC/D,UAAc,MAAM;EACpB,qEAAqE,GACrE,cAAc,MAAM;EACpB,iCAAiC,GACjC,SAAW;;AAGb;;;;;;;;;CASC,GACD,OAAO,iBAAS,YACd,SAAS,QAAQ,eAAe,KAAK,aAAa,YAAY,WAAW,GACxE;AAeH;;;;;CAKC,GACD,YAAY,aAAa,cAAc,QAAQ,iBAAiB,QAAQ,MAAM;AAI9E;;;CAGC,GACD,iBAAiB;EACf,sFAAsF,GACtF,QAAQ,UAAU,MAAM,EAAE,MAAM,MAAM,GAAG,QAAQ,MAAM,GAAG,IAAI;EAC9D,8GAA8G,GAC9G,cAAc,MAAM,MAAM,EAAE,MAAM,MAAM,GAAG,QAAQ,MAAM,GAAG,IAAI;EAChE,0CAA0C,GAC1C,QAAQ,UAAU,MAAM,GAAG,QAAQ,MAAM;EACzC,oDAAoD,GACpD,QAAQ,UAAU,MAAM,EAAE,MAAM,MAAM,GAAG,QAAQ,OAAO;;AAK1D;;;;;;;;CAQC,GACD,iBAAiB;EACf,sGAAsG,GACtG,OAAS,UAAU;EACnB,uEAAuE,GACvE,SAAS,MAAM;EACf,mGAAmG,GACnG,SAAS,MAAM;EACf,0FAA0F,GAC1F,OACE,MAAQ,MAAM,KAAK,aACnB,KAAQ,aACR,QAAQ,gBACL,QAAQ,MAAM,IAAI,MAAM;;AAG/B,iEAAiE,GACjE,iBAAiB;EACf,6GAA6G,GAC7G,OACE,UAAU,MAAM,IAChB,QAAU,MAAM,GAAG,IAAI,EACvB,OAAU,MAAM,GAAG,IAAI,EACvB,KAAU,aACV,QAAU,gBACP,QAAQ,IAAI;;AAKnB,yEAAyE,GACzE,iBAAiB;EACf,qEAAqE,YAC5D,UAAU;EACnB,4DAA4D,GAC5D,iBAAiB,MAAM,MAAM,EAAE,MAAM,eAAe,IAAI;EACxD,oDAAoD,GACpD,gBAAgB,MAAM,MAAM,EAAE,MAAM,cAAc,IAAI;EACtD;;;GAGC,GACD,YAAY,OAAO,MAAM,KAAK,MAAM,MAAM,KAAK,OAAO,GAAG,IAAI,eAAe,IAAI;EAChF;;GAEC,GACD,wBAAwB,IAAI,oBAAoB,IAAI;EACpD,sCAAsC,GACtC,KAAK,MAAM,SAAS,KAAK,cAAc,QAAQ,MAAM;EACrD,oDAAoD,GACpD,KAAK,MAAM,SAAS,KAAK,cAAc,QAAQ,IAAI;EACnD,8CAA8C,GAC9C,WAAW,QAAQ,MAAM,EAAE,KAAK,cAAc,QAAQ,MAAM"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ASTNode } from "../../parser/mod.js";
|
|
2
|
+
import type { EvalContext, FunctionImpl, CommandImpl, ObjectAccessor, IEvalEngine, SubHandlerFn, CommandFallbackFn } from "./context.js";
|
|
3
|
+
/**
|
|
4
|
+
* AST-based softcode evaluator.
|
|
5
|
+
*
|
|
6
|
+
* Register functions and commands, then call `evalString()` to evaluate a
|
|
7
|
+
* raw softcode string or `eval()` to evaluate an already-parsed node.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const engine = new EvalEngine(myAccessor);
|
|
11
|
+
* registerStdlib(engine);
|
|
12
|
+
* engine.registerFunction("u", { eval: "lazy", minArgs: 1, maxArgs: Infinity, exec: uImpl });
|
|
13
|
+
* const result = await engine.evalString("[add(1,2)]", ctx);
|
|
14
|
+
* // → "3"
|
|
15
|
+
*/ export declare class EvalEngine implements IEvalEngine {
|
|
16
|
+
readonly accessor: ObjectAccessor;
|
|
17
|
+
private readonly functions: any;
|
|
18
|
+
private readonly commands: any;
|
|
19
|
+
private readonly subHandlers: any;
|
|
20
|
+
private fallbackCommand?: any;
|
|
21
|
+
constructor(/** The host-provided database accessor (passed to DB stdlib functions). */ accessor: ObjectAccessor);
|
|
22
|
+
/** Register a softcode function by name (case-insensitive). Returns `this` for chaining. */ registerFunction(name: string, impl: FunctionImpl): this;
|
|
23
|
+
/** Register a `@command` handler by name (case-insensitive). Returns `this` for chaining. */ registerCommand(name: string, impl: CommandImpl): this;
|
|
24
|
+
/**
|
|
25
|
+
* Register a custom `%<code>` substitution handler.
|
|
26
|
+
*
|
|
27
|
+
* Custom handlers are checked **before** built-in substitutions, so you can
|
|
28
|
+
* override any built-in code. `match` is either an exact code string (e.g.
|
|
29
|
+
* `"s"` for `%s`) or a predicate (e.g. `code => code.startsWith("V")` for
|
|
30
|
+
* `%Va`–`%Vz`).
|
|
31
|
+
*
|
|
32
|
+
* @returns `this` for chaining.
|
|
33
|
+
*/ registerSub(match: string | ((code: string) => boolean), fn: SubHandlerFn): this;
|
|
34
|
+
/**
|
|
35
|
+
* Register a fallback handler for `@commands` that have no specific handler registered.
|
|
36
|
+
*
|
|
37
|
+
* @returns `this` for chaining.
|
|
38
|
+
*/ registerCommandFallback(fn: CommandFallbackFn): this;
|
|
39
|
+
/** Parse and evaluate a raw softcode string. */ evalString(source: string, ctx: EvalContext): Promise<string>;
|
|
40
|
+
/** Evaluate a node to a string. */ eval(node: ASTNode, ctx: EvalContext): Promise<string>;
|
|
41
|
+
/** Execute a node for its side effects (commands). */ exec(node: ASTNode, ctx: EvalContext): Promise<void>;
|
|
42
|
+
private evalParts: any;
|
|
43
|
+
private evalFunction: any;
|
|
44
|
+
private evalSub: any;
|
|
45
|
+
private evalSpecialVar: any;
|
|
46
|
+
private resolveLocation: any;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sources":["../../../src/eval/engine.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,8BAAkC;AAEvD,cACE,WAAW,EACX,YAAY,EAAE,WAAW,EACzB,cAAc,EAAE,WAAW,EAChB,YAAY,EAAE,iBAAiB,uBACtB;AAItB;;;;;;;;;;;;CAYC,GACD,OAAO,cAAM,sBAAsB;WAQtB,UAAU;EAPrB,iBAAiB,eAA8C;EAC/D,iBAAiB,cAA6C;EAC9D,iBAAiB,iBAA2F;EAC5G,QAAQ,sBAAoC;EAE5C,YACE,yEAAyE,GACzE,AAAS,UAAU,cAAc;EAGnC,0FAA0F,GAC1F,iBAAiB,MAAM,MAAM,EAAE,MAAM,YAAY,GAAG,IAAI;EAKxD,2FAA2F,GAC3F,gBAAgB,MAAM,MAAM,EAAE,MAAM,WAAW,GAAG,IAAI;EAKtD;;;;;;;;;GASC,GACD,YACE,OAAO,MAAM,KAAK,MAAM,MAAM,KAAK,OAAO,CAAC,EAC3C,IAAI,YAAY,GACf,IAAI;EAKP;;;;GAIC,GACD,wBAAwB,IAAI,iBAAiB,GAAG,IAAI;EAKpD,8CAA8C,GAC9C,AAAM,WAAW,QAAQ,MAAM,EAAE,KAAK,WAAW,GAAG,QAAQ,MAAM;EAOlE,iCAAiC,GACjC,AAAM,KAAK,MAAM,OAAO,EAAE,KAAK,WAAW,GAAG,QAAQ,MAAM;EA8C3D,oDAAoD,GACpD,AAAM,KAAK,MAAM,OAAO,EAAE,KAAK,WAAW,GAAG,QAAQ,IAAI;UA0C3C;UAYA;UA8BA;UA4CN;UAQM;AAQhB"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* AST-based softcode evaluator: `EvalEngine`, `makeContext()`, `registerStdlib()`,
|
|
4
|
+
* and the full type vocabulary for contexts, accessors, and function registrations.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { EvalEngine, makeContext, registerStdlib } from "@ursamu/mushcode/eval";
|
|
9
|
+
*
|
|
10
|
+
* const engine = new EvalEngine({
|
|
11
|
+
* getAttr: async (_id, _attr) => null,
|
|
12
|
+
* resolveTarget: async (_from, expr) => expr === "me" ? "player-uuid" : null,
|
|
13
|
+
* getName: async (_id) => "Tester",
|
|
14
|
+
* hasFlag: async (_id, _flag) => false,
|
|
15
|
+
* });
|
|
16
|
+
* registerStdlib(engine);
|
|
17
|
+
*
|
|
18
|
+
* const ctx = makeContext({ enactor: "player-uuid", executor: "player-uuid" });
|
|
19
|
+
* const result = await engine.evalString("[add(1,2)] [capstr(hello)]", ctx);
|
|
20
|
+
* console.log(result); // "3 Hello"
|
|
21
|
+
* ```
|
|
22
|
+
*/ export { EvalEngine } from "./engine.js";
|
|
23
|
+
export { makeContext } from "./context.js";
|
|
24
|
+
export { registerStdlib } from "./stdlib/mod.js";
|
|
25
|
+
export type { EvalContext, EvalThunk, ObjectAccessor, IEvalEngine, FunctionImpl, CommandImpl, IterFrame, SubHandlerFn, CommandFallbackFn } from "./context.js";
|
|
26
|
+
//# sourceMappingURL=mod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sources":["../../../src/eval/mod.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;CAqBC,GACD,SAAS,UAAU,sBAA+B;AAClD,SAAS,WAAW,uBAA+B;AACnD,SAAS,cAAc,0BAA+B;AACtD,cACE,WAAW,EAAE,SAAS,EACtB,cAAc,EAAE,WAAW,EAC3B,YAAY,EAAE,WAAW,EACzB,SAAS,EAAE,YAAY,EAAE,iBAAiB,uBACO"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sources":["../../../../src/eval/stdlib/mod.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,wBAAwB;AASjD,uEAAuE,GACvE,OAAO,iBAAS,eAAe,QAAQ,WAAW,GAAG,IAAI"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* Static analysis for softcode: `lint()` runs built-in rules and returns
|
|
4
|
+
* `Diagnostic` findings with severity, rule ID, and the offending AST node.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { parse } from "@ursamu/mushcode/parse";
|
|
9
|
+
* import { lint } from "@ursamu/mushcode/lint";
|
|
10
|
+
*
|
|
11
|
+
* const ast = parse("$finger:@pemit %#=[u(me/FN)]");
|
|
12
|
+
* const diags = lint(ast);
|
|
13
|
+
* diags.forEach(d => console.log(`[${d.severity}] ${d.rule}: ${d.message}`));
|
|
14
|
+
* ```
|
|
15
|
+
*/ import type { ASTNode } from "../../parser/mod.js";
|
|
16
|
+
/** Severity level of a lint diagnostic. */ export type Severity = "error" | "warning" | "info";
|
|
17
|
+
/** A single lint finding produced by a rule. */ export interface Diagnostic {
|
|
18
|
+
/** Identifier for the rule that produced this diagnostic. */ rule: string;
|
|
19
|
+
/** How serious the finding is. */ severity: Severity;
|
|
20
|
+
/** Human-readable description of the issue. */ message: string;
|
|
21
|
+
/** The AST node most closely associated with the issue. */ node: ASTNode;
|
|
22
|
+
}
|
|
23
|
+
/** Options passed to the {@link lint} function. */ export interface LintOptions {
|
|
24
|
+
/** Whitelist of rule IDs to run. Omit to run all rules. */ rules?: string[];
|
|
25
|
+
}
|
|
26
|
+
/** All built-in rule IDs. Pass a subset to `LintOptions.rules` to enable only those rules. */ export declare const RULES: readonly ["missing-wildcard", "iter-var-outside-iter", "arg-count", "register-before-set"];
|
|
27
|
+
/** Union type of every known rule ID string. */ export type RuleId = (typeof RULES)[number];
|
|
28
|
+
/**
|
|
29
|
+
* Run static analysis on an AST and return an array of diagnostics.
|
|
30
|
+
*
|
|
31
|
+
* Rules are applied at every DollarPattern/ListenPattern/FunctionCall/… node
|
|
32
|
+
* anywhere in the tree, so this works correctly on CommandList roots too.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* const diags = lint(parse("$+finger *:@pemit %#=[u(me/FN_FINGER,%0)]"));
|
|
36
|
+
* diags.forEach(d => console.log(`[${d.severity}] ${d.rule}: ${d.message}`));
|
|
37
|
+
*/ export declare function lint(root: ASTNode, opts?: LintOptions): Diagnostic[];
|
|
38
|
+
//# sourceMappingURL=mod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sources":["../../../src/lint/mod.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;CAcC,GACD,cAAc,OAAO,8BAA6C;AASlE,yCAAyC,GACzC,YAAY,WAAW,UAAU,YAAY;AAE7C,8CAA8C,GAC9C,iBAAiB;EACf,2DAA2D,GAC3D,MAAU,MAAM;EAChB,gCAAgC,GAChC,UAAU;EACV,6CAA6C,GAC7C,SAAU,MAAM;EAChB,yDAAyD,GACzD,MAAU;;AAGZ,iDAAiD,GACjD,iBAAiB;EACf,0DAA0D,GAC1D,QAAQ,MAAM;;AAKhB,6FAA6F,GAC7F,OAAO,cAAM,iBACX,oBACA,yBACA,aACA,uBACS;AAEX,8CAA8C,GAC9C,YAAY,iBAAiB,OAAO,MAAM;AAI1C;;;;;;;;;CASC,GACD,OAAO,iBAAS,KAAK,MAAM,OAAO,EAAE,OAAO,WAAW,GAAG"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* Converts an AST back to a canonical softcode string via `print()`.
|
|
4
|
+
* Supports compact (semicolon-separated) and pretty (newline-separated) modes.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { parse } from "@ursamu/mushcode/parse";
|
|
9
|
+
* import { print } from "@ursamu/mushcode/print";
|
|
10
|
+
*
|
|
11
|
+
* const ast = parse("@pemit %#=Hello;@pemit %#=World");
|
|
12
|
+
* console.log(print(ast, { mode: "pretty" }));
|
|
13
|
+
* // @pemit %#=Hello
|
|
14
|
+
* // @pemit %#=World
|
|
15
|
+
* ```
|
|
16
|
+
*/ export type { PrintMode, PrintOptions } from "./printer.js";
|
|
17
|
+
export { print } from "./printer.js";
|
|
18
|
+
//# sourceMappingURL=mod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sources":["../../../src/print/mod.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD,cAAc,SAAS,EAAE,YAAY,uBAAuB;AAC5D,SAAS,KAAK,uBAA8C"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ASTNode } from "../../parser/mod.js";
|
|
2
|
+
/** Controls how `CommandList` separators are rendered in the output. */ export type PrintMode = "compact" | "pretty";
|
|
3
|
+
/** Options for the {@link print} function. */ export interface PrintOptions {
|
|
4
|
+
/** "compact" (default): CommandList joined by ";".
|
|
5
|
+
* "pretty": CommandList joined by ";\n". */ mode?: PrintMode;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Convert an AST node back to a canonical softcode string.
|
|
9
|
+
*
|
|
10
|
+
* The output is semantically equivalent to the original source but whitespace
|
|
11
|
+
* may be normalised (e.g. `@pemit%#=x` becomes `@pemit %#=x`).
|
|
12
|
+
* Lock-expression nodes (LockOr, LockAnd, …) produced by the "LockExpr" start
|
|
13
|
+
* rule are printed via the lock printer.
|
|
14
|
+
*/ export declare function print(node: ASTNode, opts?: PrintOptions): string;
|
|
15
|
+
//# sourceMappingURL=printer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"printer.d.ts","sources":["../../../src/print/printer.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,8BAA8B;AAKnD,sEAAsE,GACtE,YAAY,YAAY,YAAY;AAEpC,4CAA4C,GAC5C,iBAAiB;EACf;6CAC2C,GAC3C,OAAO;;AAKT;;;;;;;CAOC,GACD,OAAO,iBAAS,MAAM,MAAM,OAAO,EAAE,OAAO,YAAY,GAAG,MAAM"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* Depth-first AST traversal and tree transformation utilities:
|
|
4
|
+
* `walk()`, `transform()`, `findAll()`, `findFirst()`, `findFirstOrNull()`.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { parse } from "@ursamu/mushcode/parse";
|
|
9
|
+
* import { findAll } from "@ursamu/mushcode/traverse";
|
|
10
|
+
*
|
|
11
|
+
* const ast = parse("[add(1,[mul(2,3)])]");
|
|
12
|
+
* const calls = findAll(ast, "FunctionCall");
|
|
13
|
+
* console.log(calls.map(n => n.name)); // ["add", "mul"]
|
|
14
|
+
* ```
|
|
15
|
+
*/ export type { Visitor } from "./walk.js";
|
|
16
|
+
export { walk, findAll, findFirst, findFirstOrNull } from "./walk.js";
|
|
17
|
+
export type { Transformer } from "./transform.js";
|
|
18
|
+
export { transform } from "./transform.js";
|
|
19
|
+
//# sourceMappingURL=mod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sources":["../../../src/traverse/mod.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;CAcC,GACD,cAAc,OAAO,oBAAwD;AAC7E,SAAS,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,eAAe,oBAA2B;AAC7E,cAAc,WAAW,yBAAyD;AAClF,SAAS,SAAS,yBAAgE"}
|