roll-parser 3.0.0-beta.0 → 3.0.0

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 (159) hide show
  1. package/CHANGELOG.md +107 -9
  2. package/MIGRATION.md +147 -0
  3. package/README.md +960 -154
  4. package/dist/cli/args.d.ts +1 -0
  5. package/dist/cli/args.d.ts.map +1 -1
  6. package/dist/cli/args.js +81 -0
  7. package/dist/cli/args.js.map +1 -0
  8. package/dist/cli/format.d.ts +15 -3
  9. package/dist/cli/format.d.ts.map +1 -1
  10. package/dist/cli/format.js +17 -0
  11. package/dist/cli/format.js.map +1 -0
  12. package/dist/cli/index.d.ts +3 -0
  13. package/dist/cli/index.d.ts.map +1 -1
  14. package/dist/cli/index.js +14 -0
  15. package/dist/cli/index.js.map +1 -0
  16. package/dist/cli/main.d.ts +36 -0
  17. package/dist/cli/main.d.ts.map +1 -0
  18. package/dist/cli/main.js +83 -0
  19. package/dist/cli/main.js.map +1 -0
  20. package/dist/errors.d.ts +332 -17
  21. package/dist/errors.d.ts.map +1 -1
  22. package/dist/errors.js +141 -0
  23. package/dist/errors.js.map +1 -0
  24. package/dist/evaluator/die.d.ts +26 -0
  25. package/dist/evaluator/die.d.ts.map +1 -0
  26. package/dist/evaluator/die.js +19 -0
  27. package/dist/evaluator/die.js.map +1 -0
  28. package/dist/evaluator/env.d.ts +58 -0
  29. package/dist/evaluator/env.d.ts.map +1 -0
  30. package/dist/evaluator/env.js +11 -0
  31. package/dist/evaluator/env.js.map +1 -0
  32. package/dist/evaluator/evaluator.d.ts +41 -75
  33. package/dist/evaluator/evaluator.d.ts.map +1 -1
  34. package/dist/evaluator/evaluator.js +906 -0
  35. package/dist/evaluator/evaluator.js.map +1 -0
  36. package/dist/evaluator/modifiers/compare.js +15 -0
  37. package/dist/evaluator/modifiers/compare.js.map +1 -0
  38. package/dist/evaluator/modifiers/crit-threshold.d.ts +0 -1
  39. package/dist/evaluator/modifiers/crit-threshold.d.ts.map +1 -1
  40. package/dist/evaluator/modifiers/crit-threshold.js +23 -0
  41. package/dist/evaluator/modifiers/crit-threshold.js.map +1 -0
  42. package/dist/evaluator/modifiers/die-bound.d.ts +26 -0
  43. package/dist/evaluator/modifiers/die-bound.d.ts.map +1 -0
  44. package/dist/evaluator/modifiers/die-bound.js +14 -0
  45. package/dist/evaluator/modifiers/die-bound.js.map +1 -0
  46. package/dist/evaluator/modifiers/explode.d.ts +13 -5
  47. package/dist/evaluator/modifiers/explode.d.ts.map +1 -1
  48. package/dist/evaluator/modifiers/explode.js +103 -0
  49. package/dist/evaluator/modifiers/explode.js.map +1 -0
  50. package/dist/evaluator/modifiers/flags.d.ts +37 -0
  51. package/dist/evaluator/modifiers/flags.d.ts.map +1 -0
  52. package/dist/evaluator/modifiers/flags.js +18 -0
  53. package/dist/evaluator/modifiers/flags.js.map +1 -0
  54. package/dist/evaluator/modifiers/keep-drop.d.ts +12 -28
  55. package/dist/evaluator/modifiers/keep-drop.d.ts.map +1 -1
  56. package/dist/evaluator/modifiers/keep-drop.js +82 -0
  57. package/dist/evaluator/modifiers/keep-drop.js.map +1 -0
  58. package/dist/evaluator/modifiers/reroll.d.ts +12 -4
  59. package/dist/evaluator/modifiers/reroll.d.ts.map +1 -1
  60. package/dist/evaluator/modifiers/reroll.js +62 -0
  61. package/dist/evaluator/modifiers/reroll.js.map +1 -0
  62. package/dist/evaluator/modifiers/sort.d.ts +4 -0
  63. package/dist/evaluator/modifiers/sort.d.ts.map +1 -1
  64. package/dist/evaluator/modifiers/sort.js +13 -0
  65. package/dist/evaluator/modifiers/sort.js.map +1 -0
  66. package/dist/evaluator/modifiers/success-count.d.ts +2 -6
  67. package/dist/evaluator/modifiers/success-count.d.ts.map +1 -1
  68. package/dist/evaluator/modifiers/success-count.js +24 -0
  69. package/dist/evaluator/modifiers/success-count.js.map +1 -0
  70. package/dist/index.d.ts +33 -11
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +12 -2560
  73. package/dist/index.js.map +1 -26
  74. package/dist/lexer/lexer.d.ts +50 -5
  75. package/dist/lexer/lexer.d.ts.map +1 -1
  76. package/dist/lexer/lexer.js +260 -0
  77. package/dist/lexer/lexer.js.map +1 -0
  78. package/dist/lexer/tokens.d.ts +31 -6
  79. package/dist/lexer/tokens.d.ts.map +1 -1
  80. package/dist/lexer/tokens.js +42 -0
  81. package/dist/lexer/tokens.js.map +1 -0
  82. package/dist/parser/ast.d.ts +314 -160
  83. package/dist/parser/ast.d.ts.map +1 -1
  84. package/dist/parser/ast.js +52 -0
  85. package/dist/parser/ast.js.map +1 -0
  86. package/dist/parser/guards.d.ts +106 -0
  87. package/dist/parser/guards.d.ts.map +1 -0
  88. package/dist/parser/guards.js +121 -0
  89. package/dist/parser/guards.js.map +1 -0
  90. package/dist/parser/parser.d.ts +118 -14
  91. package/dist/parser/parser.d.ts.map +1 -1
  92. package/dist/parser/parser.js +751 -0
  93. package/dist/parser/parser.js.map +1 -0
  94. package/dist/rng/mock.d.ts +73 -12
  95. package/dist/rng/mock.d.ts.map +1 -1
  96. package/dist/rng/mock.js +30 -0
  97. package/dist/rng/mock.js.map +1 -0
  98. package/dist/rng/seeded.d.ts +141 -9
  99. package/dist/rng/seeded.d.ts.map +1 -1
  100. package/dist/rng/seeded.js +138 -0
  101. package/dist/rng/seeded.js.map +1 -0
  102. package/dist/rng/types.d.ts +57 -0
  103. package/dist/rng/types.d.ts.map +1 -1
  104. package/dist/rng/types.js +2 -0
  105. package/dist/rng/types.js.map +1 -0
  106. package/dist/roll.d.ts +58 -28
  107. package/dist/roll.d.ts.map +1 -1
  108. package/dist/roll.js +8 -0
  109. package/dist/roll.js.map +1 -0
  110. package/dist/testing.d.ts +5 -4
  111. package/dist/testing.d.ts.map +1 -1
  112. package/dist/testing.js +2 -41
  113. package/dist/testing.js.map +1 -11
  114. package/dist/types.d.ts +306 -44
  115. package/dist/types.d.ts.map +1 -1
  116. package/dist/types.js +8 -0
  117. package/dist/types.js.map +1 -0
  118. package/dist/version.d.ts +2 -0
  119. package/dist/version.d.ts.map +1 -0
  120. package/dist/version.js +2 -0
  121. package/dist/version.js.map +1 -0
  122. package/package.json +83 -34
  123. package/src/cli/args.ts +66 -10
  124. package/src/cli/format.ts +22 -3
  125. package/src/cli/index.ts +27 -84
  126. package/src/cli/main.ts +129 -0
  127. package/src/errors.ts +480 -27
  128. package/src/evaluator/die.ts +50 -0
  129. package/src/evaluator/env.ts +73 -0
  130. package/src/evaluator/evaluator.ts +653 -421
  131. package/src/evaluator/modifiers/crit-threshold.ts +3 -6
  132. package/src/evaluator/modifiers/die-bound.ts +39 -0
  133. package/src/evaluator/modifiers/explode.ts +60 -58
  134. package/src/evaluator/modifiers/flags.ts +61 -0
  135. package/src/evaluator/modifiers/keep-drop.ts +124 -126
  136. package/src/evaluator/modifiers/reroll.ts +28 -49
  137. package/src/evaluator/modifiers/sort.ts +14 -1
  138. package/src/evaluator/modifiers/success-count.ts +5 -8
  139. package/src/index.ts +56 -35
  140. package/src/lexer/lexer.ts +107 -34
  141. package/src/lexer/tokens.ts +31 -6
  142. package/src/parser/ast.ts +323 -341
  143. package/src/parser/guards.ts +248 -0
  144. package/src/parser/parser.ts +419 -242
  145. package/src/rng/mock.ts +74 -13
  146. package/src/rng/seeded.ts +299 -64
  147. package/src/rng/types.ts +57 -0
  148. package/src/roll.ts +64 -47
  149. package/src/testing.ts +5 -9
  150. package/src/types.ts +310 -43
  151. package/src/version.ts +2 -0
  152. package/dist/cli.js +0 -2608
  153. package/dist/cli.js.map +0 -28
  154. package/dist/evaluator/index.d.ts +0 -8
  155. package/dist/evaluator/index.d.ts.map +0 -1
  156. package/dist/rng/index.d.ts +0 -8
  157. package/dist/rng/index.d.ts.map +0 -1
  158. package/src/evaluator/index.ts +0 -14
  159. package/src/rng/index.ts +0 -8
@@ -3,71 +3,32 @@
3
3
  *
4
4
  * @module evaluator/evaluator
5
5
  */
6
- import type { RollParserErrorCode } from '../errors.js';
7
- import { RollParserError } from '../errors.js';
6
+ import { EvaluatorError } from '../errors.js';
8
7
  import type { ASTNode } from '../parser/ast.js';
9
8
  import type { RNG } from '../rng/types.js';
10
9
  import type { DieResult, EvaluateOptions, RollResult } from '../types.js';
11
10
  import { DegreeOfSuccess } from '../types.js';
12
11
  import { DEFAULT_MAX_EXPLODE_ITERATIONS } from './modifiers/explode.js';
13
12
  import { DEFAULT_MAX_REROLL_ITERATIONS } from './modifiers/reroll.js';
13
+ export { EvaluatorError };
14
14
  /**
15
- * Error thrown during AST evaluation.
15
+ * Default value of `EvaluationOptions.maxDice`: the number of dice a single
16
+ * evaluation may roll before `DICE_LIMIT_EXCEEDED` is thrown.
17
+ *
18
+ * Counted across the whole expression, not per pool, so `6000d6+6000d6`
19
+ * breaches it. Includes dice rolled by explosions, rerolls, and
20
+ * meta-expressions.
21
+ *
22
+ * @category Limits
16
23
  */
17
- export declare class EvaluatorError extends RollParserError {
18
- readonly nodeType: string | undefined;
19
- /**
20
- * Source span of the tightest AST node that was being evaluated when the
21
- * error was thrown — stamped by `evalNode` on the way up, so the innermost
22
- * node wins. `undefined` when the AST was built without parser spans.
23
- */
24
- start: number | undefined;
25
- end: number | undefined;
26
- constructor(message: string, code: RollParserErrorCode, nodeType?: string);
27
- }
28
- /** Default maximum total dice allowed per evaluation. */
29
24
  export declare const DEFAULT_MAX_DICE = 10000;
30
25
  export { DEFAULT_MAX_EXPLODE_ITERATIONS, DEFAULT_MAX_REROLL_ITERATIONS };
31
- /**
32
- * Per-evaluation shared environment (created once, shared across all branches).
33
- *
34
- * Exported for use by modifier implementations under `./modifiers/*`. Not part
35
- * of the public library API.
36
- */
37
- export type EvalEnv = {
38
- readonly maxDice: number;
39
- readonly maxExplodeIterations: number;
40
- readonly maxRerollIterations: number;
41
- totalDiceRolled: number;
42
- /**
43
- * Set to `true` by `evalSuccessCount`. Propagates through the shared env
44
- * so `evaluate()` can include `successes`/`failures` fields even when no
45
- * die was tagged (impossible threshold).
46
- */
47
- hasSuccessCount: boolean;
48
- /**
49
- * `true` while the evaluator is inside a `VersusNode`'s roll or DC
50
- * sub-evaluation. `evalVersus` rejects nesting via this flag — catches
51
- * paren-nested versus (`1d20 vs (5 vs 3)`) that slip past the parser's
52
- * left-chain check.
53
- */
54
- insideVersus: boolean;
55
- /**
56
- * User-supplied variable map for `@name` / `@{name}` references. Always
57
- * defined — `evaluate()` defaults to an empty object so lookups can be
58
- * branch-free on presence.
59
- */
60
- readonly context: Readonly<Record<string, number>>;
61
- /**
62
- * Behavior when a referenced variable is missing from `context`. Always
63
- * defined — `evaluate()` defaults to `'throw'`.
64
- */
65
- readonly onMissingVariable: 'throw' | 'zero';
66
- };
67
26
  /**
68
27
  * Per-branch mutable accumulator for tracking rolls and output during recursion.
69
28
  *
70
- * @internal exported for targeted `mergeMetaRolls` tests only; not a public API.
29
+ * Module-level export, deliberately absent from `src/index.ts` the package
30
+ * surface never mentions it. See {@link mergeMetaRolls} for why the export
31
+ * exists at all.
71
32
  */
72
33
  export type EvalContext = {
73
34
  rolls: DieResult[];
@@ -86,36 +47,41 @@ export type EvalContext = {
86
47
  };
87
48
  };
88
49
  /**
89
- * Forwards rolls from a throwaway sub-expression context into the parent
90
- * audit trail, tagging them as `'meta'` + `'dropped'`. Meta dice are dice
91
- * rolled to compute parameters (dice count, sides, threshold, modifier
92
- * count) — they consume RNG and count against `maxDice`, so they must be
93
- * inspectable. Tagging them `'dropped'` keeps totals correct via
94
- * `sumKeptDice`; `'meta'` lets renderers hide them and lets callers
95
- * distinguish them from ordinary pool dice.
50
+ * Evaluates a parsed AST against an {@link RNG} and returns the roll result.
96
51
  *
97
- * `'success'`/`'failure'` tags are stripped here as defense-in-depth against
98
- * a SuccessCount leaking into a meta sub-expression (parser rejects all such
99
- * wrappings; this strip ensures a future parse regression cannot leak tags
100
- * into the top-level `successes`/`failures` scan).
101
- */
102
- /** @internal exported for targeted defense-in-depth tests only. */
103
- export declare function mergeMetaRolls(parent: EvalContext, source: EvalContext): void;
104
- /**
105
- * Evaluates a parsed AST and returns the roll result.
52
+ * The second half of the pipeline {@link roll} is `evaluate(parse(...))`.
53
+ * Call it directly to reuse one AST across many rolls, or to drive a
54
+ * hand-built AST.
55
+ *
56
+ * Unlike `roll`, the RNG is required: `evaluate` never invents a randomness
57
+ * source, so a caller can never accidentally get an unseeded roll.
106
58
  *
107
- * @param ast - The parsed AST node
108
- * @param rng - Random number generator to use for dice rolls
109
- * @param options - Optional evaluation options
110
- * @returns Complete roll result with total and metadata
59
+ * @param ast - The AST to evaluate, from {@link parse} or hand-built
60
+ * @param rng - Randomness source; one `nextInt` call per die
61
+ * @param options - Evaluation limits plus the original `notation` string,
62
+ * which the AST cannot supply
63
+ * @returns Complete {@link RollResult}
64
+ * @throws {EvaluatorError} On a limit breach, division by zero, an undefined
65
+ * variable, or a non-finite total
66
+ * @throws {RollParserError} `INVALID_EVALUATION_LIMIT` when a supplied limit is
67
+ * not an integer in range — raised before any die is rolled
111
68
  *
112
69
  * @example
113
70
  * ```typescript
71
+ * import { evaluate, parse } from 'roll-parser';
72
+ * import { createMockRng } from 'roll-parser/testing';
73
+ *
114
74
  * const ast = parse('2d6+3');
115
- * const rng = new SeededRNG('test');
116
- * const result = evaluate(ast, rng);
117
- * console.log(result.total); // Sum of dice plus 3
75
+ * const result = evaluate(ast, createMockRng([4, 2]), { notation: '2d6+3' });
76
+ * result.total; // 9
77
+ * result.rendered; // '2d6[4, 2] + 3 = 9'
118
78
  * ```
79
+ *
80
+ * Omitting `notation` falls back to the normalized `expression`, which is
81
+ * reconstructed from the AST — so `RollResult.notation` is always a string,
82
+ * just not necessarily the one the user typed.
83
+ *
84
+ * @category Core
119
85
  */
120
86
  export declare function evaluate(ast: ASTNode, rng: RNG, options?: EvaluateOptions): RollResult;
121
87
  //# sourceMappingURL=evaluator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/evaluator/evaluator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EACV,OAAO,EAkBR,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EAEV,SAAS,EACT,eAAe,EAGf,UAAU,EACX,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAKL,8BAA8B,EAC/B,MAAM,wBAAwB,CAAC;AAShC,OAAO,EAGL,6BAA6B,EAC9B,MAAM,uBAAuB,CAAC;AAI/B;;GAEG;AACH,qBAAa,cAAe,SAAQ,eAAe;IACjD,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC;;;;OAIG;IACH,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;gBAEZ,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,CAAC,EAAE,MAAM;CAO1E;AAED,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,QAAS,CAAC;AAEvC,OAAO,EAAE,8BAA8B,EAAE,6BAA6B,EAAE,CAAC;AAEzE;;;;;GAKG;AACH,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,eAAe,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,eAAe,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,YAAY,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD;;;OAGG;IACH,QAAQ,CAAC,iBAAiB,EAAE,OAAO,GAAG,MAAM,CAAC;CAC9C,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB;;;;;OAKG;IACH,cAAc,CAAC,EAAE;QACf,MAAM,EAAE,eAAe,CAAC;QACxB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;QAC5B,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AA+FF;;;;;;;;;;;;;GAaG;AACH,mEAAmE;AACnE,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAa7E;AA8pCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,GAAE,eAAoB,GAAG,UAAU,CAmF1F"}
1
+ {"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/evaluator/evaluator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAiB,cAAc,EAAuC,MAAM,cAAc,CAAC;AAClG,OAAO,KAAK,EACV,OAAO,EAmBR,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EAIV,SAAS,EACT,eAAe,EAKf,UAAU,EACX,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAK9C,OAAO,EAKL,8BAA8B,EAC/B,MAAM,wBAAwB,CAAC;AAQhC,OAAO,EAGL,6BAA6B,EAC9B,MAAM,uBAAuB,CAAC;AAM/B,OAAO,EAAE,cAAc,EAAE,CAAC;AAM1B;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,QAAS,CAAC;AAmCvC,OAAO,EAAE,8BAA8B,EAAE,6BAA6B,EAAE,CAAC;AAMzE;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB;;;;;OAKG;IACH,cAAc,CAAC,EAAE;QACf,MAAM,EAAE,eAAe,CAAC;QACxB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;QAC5B,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AA++CF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,GAAE,eAAoB,GAAG,UAAU,CA4D1F"}