xray16 1.6.3 → 1.6.4

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/README.md CHANGED
@@ -115,17 +115,17 @@ This avoids temporary result locals for patterns like `return condition ? first
115
115
 
116
116
  ### inline_constants
117
117
 
118
- Plugin inlining compile-time constant values of `@inline` JSDoc tagged declarations.\
118
+ Plugin that inlines compile-time constants from declarations tagged with `@inline` or `@virtual`.\
119
119
  Supported targets are enums, module-level `as const` object literals and module-level scalar constants.\
120
- Member accesses are replaced with literal values in place, while original tables are still emitted,
121
- so iteration / reverse mapping / whole-object usages keep working.\
120
+ Values may be literals or expressions that can be folded at build time: arithmetic, string concatenation,
121
+ template literals and references to other constant declarations.\
122
122
  Tagged declarations act as an explicit whitelist and produce build errors when they cannot be inlined.
123
123
 
124
- Values may be literals or expressions foldable on build time - arithmetic, string concatenation,
125
- template literals and references to other constant declarations (enum members, module-level const scalars,
126
- `as const` object properties, whitelisted namespace constants like `math.pi`).\
127
- Runtime-dependent expressions (function calls, mutable object properties, values producing NaN / Infinity)
128
- are rejected with build errors.
124
+ - `@inline` replaces accesses with literal values but still emits the original declaration, so iteration,
125
+ reverse mapping and whole-object usages keep working. Import bindings that are no longer used at runtime
126
+ are stripped; if the target module is proven pure, its `require` is dropped too.
127
+ - `@virtual` includes `@inline` behavior and also removes the declaration from emitted output. Every value
128
+ reference must be computable at build time. Object spreads of virtual objects are expanded to table literals.
129
129
 
130
130
  ```typescript
131
131
  /**
@@ -137,19 +137,16 @@ export const medkits = {
137
137
  } as const;
138
138
 
139
139
  /**
140
- * @inline
140
+ * @virtual
141
141
  */
142
142
  export const TIMEOUT: number = 60 * 1000;
143
143
 
144
- /**
145
- * @inline
146
- */
147
- export const PI_DEGREE: number = math.pi / 180;
148
-
149
144
  // Build time: `medkits.medkit_army` access is emitted as plain "medkit_army" string literal.
150
- // Build time: `TIMEOUT` reference is emitted as 60000, `PI_DEGREE` as 0.017453292519943295.
145
+ // Build time: `TIMEOUT` reference is emitted as 60000 and the declaration is erased from output.
151
146
  ```
152
147
 
148
+ See [src/plugins/inline_constants/README.md](src/plugins/inline_constants/README.md) for full documentation.
149
+
153
150
  ### inject_tracy_zones
154
151
 
155
152
  Plugin designed to work specifically with [tracy profiler](https://github.com/wolfpld/tracy).\
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xray16",
3
- "version": "1.6.3",
3
+ "version": "1.6.4",
4
4
  "author": "Neloreck",
5
5
  "repository": "https://github.com/xray-forge/xray-16-types",
6
6
  "homepage": "https://xray-forge.github.io/xray-16-types/index.html",
@@ -1,14 +1,21 @@
1
1
  import { type Plugin } from "typescript-to-lua";
2
2
  /**
3
- * Plugin that inlines compile-time constant values of `@inline` JSDoc tagged declarations.
3
+ * Plugin that inlines compile-time constants from declarations tagged with `@inline` or `@virtual`.
4
4
  *
5
5
  * Supported targets are enums, module-level `as const` object literals and module-level scalar constants.
6
- * Values may be literals or expressions foldable on build time - arithmetic, string concatenation,
6
+ * Values may be literals or expressions that can be folded at build time: arithmetic, string concatenation,
7
7
  * template literals and references to other constant declarations (enum members, const scalars,
8
8
  * `as const` object properties, whitelisted constants like 'math.pi').
9
- * Tagged declarations act as an explicit whitelist - member accesses are replaced with literal values in place,
10
- * while original tables are still emitted, so iteration / reverse mapping / whole-object usages keep working.
11
- * Tagged declarations that cannot be inlined produce build errors instead of silently emitting property lookups.
9
+ *
10
+ * `@inline` replaces member accesses with literal values while still emitting the original declaration,
11
+ * so iteration, reverse mapping and whole-object usages keep working. Import bindings with no remaining
12
+ * runtime usages are stripped; requires of provably pure modules are dropped with them.
13
+ *
14
+ * `@virtual` includes `@inline` behavior and also erases the declaration from emitted output. Every
15
+ * value reference must be computable at build time. Object spreads are expanded to table literals.
16
+ * Modules containing `@virtual` declarations are validated to be side-effect free.
17
+ *
18
+ * Tagged declarations act as an explicit whitelist and produce build errors when they cannot be inlined.
12
19
  */
13
20
  declare const plugin: Plugin;
14
21
  export default plugin;
@@ -3,22 +3,29 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const ts = require("typescript");
4
4
  const transformation_1 = require("./transformation");
5
5
  /**
6
- * Plugin that inlines compile-time constant values of `@inline` JSDoc tagged declarations.
6
+ * Plugin that inlines compile-time constants from declarations tagged with `@inline` or `@virtual`.
7
7
  *
8
8
  * Supported targets are enums, module-level `as const` object literals and module-level scalar constants.
9
- * Values may be literals or expressions foldable on build time - arithmetic, string concatenation,
9
+ * Values may be literals or expressions that can be folded at build time: arithmetic, string concatenation,
10
10
  * template literals and references to other constant declarations (enum members, const scalars,
11
11
  * `as const` object properties, whitelisted constants like 'math.pi').
12
- * Tagged declarations act as an explicit whitelist - member accesses are replaced with literal values in place,
13
- * while original tables are still emitted, so iteration / reverse mapping / whole-object usages keep working.
14
- * Tagged declarations that cannot be inlined produce build errors instead of silently emitting property lookups.
12
+ *
13
+ * `@inline` replaces member accesses with literal values while still emitting the original declaration,
14
+ * so iteration, reverse mapping and whole-object usages keep working. Import bindings with no remaining
15
+ * runtime usages are stripped; requires of provably pure modules are dropped with them.
16
+ *
17
+ * `@virtual` includes `@inline` behavior and also erases the declaration from emitted output. Every
18
+ * value reference must be computable at build time. Object spreads are expanded to table literals.
19
+ * Modules containing `@virtual` declarations are validated to be side-effect free.
20
+ *
21
+ * Tagged declarations act as an explicit whitelist and produce build errors when they cannot be inlined.
15
22
  */
16
23
  const plugin = {
17
24
  beforeTransform(program) {
18
25
  // Force binder to assign node parents before any 'getJSDocTags' call,
19
26
  // otherwise empty results are computed for parent-less nodes and cached on them forever.
20
27
  program.getTypeChecker();
21
- const diagnostics = (0, transformation_1.validateTopLevelTags)(program);
28
+ const diagnostics = [...(0, transformation_1.validateTopLevelTags)(program), ...(0, transformation_1.collectVirtualDiagnostics)(program)];
22
29
  if (diagnostics.length > 0) {
23
30
  return diagnostics;
24
31
  }
@@ -27,15 +34,22 @@ const plugin = {
27
34
  [ts.SyntaxKind.PropertyAccessExpression]: transformation_1.transformAccessExpression,
28
35
  [ts.SyntaxKind.ElementAccessExpression]: transformation_1.transformAccessExpression,
29
36
  [ts.SyntaxKind.Identifier]: transformation_1.transformIdentifierExpression,
37
+ [ts.SyntaxKind.ImportDeclaration]: transformation_1.transformImportDeclaration,
30
38
  [ts.SyntaxKind.VariableStatement]: (statement, context) => {
31
39
  if ((0, transformation_1.hasInlineTag)(statement)) {
32
40
  (0, transformation_1.validateVariableStatement)(statement, context);
41
+ if ((0, transformation_1.hasVirtualTag)(statement)) {
42
+ return [];
43
+ }
33
44
  }
34
45
  return context.superTransformStatements(statement);
35
46
  },
36
47
  [ts.SyntaxKind.EnumDeclaration]: (declaration, context) => {
37
48
  if ((0, transformation_1.hasInlineTag)(declaration)) {
38
49
  (0, transformation_1.validateEnumDeclaration)(declaration, context);
50
+ if ((0, transformation_1.hasVirtualTag)(declaration)) {
51
+ return [];
52
+ }
39
53
  }
40
54
  return context.superTransformStatements(declaration);
41
55
  },
@@ -1,20 +1,28 @@
1
1
  import * as ts from "typescript";
2
2
  /**
3
- * Check whether node is annotated with `@inline` JSDoc tag.
3
+ * Check whether a node is whitelisted for inlining.
4
+ * Both `@inline` and `@virtual` enable inlining; `@virtual` adds erasure rules elsewhere.
4
5
  *
5
6
  * @param node - Node to check tags for.
6
- * @returns Whether the node has `@inline` JSDoc tag.
7
+ * @returns Whether the node is whitelisted for inlining.
7
8
  */
8
9
  export declare function hasInlineTag(node: ts.Node): boolean;
9
10
  /**
10
- * Find variable statement containing provided declaration node, if any.
11
+ * Check whether a node has the `@virtual` JSDoc tag.
12
+ *
13
+ * @param node - Node to check tags for.
14
+ * @returns Whether the node has `@virtual` JSDoc tag.
15
+ */
16
+ export declare function hasVirtualTag(node: ts.Node): boolean;
17
+ /**
18
+ * Find the variable statement that contains the provided declaration node.
11
19
  *
12
20
  * @param node - Declaration node to walk up from.
13
21
  * @returns Containing variable statement or null.
14
22
  */
15
23
  export declare function getContainingVariableStatement(node: ts.Node): ts.VariableStatement | null;
16
24
  /**
17
- * Unwrap initializer expression from as/satisfies/parenthesized wrappers.
25
+ * Unwrap an initializer expression from `as`, `satisfies`, and parenthesized wrappers.
18
26
  *
19
27
  * @param expression - Initializer expression to unwrap.
20
28
  * @returns Unwrapped expression or null.
@@ -24,18 +32,18 @@ export declare function unwrapInitializer(expression?: ts.Expression): ts.Expres
24
32
  * Check whether variable statement is a module-level `const` declaration.
25
33
  *
26
34
  * @param statement - Variable statement to check.
27
- * @returns Whether statement is module-level const.
35
+ * @returns Whether the statement is a module-level const.
28
36
  */
29
37
  export declare function isModuleLevelConst(statement: ts.VariableStatement): boolean;
30
38
  /**
31
- * Check whether expression is wrapped with `as const` assertion, possibly through parens/satisfies wrappers.
39
+ * Check whether an expression is wrapped in an `as const` assertion, possibly through parens/satisfies wrappers.
32
40
  *
33
41
  * @param expression - Expression to check.
34
- * @returns Whether expression has `as const` assertion.
42
+ * @returns Whether the expression has an `as const` assertion.
35
43
  */
36
44
  export declare function hasAsConstAssertion(expression?: ts.Expression): boolean;
37
45
  /**
38
- * Check whether property is declared inside an `as const` object literal assigned to a module-level const.
46
+ * Check whether a property is declared inside an `as const` object literal assigned to a module-level const.
39
47
  * Such properties are readonly and cannot be legally reassigned, so their values are stable at runtime.
40
48
  *
41
49
  * @param declaration - Property declaration to check.
@@ -43,18 +51,19 @@ export declare function hasAsConstAssertion(expression?: ts.Expression): boolean
43
51
  */
44
52
  export declare function isReadonlyModuleConstProperty(declaration: ts.PropertyAssignment | ts.ShorthandPropertyAssignment): boolean;
45
53
  /**
46
- * Check whether identifier node is used in a value position where it can be replaced with a literal.
54
+ * Check whether an identifier is used in a value position where it can be replaced with a literal.
47
55
  *
48
56
  * @param node - Identifier node to check.
49
- * @returns Whether identifier is a replace-able value usage.
57
+ * @returns Whether the identifier is a replaceable value usage.
50
58
  */
51
59
  export declare function isValueUsagePosition(node: ts.Identifier): boolean;
52
60
  /**
53
- * Resolve member symbol for property/element access expression.
54
- * Element access with literal key is resolved through object type when direct symbol resolution fails.
61
+ * Get global access path for a runtime-constant engine member declaration.
62
+ * Qualifying declarations are `static readonly` class members declared inside ambient `declare module "xray16"` -
63
+ * such values are registered once by the engine and never change at runtime.
64
+ * The path uses the declared class name, so import aliases do not affect emitted references.
55
65
  *
56
- * @param checker - Program type checker.
57
- * @param node - Access expression to resolve symbol for.
58
- * @returns Resolved member symbol or null.
66
+ * @param declaration - Declaration to check.
67
+ * @returns Global access path like ['stalker_ids', 'action_dying'], or null when not a constant engine member.
59
68
  */
60
- export declare function resolveMemberSymbol(checker: ts.TypeChecker, node: ts.PropertyAccessExpression | ts.ElementAccessExpression): ts.Symbol | null;
69
+ export declare function getEngineConstantPath(declaration: ts.Declaration): Array<string> | null;
@@ -1,26 +1,47 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.hasInlineTag = hasInlineTag;
4
+ exports.hasVirtualTag = hasVirtualTag;
4
5
  exports.getContainingVariableStatement = getContainingVariableStatement;
5
6
  exports.unwrapInitializer = unwrapInitializer;
6
7
  exports.isModuleLevelConst = isModuleLevelConst;
7
8
  exports.hasAsConstAssertion = hasAsConstAssertion;
8
9
  exports.isReadonlyModuleConstProperty = isReadonlyModuleConstProperty;
9
10
  exports.isValueUsagePosition = isValueUsagePosition;
10
- exports.resolveMemberSymbol = resolveMemberSymbol;
11
+ exports.getEngineConstantPath = getEngineConstantPath;
11
12
  const ts = require("typescript");
12
13
  const constants_1 = require("./constants");
13
14
  /**
14
- * Check whether node is annotated with `@inline` JSDoc tag.
15
+ * Check whether a node has the provided JSDoc tag.
15
16
  *
16
17
  * @param node - Node to check tags for.
17
- * @returns Whether the node has `@inline` JSDoc tag.
18
+ * @param tag - Tag name to look for.
19
+ * @returns Whether the node has the JSDoc tag.
20
+ */
21
+ function hasJsDocTag(node, tag) {
22
+ return ts.getJSDocTags(node).some((it) => it.tagName.text === tag);
23
+ }
24
+ /**
25
+ * Check whether a node is whitelisted for inlining.
26
+ * Both `@inline` and `@virtual` enable inlining; `@virtual` adds erasure rules elsewhere.
27
+ *
28
+ * @param node - Node to check tags for.
29
+ * @returns Whether the node is whitelisted for inlining.
18
30
  */
19
31
  function hasInlineTag(node) {
20
- return ts.getJSDocTags(node).some((it) => it.tagName.text === constants_1.INLINE_TAG);
32
+ return hasJsDocTag(node, constants_1.INLINE_TAG) || hasJsDocTag(node, constants_1.VIRTUAL_TAG);
21
33
  }
22
34
  /**
23
- * Find variable statement containing provided declaration node, if any.
35
+ * Check whether a node has the `@virtual` JSDoc tag.
36
+ *
37
+ * @param node - Node to check tags for.
38
+ * @returns Whether the node has `@virtual` JSDoc tag.
39
+ */
40
+ function hasVirtualTag(node) {
41
+ return hasJsDocTag(node, constants_1.VIRTUAL_TAG);
42
+ }
43
+ /**
44
+ * Find the variable statement that contains the provided declaration node.
24
45
  *
25
46
  * @param node - Declaration node to walk up from.
26
47
  * @returns Containing variable statement or null.
@@ -36,7 +57,7 @@ function getContainingVariableStatement(node) {
36
57
  return null;
37
58
  }
38
59
  /**
39
- * Unwrap initializer expression from as/satisfies/parenthesized wrappers.
60
+ * Unwrap an initializer expression from `as`, `satisfies`, and parenthesized wrappers.
40
61
  *
41
62
  * @param expression - Initializer expression to unwrap.
42
63
  * @returns Unwrapped expression or null.
@@ -56,16 +77,16 @@ function unwrapInitializer(expression) {
56
77
  * Check whether variable statement is a module-level `const` declaration.
57
78
  *
58
79
  * @param statement - Variable statement to check.
59
- * @returns Whether statement is module-level const.
80
+ * @returns Whether the statement is a module-level const.
60
81
  */
61
82
  function isModuleLevelConst(statement) {
62
83
  return ts.isSourceFile(statement.parent) && (statement.declarationList.flags & ts.NodeFlags.Const) !== 0;
63
84
  }
64
85
  /**
65
- * Check whether expression is wrapped with `as const` assertion, possibly through parens/satisfies wrappers.
86
+ * Check whether an expression is wrapped in an `as const` assertion, possibly through parens/satisfies wrappers.
66
87
  *
67
88
  * @param expression - Expression to check.
68
- * @returns Whether expression has `as const` assertion.
89
+ * @returns Whether the expression has an `as const` assertion.
69
90
  */
70
91
  function hasAsConstAssertion(expression) {
71
92
  let current = expression;
@@ -85,7 +106,7 @@ function hasAsConstAssertion(expression) {
85
106
  return false;
86
107
  }
87
108
  /**
88
- * Check whether property is declared inside an `as const` object literal assigned to a module-level const.
109
+ * Check whether a property is declared inside an `as const` object literal assigned to a module-level const.
89
110
  * Such properties are readonly and cannot be legally reassigned, so their values are stable at runtime.
90
111
  *
91
112
  * @param declaration - Property declaration to check.
@@ -116,10 +137,10 @@ function isReadonlyModuleConstProperty(declaration) {
116
137
  return statement !== null && isModuleLevelConst(statement);
117
138
  }
118
139
  /**
119
- * Check whether identifier node is used in a value position where it can be replaced with a literal.
140
+ * Check whether an identifier is used in a value position where it can be replaced with a literal.
120
141
  *
121
142
  * @param node - Identifier node to check.
122
- * @returns Whether identifier is a replace-able value usage.
143
+ * @returns Whether the identifier is a replaceable value usage.
123
144
  */
124
145
  function isValueUsagePosition(node) {
125
146
  const parent = node.parent;
@@ -165,21 +186,34 @@ function isValueUsagePosition(node) {
165
186
  return true;
166
187
  }
167
188
  /**
168
- * Resolve member symbol for property/element access expression.
169
- * Element access with literal key is resolved through object type when direct symbol resolution fails.
189
+ * Get global access path for a runtime-constant engine member declaration.
190
+ * Qualifying declarations are `static readonly` class members declared inside ambient `declare module "xray16"` -
191
+ * such values are registered once by the engine and never change at runtime.
192
+ * The path uses the declared class name, so import aliases do not affect emitted references.
170
193
  *
171
- * @param checker - Program type checker.
172
- * @param node - Access expression to resolve symbol for.
173
- * @returns Resolved member symbol or null.
194
+ * @param declaration - Declaration to check.
195
+ * @returns Global access path like ['stalker_ids', 'action_dying'], or null when not a constant engine member.
174
196
  */
175
- function resolveMemberSymbol(checker, node) {
176
- const symbol = checker.getSymbolAtLocation(node);
177
- if (symbol !== undefined) {
178
- return symbol;
197
+ function getEngineConstantPath(declaration) {
198
+ if (!ts.isPropertyDeclaration(declaration) || !ts.isIdentifier(declaration.name)) {
199
+ return null;
200
+ }
201
+ const modifiers = ts.getModifiers(declaration) ?? [];
202
+ const isStaticReadonly = modifiers.some((it) => it.kind === ts.SyntaxKind.StaticKeyword) &&
203
+ modifiers.some((it) => it.kind === ts.SyntaxKind.ReadonlyKeyword);
204
+ if (!isStaticReadonly) {
205
+ return null;
206
+ }
207
+ const classDeclaration = declaration.parent;
208
+ if (!ts.isClassDeclaration(classDeclaration) || classDeclaration.name === undefined) {
209
+ return null;
179
210
  }
180
- if (ts.isElementAccessExpression(node) &&
181
- (ts.isStringLiteralLike(node.argumentExpression) || ts.isNumericLiteral(node.argumentExpression))) {
182
- return checker.getTypeAtLocation(node.expression).getProperty(node.argumentExpression.text) ?? null;
211
+ let current = classDeclaration.parent;
212
+ while (current !== undefined && !ts.isSourceFile(current)) {
213
+ if (ts.isModuleDeclaration(current) && ts.isStringLiteral(current.name) && current.name.text === "xray16") {
214
+ return [classDeclaration.name.text, declaration.name.text];
215
+ }
216
+ current = current.parent;
183
217
  }
184
218
  return null;
185
219
  }
@@ -3,12 +3,70 @@
3
3
  */
4
4
  export declare const INLINE_TAG: string;
5
5
  /**
6
- * Value types that can be inlined as lua literals.
6
+ * JSDoc tag marking declarations for compile-time inlining and erasure from emitted output.
7
+ * Includes `@inline` behavior and requires every value reference to be erasable.
8
+ */
9
+ export declare const VIRTUAL_TAG: string;
10
+ /**
11
+ * Value types that can be inlined as Lua literals.
7
12
  */
8
13
  export type TInlineValue = string | number | boolean;
9
14
  /**
10
- * Numeric namespace constants that are identical IEEE 754 doubles in build environment and LuaJIT runtime.
11
- * Covers both TS 'Math' and lua 'math' namespaces, function calls are intentionally not supported
12
- * since libm implementations may differ between build machine and game runtime.
15
+ * Reference to a runtime-constant engine value like 'stalker_ids.action_dying'.
16
+ * Emitted as a global access expression instead of a baked literal, so values stay correct
17
+ * even when engine builds diverge from the literal types declared in typings.
18
+ */
19
+ export interface IEngineReference {
20
+ kind: "engine-ref";
21
+ path: Array<string>;
22
+ isNumeric: boolean;
23
+ }
24
+ /**
25
+ * Binary numeric expression mixing engine references with other folded values.
26
+ */
27
+ export interface IFoldedBinary {
28
+ kind: "binary";
29
+ operator: TFoldedBinaryOperator;
30
+ left: TFoldedValue;
31
+ right: TFoldedValue;
32
+ }
33
+ /**
34
+ * Numeric negation of a folded expression.
35
+ */
36
+ export interface IFoldedNegation {
37
+ kind: "negate";
38
+ operand: TFoldedValue;
39
+ }
40
+ /**
41
+ * Operators allowed in folded expression trees - restricted to those where emitted Lua matches
42
+ * tstl lowering exactly. '%', bitwise operators and string concatenation are rejected for trees.
43
+ */
44
+ export type TFoldedBinaryOperator = "+" | "-" | "*" | "/" | "**";
45
+ /**
46
+ * Expression parts of folded values that cannot be computed to plain literals at build time.
47
+ */
48
+ export type TFoldedExpression = IEngineReference | IFoldedBinary | IFoldedNegation;
49
+ /**
50
+ * Result of build-time folding - either a plain literal or an expression tree with engine references.
51
+ */
52
+ export type TFoldedValue = TInlineValue | TFoldedExpression;
53
+ /**
54
+ * Check whether folded value is an expression tree rather than a plain literal.
55
+ *
56
+ * @param value - Folded value to check.
57
+ * @returns Whether value is an expression tree.
58
+ */
59
+ export declare function isFoldedExpression(value: TFoldedValue): value is TFoldedExpression;
60
+ /**
61
+ * Check whether folded value is numeric - a number literal or a numeric expression tree.
62
+ *
63
+ * @param value - Folded value to check.
64
+ * @returns Whether value is numeric.
65
+ */
66
+ export declare function isNumericFoldedValue(value: TFoldedValue): boolean;
67
+ /**
68
+ * Numeric namespace constants with identical IEEE 754 double values in the build environment and LuaJIT runtime.
69
+ * Covers both TS 'Math' and Lua 'math' namespaces. Function calls are intentionally not supported because
70
+ * libm implementations may differ between build machine and game runtime.
13
71
  */
14
72
  export declare const FOLDABLE_NAMESPACE_CONSTANTS: Record<string, Record<string, number>>;
@@ -1,14 +1,45 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FOLDABLE_NAMESPACE_CONSTANTS = exports.INLINE_TAG = void 0;
3
+ exports.FOLDABLE_NAMESPACE_CONSTANTS = exports.VIRTUAL_TAG = exports.INLINE_TAG = void 0;
4
+ exports.isFoldedExpression = isFoldedExpression;
5
+ exports.isNumericFoldedValue = isNumericFoldedValue;
4
6
  /**
5
7
  * JSDoc tag marking declarations as whitelisted for compile-time inlining.
6
8
  */
7
9
  exports.INLINE_TAG = "inline";
8
10
  /**
9
- * Numeric namespace constants that are identical IEEE 754 doubles in build environment and LuaJIT runtime.
10
- * Covers both TS 'Math' and lua 'math' namespaces, function calls are intentionally not supported
11
- * since libm implementations may differ between build machine and game runtime.
11
+ * JSDoc tag marking declarations for compile-time inlining and erasure from emitted output.
12
+ * Includes `@inline` behavior and requires every value reference to be erasable.
13
+ */
14
+ exports.VIRTUAL_TAG = "virtual";
15
+ /**
16
+ * Check whether folded value is an expression tree rather than a plain literal.
17
+ *
18
+ * @param value - Folded value to check.
19
+ * @returns Whether value is an expression tree.
20
+ */
21
+ function isFoldedExpression(value) {
22
+ return typeof value === "object";
23
+ }
24
+ /**
25
+ * Check whether folded value is numeric - a number literal or a numeric expression tree.
26
+ *
27
+ * @param value - Folded value to check.
28
+ * @returns Whether value is numeric.
29
+ */
30
+ function isNumericFoldedValue(value) {
31
+ if (typeof value === "number") {
32
+ return true;
33
+ }
34
+ if (typeof value === "object") {
35
+ return value.kind === "engine-ref" ? value.isNumeric : true;
36
+ }
37
+ return false;
38
+ }
39
+ /**
40
+ * Numeric namespace constants with identical IEEE 754 double values in the build environment and LuaJIT runtime.
41
+ * Covers both TS 'Math' and Lua 'math' namespaces. Function calls are intentionally not supported because
42
+ * libm implementations may differ between build machine and game runtime.
12
43
  */
13
44
  exports.FOLDABLE_NAMESPACE_CONSTANTS = {
14
45
  Math: {
@@ -1,6 +1,12 @@
1
1
  export declare const createUnsupportedDeclarationError: ((node: import("typescript").Node, ...args: any[]) => import("typescript").Diagnostic) & {
2
2
  code: number;
3
3
  };
4
+ export declare const createVirtualValueReferenceError: ((node: import("typescript").Node, name: string) => import("typescript").Diagnostic) & {
5
+ code: number;
6
+ };
7
+ export declare const createImpureVirtualModuleError: ((node: import("typescript").Node, ...args: any[]) => import("typescript").Diagnostic) & {
8
+ code: number;
9
+ };
4
10
  export declare const createNotModuleLevelError: ((node: import("typescript").Node, ...args: any[]) => import("typescript").Diagnostic) & {
5
11
  code: number;
6
12
  };
@@ -1,9 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createNotConstantEnumMemberError = exports.createForeignPropertyError = exports.createNotLiteralPropertyError = exports.createNotLiteralConstantError = exports.createNotAsConstObjectError = exports.createNotConstError = exports.createNotModuleLevelError = exports.createUnsupportedDeclarationError = void 0;
3
+ exports.createNotConstantEnumMemberError = exports.createForeignPropertyError = exports.createNotLiteralPropertyError = exports.createNotLiteralConstantError = exports.createNotAsConstObjectError = exports.createNotConstError = exports.createNotModuleLevelError = exports.createImpureVirtualModuleError = exports.createVirtualValueReferenceError = exports.createUnsupportedDeclarationError = void 0;
4
4
  const diagnostics_1 = require("../../utils/diagnostics");
5
5
  const constants_1 = require("./constants");
6
- exports.createUnsupportedDeclarationError = (0, diagnostics_1.createErrorDiagnosticFactory)(`'@${constants_1.INLINE_TAG}' is supported only for enums and module-level 'const' declarations.`);
6
+ exports.createUnsupportedDeclarationError = (0, diagnostics_1.createErrorDiagnosticFactory)(`'@${constants_1.INLINE_TAG}' and '@${constants_1.VIRTUAL_TAG}' are supported only for enums and module-level 'const' declarations.`);
7
+ exports.createVirtualValueReferenceError = (0, diagnostics_1.createErrorDiagnosticFactory)((name) => `'@${constants_1.VIRTUAL_TAG}' declaration '${name}' is referenced as a value and cannot be erased, ` +
8
+ `demote it to '@${constants_1.INLINE_TAG}' or make the reference computable on build time.`);
9
+ exports.createImpureVirtualModuleError = (0, diagnostics_1.createErrorDiagnosticFactory)(`Modules with '@${constants_1.VIRTUAL_TAG}' declarations may contain only type-only imports, ` +
10
+ `'@${constants_1.INLINE_TAG}'/'@${constants_1.VIRTUAL_TAG}' constants, constant enums, type aliases and interfaces.`);
7
11
  exports.createNotModuleLevelError = (0, diagnostics_1.createErrorDiagnosticFactory)(`'@${constants_1.INLINE_TAG}' declarations must be module-level statements.`);
8
12
  exports.createNotConstError = (0, diagnostics_1.createErrorDiagnosticFactory)(`'@${constants_1.INLINE_TAG}' declarations must use 'const' keyword.`);
9
13
  exports.createNotAsConstObjectError = (0, diagnostics_1.createErrorDiagnosticFactory)((name) => `'@${constants_1.INLINE_TAG}' object '${name}' must use 'as const' assertion.`);