@neocompose/cli 0.31.15 → 0.32.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.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.32.0] - 2026-08-18
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- P69 Math builtins: call `Math.Min`, `Max`, `Clamp`, `Round`, `Floor`,
|
|
8
|
+
`Ceiling`, `Truncate`, `Abs`, `Sign`, and `Sqrt`, and read the `Math.PI` and
|
|
9
|
+
`Math.E` constants, from any NeoScript body. Results are inferred from the
|
|
10
|
+
argument types under the arithmetic join rule, `Round`/`Floor`/`Ceiling`/
|
|
11
|
+
`Truncate` return `int` on `int` and `float` input, and `Math` is now a
|
|
12
|
+
reserved name.
|
|
13
|
+
|
|
14
|
+
## [0.31.17] - 2026-08-18
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Accept runtime interface patterns on open Class hierarchies while retaining
|
|
19
|
+
impossible-pattern diagnostics for sealed Classes.
|
|
20
|
+
- Recognize typed NeoScript setters as writable from initializers and function
|
|
21
|
+
bodies, including compound assignments, and compile their setter bodies.
|
|
22
|
+
- Preserve `NeoVariant<T>` member types in the local manifest used by
|
|
23
|
+
`neo script check --all`, matching `neo test` candidate compilation.
|
|
24
|
+
|
|
25
|
+
## [0.31.16] - 2026-08-18
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- Resolve unordered List membership from entry `containerId` rows during
|
|
30
|
+
NeoScript evaluation, so root-backed indexes and collection operations see
|
|
31
|
+
stored entries in CLI tests, web previews, and world construction.
|
|
32
|
+
|
|
3
33
|
## [0.31.15] - 2026-08-18
|
|
4
34
|
|
|
5
35
|
### Fixed
|
package/dist/neo.mjs
CHANGED
|
@@ -1308,6 +1308,20 @@ function structuredLeafFieldProperties(owner) {
|
|
|
1308
1308
|
(field) => property(owner, field.name, field.type, field.documentation, true)
|
|
1309
1309
|
);
|
|
1310
1310
|
}
|
|
1311
|
+
function mathFunction(name, parameterNames, documentation, returnType = FLOAT_TYPE) {
|
|
1312
|
+
return {
|
|
1313
|
+
id: `${NEOSCRIPT_MATH_TYPE_ID}:function:${name}`,
|
|
1314
|
+
name,
|
|
1315
|
+
kind: "function",
|
|
1316
|
+
type: returnType,
|
|
1317
|
+
returnType,
|
|
1318
|
+
parameters: parameterNames.map(
|
|
1319
|
+
(parameterName) => parameter(parameterName, FLOAT_TYPE)
|
|
1320
|
+
),
|
|
1321
|
+
documentation,
|
|
1322
|
+
static: true
|
|
1323
|
+
};
|
|
1324
|
+
}
|
|
1311
1325
|
function vectorTypes() {
|
|
1312
1326
|
const names = [
|
|
1313
1327
|
"Vector2",
|
|
@@ -1322,7 +1336,7 @@ function vectorTypes() {
|
|
|
1322
1336
|
members: structuredLeafFieldProperties(name)
|
|
1323
1337
|
}));
|
|
1324
1338
|
}
|
|
1325
|
-
var NEO_PROJECT_IGNORED_DIRECTORY_NAMES, NEOSCRIPT_KEYWORDS, NEOSCRIPT_INFERRED_LOCAL_KEYWORD, NEOSCRIPT_CONSTRUCTOR_KEYWORD, NEOSCRIPT_PRIMITIVE_TYPES, NEOSCRIPT_BUILTIN_TYPES, NEO_VARIANT_TYPE_NAME, NEO_VARIANT_FOLDER_TYPE_NAME, NEO_LOOKUP_VARIANT_TYPE_NAME, NEO_LOOKUP_VARIANT_FOLDER_TYPE_NAME, NEO_VARIANT_SCOPE_NAME, NEO_VARIANT_RESERVED_NAME, NEO_VARIANT_FOLDER_PATH_SEPARATOR, NEOSCRIPT_OPERATORS, NEOSCRIPT_STATEMENT_SNIPPETS, STRING_TYPE, INT_TYPE, FLOAT_TYPE, BOOL_TYPE, IMAGE_REF_TYPE, SPRITE_INFO_TYPE, FLOAT_OPTIONAL_TYPE, NEOSCRIPT_STRUCTURED_LEAF_FIELDS, NEOSCRIPT_IMAGE_REGISTRY_TYPE, NEOSCRIPT_AUDIO_CLIP_REGISTRY_TYPE, NEOSCRIPT_PENDING_SYMBOL_ID_PREFIX, REGISTRY_ENTRY_TYPES, NEOSCRIPT_GLOBALS, NEOSCRIPT_SPRITE_INFO_EMPTY_MEMBER_ID, NEOSCRIPT_SPRITE_INFO_EMPTY_VALUE, NEOSCRIPT_BUILTIN_TYPE_SYMBOLS;
|
|
1339
|
+
var NEO_PROJECT_IGNORED_DIRECTORY_NAMES, NEOSCRIPT_KEYWORDS, NEOSCRIPT_INFERRED_LOCAL_KEYWORD, NEOSCRIPT_CONSTRUCTOR_KEYWORD, NEOSCRIPT_PRIMITIVE_TYPES, NEOSCRIPT_BUILTIN_ANNOTATION_TYPES, NEOSCRIPT_BUILTIN_NAMESPACES, NEOSCRIPT_BUILTIN_TYPES, NEO_VARIANT_TYPE_NAME, NEO_VARIANT_FOLDER_TYPE_NAME, NEO_LOOKUP_VARIANT_TYPE_NAME, NEO_LOOKUP_VARIANT_FOLDER_TYPE_NAME, NEO_VARIANT_SCOPE_NAME, NEO_VARIANT_RESERVED_NAME, NEO_VARIANT_FOLDER_PATH_SEPARATOR, NEOSCRIPT_OPERATORS, NEOSCRIPT_STATEMENT_SNIPPETS, STRING_TYPE, INT_TYPE, FLOAT_TYPE, BOOL_TYPE, IMAGE_REF_TYPE, SPRITE_INFO_TYPE, FLOAT_OPTIONAL_TYPE, NEOSCRIPT_STRUCTURED_LEAF_FIELDS, NEOSCRIPT_IMAGE_REGISTRY_TYPE, NEOSCRIPT_AUDIO_CLIP_REGISTRY_TYPE, NEOSCRIPT_PENDING_SYMBOL_ID_PREFIX, REGISTRY_ENTRY_TYPES, NEOSCRIPT_GLOBALS, NEOSCRIPT_SPRITE_INFO_EMPTY_MEMBER_ID, NEOSCRIPT_SPRITE_INFO_EMPTY_VALUE, NEOSCRIPT_MATH_TYPE_ID, MATH_INFERENCE_RULE, MATH_INTEGRAL_RULE, NEOSCRIPT_BUILTIN_TYPE_SYMBOLS;
|
|
1326
1340
|
var init_language_spec = __esm({
|
|
1327
1341
|
"../packages/neoscript-language/src/language-spec.ts"() {
|
|
1328
1342
|
"use strict";
|
|
@@ -1384,7 +1398,7 @@ var init_language_spec = __esm({
|
|
|
1384
1398
|
"bool",
|
|
1385
1399
|
"string"
|
|
1386
1400
|
];
|
|
1387
|
-
|
|
1401
|
+
NEOSCRIPT_BUILTIN_ANNOTATION_TYPES = [
|
|
1388
1402
|
"Dictionary",
|
|
1389
1403
|
"List",
|
|
1390
1404
|
"Set",
|
|
@@ -1410,6 +1424,11 @@ var init_language_spec = __esm({
|
|
|
1410
1424
|
"Vector3Int",
|
|
1411
1425
|
"Color"
|
|
1412
1426
|
];
|
|
1427
|
+
NEOSCRIPT_BUILTIN_NAMESPACES = ["Math"];
|
|
1428
|
+
NEOSCRIPT_BUILTIN_TYPES = [
|
|
1429
|
+
...NEOSCRIPT_BUILTIN_ANNOTATION_TYPES,
|
|
1430
|
+
...NEOSCRIPT_BUILTIN_NAMESPACES
|
|
1431
|
+
];
|
|
1413
1432
|
NEO_VARIANT_TYPE_NAME = "NeoVariant";
|
|
1414
1433
|
NEO_VARIANT_FOLDER_TYPE_NAME = "NeoVariantFolder";
|
|
1415
1434
|
NEO_LOOKUP_VARIANT_TYPE_NAME = "NeoLookupVariant";
|
|
@@ -1658,6 +1677,9 @@ var init_language_spec = __esm({
|
|
|
1658
1677
|
fileId: "",
|
|
1659
1678
|
sliceIndex: 0
|
|
1660
1679
|
});
|
|
1680
|
+
NEOSCRIPT_MATH_TYPE_ID = "builtin:Math";
|
|
1681
|
+
MATH_INFERENCE_RULE = "Accepts int, float, or decimal; the result mirrors the widest argument type.";
|
|
1682
|
+
MATH_INTEGRAL_RULE = "Accepts int, float, or decimal; int and float return int, decimal returns decimal.";
|
|
1661
1683
|
NEOSCRIPT_BUILTIN_TYPE_SYMBOLS = [
|
|
1662
1684
|
{
|
|
1663
1685
|
id: "builtin:SpriteInfo",
|
|
@@ -1730,6 +1752,87 @@ var init_language_spec = __esm({
|
|
|
1730
1752
|
name: "Color",
|
|
1731
1753
|
kind: "builtin",
|
|
1732
1754
|
members: structuredLeafFieldProperties("Color")
|
|
1755
|
+
},
|
|
1756
|
+
{
|
|
1757
|
+
id: NEOSCRIPT_MATH_TYPE_ID,
|
|
1758
|
+
name: "Math",
|
|
1759
|
+
kind: "builtin",
|
|
1760
|
+
documentation: "Numeric builtins with C# names and C# semantics. Math is a qualifier only \u2014 it names no type and holds no value, and every member is a pure function or constant.",
|
|
1761
|
+
members: [
|
|
1762
|
+
mathFunction(
|
|
1763
|
+
"Min",
|
|
1764
|
+
["a", "b"],
|
|
1765
|
+
`Returns the smaller of two values. ${MATH_INFERENCE_RULE} Ties return the first argument.`
|
|
1766
|
+
),
|
|
1767
|
+
mathFunction(
|
|
1768
|
+
"Max",
|
|
1769
|
+
["a", "b"],
|
|
1770
|
+
`Returns the larger of two values. ${MATH_INFERENCE_RULE} Ties return the first argument.`
|
|
1771
|
+
),
|
|
1772
|
+
mathFunction(
|
|
1773
|
+
"Clamp",
|
|
1774
|
+
["value", "min", "max"],
|
|
1775
|
+
`Returns value pinned to the inclusive range min..max. ${MATH_INFERENCE_RULE} Requires min <= max.`
|
|
1776
|
+
),
|
|
1777
|
+
mathFunction(
|
|
1778
|
+
"Round",
|
|
1779
|
+
["x"],
|
|
1780
|
+
`Rounds to the nearest integer; midpoints round to even (banker's rounding). ${MATH_INTEGRAL_RULE}`,
|
|
1781
|
+
INT_TYPE
|
|
1782
|
+
),
|
|
1783
|
+
mathFunction(
|
|
1784
|
+
"Floor",
|
|
1785
|
+
["x"],
|
|
1786
|
+
`Rounds toward negative infinity. ${MATH_INTEGRAL_RULE}`,
|
|
1787
|
+
INT_TYPE
|
|
1788
|
+
),
|
|
1789
|
+
mathFunction(
|
|
1790
|
+
"Ceiling",
|
|
1791
|
+
["x"],
|
|
1792
|
+
`Rounds toward positive infinity. ${MATH_INTEGRAL_RULE}`,
|
|
1793
|
+
INT_TYPE
|
|
1794
|
+
),
|
|
1795
|
+
mathFunction(
|
|
1796
|
+
"Truncate",
|
|
1797
|
+
["x"],
|
|
1798
|
+
`Rounds toward zero. ${MATH_INTEGRAL_RULE}`,
|
|
1799
|
+
INT_TYPE
|
|
1800
|
+
),
|
|
1801
|
+
mathFunction(
|
|
1802
|
+
"Abs",
|
|
1803
|
+
["x"],
|
|
1804
|
+
`Returns the absolute value. ${MATH_INFERENCE_RULE}`
|
|
1805
|
+
),
|
|
1806
|
+
mathFunction(
|
|
1807
|
+
"Sign",
|
|
1808
|
+
["x"],
|
|
1809
|
+
"Returns -1, 0, or 1 for a negative, zero, or positive value. Accepts int, float, or decimal and always returns int.",
|
|
1810
|
+
INT_TYPE
|
|
1811
|
+
),
|
|
1812
|
+
mathFunction(
|
|
1813
|
+
"Sqrt",
|
|
1814
|
+
["x"],
|
|
1815
|
+
"Returns the square root. Accepts int or float and returns float; does not accept decimal."
|
|
1816
|
+
),
|
|
1817
|
+
{
|
|
1818
|
+
...property(
|
|
1819
|
+
"Math",
|
|
1820
|
+
"PI",
|
|
1821
|
+
FLOAT_TYPE,
|
|
1822
|
+
"The ratio of a circle's circumference to its diameter (3.141592653589793)."
|
|
1823
|
+
),
|
|
1824
|
+
static: true
|
|
1825
|
+
},
|
|
1826
|
+
{
|
|
1827
|
+
...property(
|
|
1828
|
+
"Math",
|
|
1829
|
+
"E",
|
|
1830
|
+
FLOAT_TYPE,
|
|
1831
|
+
"The base of the natural logarithm (2.718281828459045)."
|
|
1832
|
+
),
|
|
1833
|
+
static: true
|
|
1834
|
+
}
|
|
1835
|
+
]
|
|
1733
1836
|
}
|
|
1734
1837
|
];
|
|
1735
1838
|
}
|
|
@@ -2320,12 +2423,11 @@ function complete(snapshot, position) {
|
|
|
2320
2423
|
word
|
|
2321
2424
|
);
|
|
2322
2425
|
} else {
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
candidates = completionItemsForResolution(snapshot, resolved, word);
|
|
2426
|
+
candidates = completionItemsForResolution(
|
|
2427
|
+
snapshot,
|
|
2428
|
+
resolveChain(snapshot, receiverTokens, offset),
|
|
2429
|
+
word
|
|
2430
|
+
);
|
|
2329
2431
|
}
|
|
2330
2432
|
} else if (tail?.kind === "identifier" && tail.text === NEOSCRIPT_CONSTRUCTOR_KEYWORD) {
|
|
2331
2433
|
candidates = constructorCompletionItems(
|
|
@@ -3205,6 +3307,7 @@ function typeCompletionItems(snapshot, word) {
|
|
|
3205
3307
|
)
|
|
3206
3308
|
);
|
|
3207
3309
|
for (const type of snapshot.project.typeByName.values()) {
|
|
3310
|
+
if (type.id === NEOSCRIPT_MATH_TYPE_ID) continue;
|
|
3208
3311
|
items.push(typeCompletion(type, word, snapshot));
|
|
3209
3312
|
}
|
|
3210
3313
|
return items;
|
|
@@ -3409,9 +3512,16 @@ function switchCaseEnumContext(snapshot, offset) {
|
|
|
3409
3512
|
function resolveChain(snapshot, tokens, offset) {
|
|
3410
3513
|
if (tokens.length === 0) return null;
|
|
3411
3514
|
const constructorType = tokens[0]?.kind === "identifier" && tokens[0].text === NEOSCRIPT_CONSTRUCTOR_KEYWORD && tokens[1]?.kind === "identifier" ? snapshot.project.typeByName.get(tokens[1].text) : void 0;
|
|
3515
|
+
const staticRoot = tokens[0]?.kind === "type" ? snapshot.project.typeByName.get(tokens[0].text) : void 0;
|
|
3412
3516
|
let current;
|
|
3413
3517
|
let cursor;
|
|
3414
|
-
if (
|
|
3518
|
+
if (staticRoot) {
|
|
3519
|
+
current = {
|
|
3520
|
+
type: { kind: "named", typeId: staticRoot.id },
|
|
3521
|
+
staticType: staticRoot
|
|
3522
|
+
};
|
|
3523
|
+
cursor = 1;
|
|
3524
|
+
} else if (constructorType?.constructorSignature) {
|
|
3415
3525
|
current = { type: constructorType.constructorSignature.returnType };
|
|
3416
3526
|
const open = tokens.findIndex(
|
|
3417
3527
|
(token, index) => index >= 2 && token.kind === "punctuation" && token.text === "("
|
|
@@ -4509,6 +4619,7 @@ var init_analyzer = __esm({
|
|
|
4509
4619
|
RESERVED_NAMES = /* @__PURE__ */ new Set([
|
|
4510
4620
|
...NEOSCRIPT_KEYWORDS,
|
|
4511
4621
|
...NEOSCRIPT_PRIMITIVE_TYPES,
|
|
4622
|
+
...NEOSCRIPT_BUILTIN_NAMESPACES,
|
|
4512
4623
|
"Dictionary",
|
|
4513
4624
|
"Set"
|
|
4514
4625
|
]);
|
|
@@ -8817,6 +8928,18 @@ function typesOverlap(left, right, project) {
|
|
|
8817
8928
|
if (isNull(right)) return isNullable(left);
|
|
8818
8929
|
if (isNeoScriptTypeAssignable(left, right, project) || isNeoScriptTypeAssignable(right, left, project))
|
|
8819
8930
|
return true;
|
|
8931
|
+
if (left.kind === "named" && right.kind === "named") {
|
|
8932
|
+
const leftDeclaration = project.typeById.get(left.typeId);
|
|
8933
|
+
const rightDeclaration = project.typeById.get(right.typeId);
|
|
8934
|
+
if (leftDeclaration?.kind === "interface" && rightDeclaration?.kind === "interface") {
|
|
8935
|
+
return true;
|
|
8936
|
+
}
|
|
8937
|
+
const classDeclaration = leftDeclaration?.kind === "class" ? leftDeclaration : rightDeclaration?.kind === "class" ? rightDeclaration : null;
|
|
8938
|
+
const interfaceDeclaration = leftDeclaration?.kind === "interface" ? leftDeclaration : rightDeclaration?.kind === "interface" ? rightDeclaration : null;
|
|
8939
|
+
if (classDeclaration !== null && interfaceDeclaration !== null) {
|
|
8940
|
+
return classDeclaration.sealed !== true;
|
|
8941
|
+
}
|
|
8942
|
+
}
|
|
8820
8943
|
return isNumeric(left) && isNumeric(right);
|
|
8821
8944
|
}
|
|
8822
8945
|
function isUnknown(type) {
|
|
@@ -8855,6 +8978,30 @@ function numericResult(left, right) {
|
|
|
8855
8978
|
}
|
|
8856
8979
|
return { kind: "primitive", name: "int" };
|
|
8857
8980
|
}
|
|
8981
|
+
function isContextualNumericLiteral(expression) {
|
|
8982
|
+
if (expression.kind === "litInt" || expression.kind === "litFloat") {
|
|
8983
|
+
return true;
|
|
8984
|
+
}
|
|
8985
|
+
return expression.kind === "unary" && expression.op === "-" && (expression.operand.kind === "litInt" || expression.operand.kind === "litFloat");
|
|
8986
|
+
}
|
|
8987
|
+
function mathResultType(rule, joined, pos) {
|
|
8988
|
+
switch (rule) {
|
|
8989
|
+
case "join":
|
|
8990
|
+
return joined;
|
|
8991
|
+
case "integral":
|
|
8992
|
+
return isPrimitive(joined, "decimal") ? joined : { kind: "primitive", name: "int" };
|
|
8993
|
+
case "int":
|
|
8994
|
+
return { kind: "primitive", name: "int" };
|
|
8995
|
+
case "float":
|
|
8996
|
+
if (isPrimitive(joined, "decimal")) {
|
|
8997
|
+
throw new CompileError(
|
|
8998
|
+
"Math.Sqrt does not accept decimal; convert explicitly with value.ToFloat().",
|
|
8999
|
+
pos
|
|
9000
|
+
);
|
|
9001
|
+
}
|
|
9002
|
+
return { kind: "primitive", name: "float" };
|
|
9003
|
+
}
|
|
9004
|
+
}
|
|
8858
9005
|
function normalizedReturnType(type, kind) {
|
|
8859
9006
|
if (kind === "action" || kind === "setter" || kind === "constructor") {
|
|
8860
9007
|
return { kind: "primitive", name: "null" };
|
|
@@ -9197,7 +9344,7 @@ function switchValueKey(value) {
|
|
|
9197
9344
|
const enumId = value.typeInfo.type === 8 /* Enum */ ? value.typeInfo.enumId : null;
|
|
9198
9345
|
return JSON.stringify([value.typeInfo.type, enumId, value.value]);
|
|
9199
9346
|
}
|
|
9200
|
-
var CONSTRUCTING_FUNCTION_KINDS, VARIANT_INITIALIZE_NAME, VARIANT_APPLY_NAME, WRITE_TARGET_DESCRIPTIONS, FALLTHROUGH_LABELS, Scope, StrictNeoScriptResolver, SPRITE_DERIVED_MEMBERS;
|
|
9347
|
+
var CONSTRUCTING_FUNCTION_KINDS, VARIANT_INITIALIZE_NAME, VARIANT_APPLY_NAME, MATH_NAMESPACE_NAME, MATH_FUNCTIONS, MATH_CONSTANTS, WRITE_TARGET_DESCRIPTIONS, FALLTHROUGH_LABELS, Scope, StrictNeoScriptResolver, SPRITE_DERIVED_MEMBERS;
|
|
9201
9348
|
var init_strict_resolver = __esm({
|
|
9202
9349
|
"../packages/neoscript-language/src/strict-resolver.ts"() {
|
|
9203
9350
|
"use strict";
|
|
@@ -9221,6 +9368,23 @@ var init_strict_resolver = __esm({
|
|
|
9221
9368
|
);
|
|
9222
9369
|
VARIANT_INITIALIZE_NAME = "Initialize";
|
|
9223
9370
|
VARIANT_APPLY_NAME = "ToVariant";
|
|
9371
|
+
MATH_NAMESPACE_NAME = "Math";
|
|
9372
|
+
MATH_FUNCTIONS = /* @__PURE__ */ new Map([
|
|
9373
|
+
["Min", { op: "min", arity: 2, result: "join" }],
|
|
9374
|
+
["Max", { op: "max", arity: 2, result: "join" }],
|
|
9375
|
+
["Clamp", { op: "clamp", arity: 3, result: "join" }],
|
|
9376
|
+
["Round", { op: "round", arity: 1, result: "integral" }],
|
|
9377
|
+
["Floor", { op: "floor", arity: 1, result: "integral" }],
|
|
9378
|
+
["Ceiling", { op: "ceiling", arity: 1, result: "integral" }],
|
|
9379
|
+
["Truncate", { op: "truncate", arity: 1, result: "integral" }],
|
|
9380
|
+
["Abs", { op: "abs", arity: 1, result: "join" }],
|
|
9381
|
+
["Sign", { op: "sign", arity: 1, result: "int" }],
|
|
9382
|
+
["Sqrt", { op: "sqrt", arity: 1, result: "float" }]
|
|
9383
|
+
]);
|
|
9384
|
+
MATH_CONSTANTS = /* @__PURE__ */ new Map([
|
|
9385
|
+
["PI", 3.141592653589793],
|
|
9386
|
+
["E", 2.718281828459045]
|
|
9387
|
+
]);
|
|
9224
9388
|
WRITE_TARGET_DESCRIPTIONS = {
|
|
9225
9389
|
this: "`this`",
|
|
9226
9390
|
local: "a local",
|
|
@@ -10218,6 +10382,12 @@ var init_strict_resolver = __esm({
|
|
|
10218
10382
|
};
|
|
10219
10383
|
}
|
|
10220
10384
|
assertLocalNameAvailable(name, scope, pos) {
|
|
10385
|
+
if (name === MATH_NAMESPACE_NAME) {
|
|
10386
|
+
throw new CompileError(
|
|
10387
|
+
`Cannot declare a local named '${MATH_NAMESPACE_NAME}' because it is a builtin namespace.`,
|
|
10388
|
+
pos
|
|
10389
|
+
);
|
|
10390
|
+
}
|
|
10221
10391
|
if (!scope.lookup(name)) return;
|
|
10222
10392
|
throw new CompileError(
|
|
10223
10393
|
`Cannot declare local '${name}' because that name is already used in an enclosing or current scope.`,
|
|
@@ -11435,6 +11605,12 @@ var init_strict_resolver = __esm({
|
|
|
11435
11605
|
false
|
|
11436
11606
|
);
|
|
11437
11607
|
}
|
|
11608
|
+
if (name === MATH_NAMESPACE_NAME) {
|
|
11609
|
+
throw new CompileError(
|
|
11610
|
+
`'${MATH_NAMESPACE_NAME}' is a builtin namespace, not a value.`,
|
|
11611
|
+
pos
|
|
11612
|
+
);
|
|
11613
|
+
}
|
|
11438
11614
|
const type = this.project.typeByName.get(name);
|
|
11439
11615
|
if (type?.kind === "enum") {
|
|
11440
11616
|
return {
|
|
@@ -11832,6 +12008,15 @@ var init_strict_resolver = __esm({
|
|
|
11832
12008
|
{ ...NEOSCRIPT_SPRITE_INFO_EMPTY_VALUE }
|
|
11833
12009
|
);
|
|
11834
12010
|
}
|
|
12011
|
+
if (receiverAst.name === MATH_NAMESPACE_NAME) {
|
|
12012
|
+
if (optional) {
|
|
12013
|
+
throw new CompileError(
|
|
12014
|
+
`Optional chaining is not valid on builtin namespace '${MATH_NAMESPACE_NAME}'.`,
|
|
12015
|
+
pos
|
|
12016
|
+
);
|
|
12017
|
+
}
|
|
12018
|
+
return this.resolveMathMemberRead(name, pos);
|
|
12019
|
+
}
|
|
11835
12020
|
const staticType = this.project.typeByName.get(receiverAst.name);
|
|
11836
12021
|
if (staticType && staticType.kind !== "enum") {
|
|
11837
12022
|
if (optional) {
|
|
@@ -12353,6 +12538,114 @@ var init_strict_resolver = __esm({
|
|
|
12353
12538
|
);
|
|
12354
12539
|
}
|
|
12355
12540
|
}
|
|
12541
|
+
/**
|
|
12542
|
+
* P69 §2.7. A member read on the `Math` namespace: the two constants lower
|
|
12543
|
+
* to `float` literals, and nothing else on `Math` is readable as a value.
|
|
12544
|
+
*/
|
|
12545
|
+
resolveMathMemberRead(name, pos) {
|
|
12546
|
+
const constant = MATH_CONSTANTS.get(name);
|
|
12547
|
+
if (constant !== void 0) {
|
|
12548
|
+
return literal({ kind: "primitive", name: "float" }, constant);
|
|
12549
|
+
}
|
|
12550
|
+
if (MATH_FUNCTIONS.has(name)) {
|
|
12551
|
+
throw new CompileError(
|
|
12552
|
+
`Math function '${MATH_NAMESPACE_NAME}.${name}' must be called with \`()\`; it cannot be read as a value.`,
|
|
12553
|
+
pos
|
|
12554
|
+
);
|
|
12555
|
+
}
|
|
12556
|
+
throw new CompileError(
|
|
12557
|
+
`${MATH_NAMESPACE_NAME} has no function '${name}'.`,
|
|
12558
|
+
pos
|
|
12559
|
+
);
|
|
12560
|
+
}
|
|
12561
|
+
/**
|
|
12562
|
+
* P69 §2. A call on the `Math` namespace. Every function is one symbol
|
|
12563
|
+
* whose result type is computed here from the resolved argument types —
|
|
12564
|
+
* the arithmetic operator join rule, verbatim — and lowers to a `mathOp`
|
|
12565
|
+
* intrinsic carrying the operands in declaration order.
|
|
12566
|
+
*/
|
|
12567
|
+
resolveMathCall(name, args, scope, pos) {
|
|
12568
|
+
const fn = MATH_FUNCTIONS.get(name);
|
|
12569
|
+
if (!fn) {
|
|
12570
|
+
if (MATH_CONSTANTS.has(name)) {
|
|
12571
|
+
throw new CompileError(
|
|
12572
|
+
`${MATH_NAMESPACE_NAME}.${name} is a constant, not a function; read it without \`()\`.`,
|
|
12573
|
+
pos
|
|
12574
|
+
);
|
|
12575
|
+
}
|
|
12576
|
+
throw new CompileError(
|
|
12577
|
+
`${MATH_NAMESPACE_NAME} has no function '${name}'.`,
|
|
12578
|
+
pos
|
|
12579
|
+
);
|
|
12580
|
+
}
|
|
12581
|
+
const label = `${MATH_NAMESPACE_NAME}.${name}`;
|
|
12582
|
+
requireArgCount(label, args, fn.arity, pos);
|
|
12583
|
+
const resolved = args.map((argument2, index) => {
|
|
12584
|
+
const value = this.resolveExpression(argument2, scope);
|
|
12585
|
+
if (isNullable(value.type)) {
|
|
12586
|
+
throw new CompileError(
|
|
12587
|
+
`${label} requires non-optional arguments; got ${this.describe(value.type)} for argument ${index + 1}.`,
|
|
12588
|
+
argument2.pos
|
|
12589
|
+
);
|
|
12590
|
+
}
|
|
12591
|
+
if (!isNumeric(value.type)) {
|
|
12592
|
+
throw new CompileError(
|
|
12593
|
+
`${label} requires numeric arguments; got ${this.describe(value.type)} for argument ${index + 1}.`,
|
|
12594
|
+
argument2.pos
|
|
12595
|
+
);
|
|
12596
|
+
}
|
|
12597
|
+
return value;
|
|
12598
|
+
});
|
|
12599
|
+
const joined = this.joinMathArguments(args, resolved, scope, pos);
|
|
12600
|
+
return intrinsic(
|
|
12601
|
+
"mathOp" /* MathOp */,
|
|
12602
|
+
{
|
|
12603
|
+
op: fn.op,
|
|
12604
|
+
argPointers: joined.arguments.map((argument2) => argument2.pointer),
|
|
12605
|
+
...isPrimitive(joined.type, "decimal") ? { decimal: true } : {}
|
|
12606
|
+
},
|
|
12607
|
+
mathResultType(fn.result, joined.type, pos)
|
|
12608
|
+
);
|
|
12609
|
+
}
|
|
12610
|
+
/**
|
|
12611
|
+
* P69 §2.1. The join of a `Math` call's argument types, after the second
|
|
12612
|
+
* resolution pass that gives numeric literals beside a `decimal` argument
|
|
12613
|
+
* their decimal reading.
|
|
12614
|
+
*
|
|
12615
|
+
* A call's argument list carries no declared expected type once typing is
|
|
12616
|
+
* inferred, so `Math.Max(price, 0.99)` would otherwise type `0.99` as
|
|
12617
|
+
* `float` and die on the mix rule with no decimal literal suffix to escape
|
|
12618
|
+
* with. Re-resolving from the preserved raw lexeme is the assignment-context
|
|
12619
|
+
* rule applied across the argument list, not a new coercion: a non-literal
|
|
12620
|
+
* `float` expression still refuses to mix.
|
|
12621
|
+
*/
|
|
12622
|
+
joinMathArguments(args, resolved, scope, pos) {
|
|
12623
|
+
const decimalType = {
|
|
12624
|
+
kind: "primitive",
|
|
12625
|
+
name: "decimal"
|
|
12626
|
+
};
|
|
12627
|
+
const anyDecimal = resolved.some(
|
|
12628
|
+
(argument2) => isPrimitive(argument2.type, "decimal")
|
|
12629
|
+
);
|
|
12630
|
+
const settled = !anyDecimal ? resolved : resolved.map((argument2, index) => {
|
|
12631
|
+
const ast = requiredAt(args, index);
|
|
12632
|
+
if (!isContextualNumericLiteral(ast)) return argument2;
|
|
12633
|
+
return this.resolveExpression(ast, scope, decimalType);
|
|
12634
|
+
});
|
|
12635
|
+
if (anyDecimal && settled.some((argument2) => isPrimitive(argument2.type, "float"))) {
|
|
12636
|
+
throw new CompileError(
|
|
12637
|
+
"Decimal and Float cannot be mixed implicitly; convert explicitly with value.ToDecimal(digits) or value.ToFloat().",
|
|
12638
|
+
pos
|
|
12639
|
+
);
|
|
12640
|
+
}
|
|
12641
|
+
return {
|
|
12642
|
+
arguments: settled,
|
|
12643
|
+
type: settled.reduce(
|
|
12644
|
+
(left, right) => numericResult(left, right.type),
|
|
12645
|
+
{ kind: "primitive", name: "int" }
|
|
12646
|
+
)
|
|
12647
|
+
};
|
|
12648
|
+
}
|
|
12356
12649
|
resolveCall(callee, argumentsList2, scope, pos) {
|
|
12357
12650
|
const variantCall = this.resolveVariantCall(
|
|
12358
12651
|
callee,
|
|
@@ -12446,6 +12739,15 @@ var init_strict_resolver = __esm({
|
|
|
12446
12739
|
);
|
|
12447
12740
|
}
|
|
12448
12741
|
if (callee.receiver.kind === "ident" && !scope.lookup(callee.receiver.name)) {
|
|
12742
|
+
if (callee.receiver.name === MATH_NAMESPACE_NAME) {
|
|
12743
|
+
if (callee.optional) {
|
|
12744
|
+
throw new CompileError(
|
|
12745
|
+
`Optional chaining is not valid on builtin namespace '${MATH_NAMESPACE_NAME}'.`,
|
|
12746
|
+
pos
|
|
12747
|
+
);
|
|
12748
|
+
}
|
|
12749
|
+
return this.resolveMathCall(callee.name, argumentsList2, scope, pos);
|
|
12750
|
+
}
|
|
12449
12751
|
const staticType = this.project.typeByName.get(callee.receiver.name);
|
|
12450
12752
|
if (staticType && staticType.kind !== "enum") {
|
|
12451
12753
|
if (callee.optional) {
|
|
@@ -14306,6 +14608,12 @@ var init_strict_resolver = __esm({
|
|
|
14306
14608
|
resolved = { kind: "primitive", name: type.name };
|
|
14307
14609
|
break;
|
|
14308
14610
|
case "named": {
|
|
14611
|
+
if (type.name === MATH_NAMESPACE_NAME) {
|
|
14612
|
+
throw new CompileError(
|
|
14613
|
+
`'${MATH_NAMESPACE_NAME}' is a builtin namespace, not a type.`,
|
|
14614
|
+
type.pos
|
|
14615
|
+
);
|
|
14616
|
+
}
|
|
14309
14617
|
const builtin = namedPrimitive(type.name);
|
|
14310
14618
|
if (builtin) {
|
|
14311
14619
|
resolved = { kind: "primitive", name: builtin };
|
|
@@ -24110,6 +24418,7 @@ function buildProjectGraph(documents) {
|
|
|
24110
24418
|
...interfaceTypeIds.length ? { interfaceTypeIds } : {},
|
|
24111
24419
|
...typeParameters.length ? { typeParameters } : {},
|
|
24112
24420
|
...classDeclaration?.modifiers.includes("abstract") ? { abstract: true } : {},
|
|
24421
|
+
...classDeclaration?.modifiers.includes("sealed") ? { sealed: true } : {},
|
|
24113
24422
|
location: location(info.uri, info.declaration.range),
|
|
24114
24423
|
selectionLocation: location(info.uri, info.declaration.nameRange)
|
|
24115
24424
|
};
|
|
@@ -24612,10 +24921,23 @@ function accessorBodyRange(source, bodyRange, keyword) {
|
|
|
24612
24921
|
continue;
|
|
24613
24922
|
}
|
|
24614
24923
|
if (depth !== 1 || token.text !== keyword) continue;
|
|
24615
|
-
|
|
24924
|
+
let openIndex = index + 1;
|
|
24925
|
+
if (tokens[openIndex]?.text === "(") {
|
|
24926
|
+
let parameterDepth = 1;
|
|
24927
|
+
for (let cursor = openIndex + 1; cursor < tokens.length; cursor++) {
|
|
24928
|
+
const candidate = tokens[cursor];
|
|
24929
|
+
if (candidate.text === "(") parameterDepth++;
|
|
24930
|
+
if (candidate.text === ")") parameterDepth--;
|
|
24931
|
+
if (parameterDepth !== 0) continue;
|
|
24932
|
+
openIndex = cursor + 1;
|
|
24933
|
+
break;
|
|
24934
|
+
}
|
|
24935
|
+
if (parameterDepth !== 0) return null;
|
|
24936
|
+
}
|
|
24937
|
+
const open = tokens[openIndex];
|
|
24616
24938
|
if (open?.text !== "{") return null;
|
|
24617
24939
|
let accessorDepth = 1;
|
|
24618
|
-
for (let cursor =
|
|
24940
|
+
for (let cursor = openIndex + 1; cursor < tokens.length; cursor++) {
|
|
24619
24941
|
const candidate = tokens[cursor];
|
|
24620
24942
|
if (candidate.text === "{") accessorDepth++;
|
|
24621
24943
|
if (candidate.text === "}") accessorDepth--;
|
|
@@ -26169,7 +26491,7 @@ var init_project_source_type_checker = __esm({
|
|
|
26169
26491
|
]);
|
|
26170
26492
|
BUILTIN_TYPES = /* @__PURE__ */ new Set([
|
|
26171
26493
|
...NEOSCRIPT_PRIMITIVE_TYPES,
|
|
26172
|
-
...
|
|
26494
|
+
...NEOSCRIPT_BUILTIN_ANNOTATION_TYPES,
|
|
26173
26495
|
"void",
|
|
26174
26496
|
"null",
|
|
26175
26497
|
"Project",
|
|
@@ -26187,7 +26509,10 @@ var init_project_source_type_checker = __esm({
|
|
|
26187
26509
|
"NeoAudioClip",
|
|
26188
26510
|
"ProjectRelation"
|
|
26189
26511
|
]);
|
|
26190
|
-
RESERVED_NAMES2 = new Set(
|
|
26512
|
+
RESERVED_NAMES2 = /* @__PURE__ */ new Set([
|
|
26513
|
+
...NEOSCRIPT_KEYWORDS,
|
|
26514
|
+
...NEOSCRIPT_BUILTIN_NAMESPACES
|
|
26515
|
+
]);
|
|
26191
26516
|
}
|
|
26192
26517
|
});
|
|
26193
26518
|
|
|
@@ -27090,7 +27415,7 @@ var init_project_source_analysis = __esm({
|
|
|
27090
27415
|
init_project_source_parameter_defaults();
|
|
27091
27416
|
BUILTIN_TYPE_NAMES = /* @__PURE__ */ new Set([
|
|
27092
27417
|
...NEOSCRIPT_PRIMITIVE_TYPES,
|
|
27093
|
-
...
|
|
27418
|
+
...NEOSCRIPT_BUILTIN_ANNOTATION_TYPES,
|
|
27094
27419
|
"void",
|
|
27095
27420
|
"null",
|
|
27096
27421
|
"Project",
|
|
@@ -27108,7 +27433,10 @@ var init_project_source_analysis = __esm({
|
|
|
27108
27433
|
"NeoAudioClip",
|
|
27109
27434
|
"ProjectRelation"
|
|
27110
27435
|
]);
|
|
27111
|
-
RESERVED_NAMES3 = new Set(
|
|
27436
|
+
RESERVED_NAMES3 = /* @__PURE__ */ new Set([
|
|
27437
|
+
...NEOSCRIPT_KEYWORDS,
|
|
27438
|
+
...NEOSCRIPT_BUILTIN_NAMESPACES
|
|
27439
|
+
]);
|
|
27112
27440
|
SYSTEM_RECORD_ID_PREFIX = "system_";
|
|
27113
27441
|
RFC_4122_UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u;
|
|
27114
27442
|
QUARANTINED_LEGACY_SYSTEM_ID_PREFIXES = [
|
|
@@ -27608,7 +27936,7 @@ function projectFallbackCompletions(analysis, document, position) {
|
|
|
27608
27936
|
}
|
|
27609
27937
|
for (const typeName of [
|
|
27610
27938
|
...NEOSCRIPT_PRIMITIVE_TYPES,
|
|
27611
|
-
...
|
|
27939
|
+
...NEOSCRIPT_BUILTIN_ANNOTATION_TYPES
|
|
27612
27940
|
]) {
|
|
27613
27941
|
if (expression) continue;
|
|
27614
27942
|
items.set(typeName, {
|
|
@@ -31325,6 +31653,7 @@ function schemaClass(value, environment, field) {
|
|
|
31325
31653
|
`${field}.implementsInterfaceIds`
|
|
31326
31654
|
),
|
|
31327
31655
|
...value.declarationModifier === "abstract" ? { abstract: true } : {},
|
|
31656
|
+
...value.isSealed === true ? { sealed: true } : {},
|
|
31328
31657
|
...sourceLocation(value.source, environment, `${field}.source`),
|
|
31329
31658
|
typeParameters: records(
|
|
31330
31659
|
value.genericParameters ?? [],
|
|
@@ -31945,6 +32274,20 @@ function memberType(member, environment, visiting, field) {
|
|
|
31945
32274
|
nullable: false
|
|
31946
32275
|
};
|
|
31947
32276
|
}
|
|
32277
|
+
if (kind === "variant") {
|
|
32278
|
+
const variantClass = [...environment.classes.values()].find(
|
|
32279
|
+
(candidate) => candidate.name === NEO_VARIANT_TYPE_NAME
|
|
32280
|
+
);
|
|
32281
|
+
if (variantClass === void 0) return { ...unknownType(), nullable };
|
|
32282
|
+
return {
|
|
32283
|
+
kind: "named",
|
|
32284
|
+
typeId: string2(variantClass.id, `${field}.variantClass.id`),
|
|
32285
|
+
typeArguments: [
|
|
32286
|
+
manifestType2(member.targetType, environment, `${field}.targetType`)
|
|
32287
|
+
],
|
|
32288
|
+
nullable
|
|
32289
|
+
};
|
|
32290
|
+
}
|
|
31948
32291
|
if (kind === "generic") {
|
|
31949
32292
|
return typeParameter(
|
|
31950
32293
|
string2(member.genericParamId, `${field}.genericParamId`),
|
|
@@ -32487,6 +32830,7 @@ var init_project_schema_manifest = __esm({
|
|
|
32487
32830
|
"use strict";
|
|
32488
32831
|
init_project();
|
|
32489
32832
|
init_project_schema_contract_generated();
|
|
32833
|
+
init_language_spec();
|
|
32490
32834
|
}
|
|
32491
32835
|
});
|
|
32492
32836
|
|
|
@@ -41523,6 +41867,18 @@ function isNSFunctionDecimalOp(value) {
|
|
|
41523
41867
|
const digits = info.digitsPointer;
|
|
41524
41868
|
return digits === void 0 || isNSPointer(digits);
|
|
41525
41869
|
}
|
|
41870
|
+
function isNSFunctionMathOp(value) {
|
|
41871
|
+
const v = value;
|
|
41872
|
+
if (v?.type !== "mathOp" /* mathOp */) return false;
|
|
41873
|
+
const info = v.info;
|
|
41874
|
+
if (typeof info !== "object" || info === null) return false;
|
|
41875
|
+
if (!NS_MATH_OPS.includes(info.op)) return false;
|
|
41876
|
+
const args = info.argPointers;
|
|
41877
|
+
if (!Array.isArray(args)) return false;
|
|
41878
|
+
if (!args.every(isNSPointer)) return false;
|
|
41879
|
+
const decimal2 = info.decimal;
|
|
41880
|
+
return decimal2 === void 0 || decimal2 === true;
|
|
41881
|
+
}
|
|
41526
41882
|
function isNSFunctionCount(value) {
|
|
41527
41883
|
const v = value;
|
|
41528
41884
|
if (v?.type !== "count" /* count */) return false;
|
|
@@ -41570,7 +41926,7 @@ function isNSFunction(value) {
|
|
|
41570
41926
|
return isNSFunctionClassConstructor(value) || isNSFunctionClassClone(value) || isNSFunctionListIndex(value) || isNSFunctionSelect(value) || isNSFunctionFirst(value) || isNSFunctionFirstOrDefault(value) || isNSFunctionWhere(value) || isNSFunctionContains(value) || // stringOp was missing from this chain since its introduction — a
|
|
41571
41927
|
// compiled getter using ToLower()/StartsWith() would fail pointer
|
|
41572
41928
|
// validation anywhere isNSFunction gates. Fixed alongside decimalOp.
|
|
41573
|
-
isNSFunctionStringOp(value) || isNSFunctionDecimalOp(value) || isNSFunctionCount(value) || isNSFunctionVisitCount(value) || isNSFunctionHasVisited(value) || isNSFunctionVectorConstructor(value) || isNSFunctionImageSlice(value) || isNSFunctionVariantInitialize(value) || isNSFunctionVariantApply(value) || isNSFunctionDeclaredConstructor(value);
|
|
41929
|
+
isNSFunctionStringOp(value) || isNSFunctionDecimalOp(value) || isNSFunctionMathOp(value) || isNSFunctionCount(value) || isNSFunctionVisitCount(value) || isNSFunctionHasVisited(value) || isNSFunctionVectorConstructor(value) || isNSFunctionImageSlice(value) || isNSFunctionVariantInitialize(value) || isNSFunctionVariantApply(value) || isNSFunctionDeclaredConstructor(value);
|
|
41574
41930
|
}
|
|
41575
41931
|
function isNSInstructionVariable(value) {
|
|
41576
41932
|
const v = value;
|
|
@@ -41861,7 +42217,7 @@ function isNSVoidBody(value) {
|
|
|
41861
42217
|
if (value.typeInfo.type !== 0 /* Null */) return false;
|
|
41862
42218
|
return value.typeInfo.required === true;
|
|
41863
42219
|
}
|
|
41864
|
-
var NS_STRING_OPS, NS_DECIMAL_OPS;
|
|
42220
|
+
var NS_STRING_OPS, NS_DECIMAL_OPS, NS_MATH_OPS;
|
|
41865
42221
|
var init_neoscript_guards = __esm({
|
|
41866
42222
|
"../src/models/neoscript/neoscript-guards.ts"() {
|
|
41867
42223
|
"use strict";
|
|
@@ -41882,6 +42238,18 @@ var init_neoscript_guards = __esm({
|
|
|
41882
42238
|
"toFloat",
|
|
41883
42239
|
"toDecimal"
|
|
41884
42240
|
];
|
|
42241
|
+
NS_MATH_OPS = [
|
|
42242
|
+
"min",
|
|
42243
|
+
"max",
|
|
42244
|
+
"clamp",
|
|
42245
|
+
"round",
|
|
42246
|
+
"floor",
|
|
42247
|
+
"ceiling",
|
|
42248
|
+
"truncate",
|
|
42249
|
+
"abs",
|
|
42250
|
+
"sign",
|
|
42251
|
+
"sqrt"
|
|
42252
|
+
];
|
|
41885
42253
|
}
|
|
41886
42254
|
});
|
|
41887
42255
|
|
|
@@ -46337,6 +46705,23 @@ var init_member_kinds_db_response = __esm({
|
|
|
46337
46705
|
});
|
|
46338
46706
|
|
|
46339
46707
|
// ../src/models/members/unordered-list-membership.ts
|
|
46708
|
+
function buildUnorderedListMembershipIndex(values) {
|
|
46709
|
+
const membersByContainerId = /* @__PURE__ */ new Map();
|
|
46710
|
+
for (const candidate of values) {
|
|
46711
|
+
const containerId = candidate.containerId;
|
|
46712
|
+
if (typeof containerId !== "string") continue;
|
|
46713
|
+
const bucket = membersByContainerId.get(containerId);
|
|
46714
|
+
if (bucket === void 0) {
|
|
46715
|
+
membersByContainerId.set(containerId, [candidate.id]);
|
|
46716
|
+
} else {
|
|
46717
|
+
bucket.push(candidate.id);
|
|
46718
|
+
}
|
|
46719
|
+
}
|
|
46720
|
+
for (const bucket of membersByContainerId.values()) {
|
|
46721
|
+
bucket.sort();
|
|
46722
|
+
}
|
|
46723
|
+
return membersByContainerId;
|
|
46724
|
+
}
|
|
46340
46725
|
function unorderedListEntryIds(values, listValue2, membershipIndex) {
|
|
46341
46726
|
if (!Array.isArray(listValue2.value)) return [];
|
|
46342
46727
|
if (membershipIndex !== void 0) {
|
|
@@ -63028,6 +63413,25 @@ function compareDecimalStrings(a, b) {
|
|
|
63028
63413
|
if (aligned.a > aligned.b) return 1;
|
|
63029
63414
|
return 0;
|
|
63030
63415
|
}
|
|
63416
|
+
function minDecimalStrings(a, b) {
|
|
63417
|
+
return compareDecimalStrings(a, b) <= 0 ? a : b;
|
|
63418
|
+
}
|
|
63419
|
+
function maxDecimalStrings(a, b) {
|
|
63420
|
+
return compareDecimalStrings(a, b) >= 0 ? a : b;
|
|
63421
|
+
}
|
|
63422
|
+
function clampDecimalStrings(value, min, max) {
|
|
63423
|
+
if (compareDecimalStrings(min, max) > 0) {
|
|
63424
|
+
throw new DecimalClampRangeError(MATH_CLAMP_RANGE_MESSAGE);
|
|
63425
|
+
}
|
|
63426
|
+
if (compareDecimalStrings(value, min) < 0) return min;
|
|
63427
|
+
if (compareDecimalStrings(value, max) > 0) return max;
|
|
63428
|
+
return value;
|
|
63429
|
+
}
|
|
63430
|
+
function absDecimalString(value) {
|
|
63431
|
+
const parts = parseDecimalArg(value, "value");
|
|
63432
|
+
const magnitude = parts.coefficient < 0n ? -parts.coefficient : parts.coefficient;
|
|
63433
|
+
return formatDecimalParts({ coefficient: magnitude, scale: parts.scale });
|
|
63434
|
+
}
|
|
63031
63435
|
function addDecimalStrings(a, b) {
|
|
63032
63436
|
const aligned = alignScales(parseDecimalArg(a, "a"), parseDecimalArg(b, "b"));
|
|
63033
63437
|
return formatDecimalParts(
|
|
@@ -63090,6 +63494,32 @@ function roundDecimalString(value, digits) {
|
|
|
63090
63494
|
const rounded = roundParts(parseDecimalArg(value, "value"), digits);
|
|
63091
63495
|
return formatDecimalParts(assertWithinEnvelope(rounded, "round"));
|
|
63092
63496
|
}
|
|
63497
|
+
function toIntegralParts(parts, direction) {
|
|
63498
|
+
if (parts.scale === 0) return parts;
|
|
63499
|
+
const divisor = pow10(parts.scale);
|
|
63500
|
+
const quotient = parts.coefficient / divisor;
|
|
63501
|
+
const remainder = parts.coefficient % divisor;
|
|
63502
|
+
if (remainder === 0n) return { coefficient: quotient, scale: 0 };
|
|
63503
|
+
if (direction === "floor" && remainder < 0n) {
|
|
63504
|
+
return { coefficient: quotient - 1n, scale: 0 };
|
|
63505
|
+
}
|
|
63506
|
+
if (direction === "ceiling" && remainder > 0n) {
|
|
63507
|
+
return { coefficient: quotient + 1n, scale: 0 };
|
|
63508
|
+
}
|
|
63509
|
+
return { coefficient: quotient, scale: 0 };
|
|
63510
|
+
}
|
|
63511
|
+
function floorDecimalString(value) {
|
|
63512
|
+
const parts = toIntegralParts(parseDecimalArg(value, "value"), "floor");
|
|
63513
|
+
return formatDecimalParts(assertWithinEnvelope(parts, "floor"));
|
|
63514
|
+
}
|
|
63515
|
+
function ceilingDecimalString(value) {
|
|
63516
|
+
const parts = toIntegralParts(parseDecimalArg(value, "value"), "ceiling");
|
|
63517
|
+
return formatDecimalParts(assertWithinEnvelope(parts, "ceiling"));
|
|
63518
|
+
}
|
|
63519
|
+
function truncateDecimalString(value) {
|
|
63520
|
+
const parts = toIntegralParts(parseDecimalArg(value, "value"), "truncate");
|
|
63521
|
+
return formatDecimalParts(assertWithinEnvelope(parts, "truncate"));
|
|
63522
|
+
}
|
|
63093
63523
|
function divideDecimalStrings(a, b, digits) {
|
|
63094
63524
|
assertDigitsInRange(digits, "divide");
|
|
63095
63525
|
const dividend = parseDecimalArg(a, "a");
|
|
@@ -63170,7 +63600,7 @@ function floatFromDecimalString(value) {
|
|
|
63170
63600
|
assertCanonicalInput(value, "value");
|
|
63171
63601
|
return Number(value);
|
|
63172
63602
|
}
|
|
63173
|
-
var DecimalOverflowError, DecimalDivisionByZeroError, DecimalDigitsRangeError, DecimalNonFiniteError, TEN;
|
|
63603
|
+
var DecimalOverflowError, DecimalDivisionByZeroError, DecimalDigitsRangeError, DecimalNonFiniteError, DecimalClampRangeError, MATH_CLAMP_RANGE_MESSAGE, TEN;
|
|
63174
63604
|
var init_decimal_math = __esm({
|
|
63175
63605
|
"../src/models/decimal/decimal-math.ts"() {
|
|
63176
63606
|
"use strict";
|
|
@@ -63183,6 +63613,9 @@ var init_decimal_math = __esm({
|
|
|
63183
63613
|
};
|
|
63184
63614
|
DecimalNonFiniteError = class extends Error {
|
|
63185
63615
|
};
|
|
63616
|
+
DecimalClampRangeError = class extends Error {
|
|
63617
|
+
};
|
|
63618
|
+
MATH_CLAMP_RANGE_MESSAGE = "Math.Clamp requires min <= max.";
|
|
63186
63619
|
TEN = 10n;
|
|
63187
63620
|
}
|
|
63188
63621
|
});
|
|
@@ -63887,9 +64320,11 @@ function makeEvaluatorLookups(members, values, options = {}) {
|
|
|
63887
64320
|
for (const a of members) attrMap.set(a.id, a);
|
|
63888
64321
|
const valMap = /* @__PURE__ */ new Map();
|
|
63889
64322
|
for (const v of values) valMap.set(v.id, v);
|
|
64323
|
+
const unorderedListMembership = buildUnorderedListMembershipIndex(values);
|
|
63890
64324
|
const lookups = {
|
|
63891
64325
|
memberById: (id2) => attrMap.get(id2) ?? null,
|
|
63892
|
-
valueById: (id2) => valMap.get(id2) ?? null
|
|
64326
|
+
valueById: (id2) => valMap.get(id2) ?? null,
|
|
64327
|
+
unorderedListEntryIds: (containerValueId) => unorderedListMembership.get(containerValueId) ?? []
|
|
63893
64328
|
};
|
|
63894
64329
|
if (options.includeValueGraphIndexes === true) {
|
|
63895
64330
|
return {
|
|
@@ -67836,9 +68271,24 @@ function resolveValueIfIdForMember(at, member, ctx) {
|
|
|
67836
68271
|
);
|
|
67837
68272
|
if (!row) return at;
|
|
67838
68273
|
ctx.valueDependencies?.add(row.id);
|
|
68274
|
+
if (isMemberListBase(member) && member.listKind === "unordered" && Array.isArray(row.value)) {
|
|
68275
|
+
return evaluatorUnorderedListEntryIds(row.id, ctx);
|
|
68276
|
+
}
|
|
67839
68277
|
const value = resolveLocalizedRowValueForMember(row, member, ctx);
|
|
67840
68278
|
return shouldUnwrapSingleLookupValue(member) ? unwrapSingleLookupValue(value, ctx) : value;
|
|
67841
68279
|
}
|
|
68280
|
+
function evaluatorUnorderedListEntryIds(containerValueId, ctx) {
|
|
68281
|
+
const runtimeRows = [...ctx.__runtimeSessionValues?.values() ?? []];
|
|
68282
|
+
const overlayRows = [...ctx.__valueOverlay?.values() ?? []];
|
|
68283
|
+
const localRows = [...runtimeRows, ...overlayRows];
|
|
68284
|
+
const shadowedIds = new Set(localRows.map((row) => row.id));
|
|
68285
|
+
const baseIds = ctx.vm.databaseVM?.unorderedListEntryIds?.(containerValueId) ?? ctx.vm.values.filter((row) => row.containerId === containerValueId).map((row) => row.id);
|
|
68286
|
+
const ids = new Set(baseIds.filter((id2) => !shadowedIds.has(id2)));
|
|
68287
|
+
for (const row of localRows) {
|
|
68288
|
+
if (row.containerId === containerValueId) ids.add(row.id);
|
|
68289
|
+
}
|
|
68290
|
+
return [...ids].sort();
|
|
68291
|
+
}
|
|
67842
68292
|
function shouldUnwrapSingleLookupValue(member) {
|
|
67843
68293
|
if (member === null) return false;
|
|
67844
68294
|
if (!isMemberLookup(member)) return false;
|
|
@@ -68054,7 +68504,7 @@ function coerceDecimalOperand(value, context) {
|
|
|
68054
68504
|
);
|
|
68055
68505
|
}
|
|
68056
68506
|
function rethrowDecimalError(error) {
|
|
68057
|
-
if (error instanceof DecimalOverflowError || error instanceof DecimalDivisionByZeroError || error instanceof DecimalDigitsRangeError || error instanceof DecimalNonFiniteError) {
|
|
68507
|
+
if (error instanceof DecimalOverflowError || error instanceof DecimalDivisionByZeroError || error instanceof DecimalDigitsRangeError || error instanceof DecimalNonFiniteError || error instanceof DecimalClampRangeError) {
|
|
68058
68508
|
throw new NSGetterRuntimeError(error.message);
|
|
68059
68509
|
}
|
|
68060
68510
|
throw error;
|
|
@@ -68081,6 +68531,163 @@ function applyDecimalArithmetic(op, operands) {
|
|
|
68081
68531
|
rethrowDecimalError(error);
|
|
68082
68532
|
}
|
|
68083
68533
|
}
|
|
68534
|
+
function mathArgPointer(info, index, fn) {
|
|
68535
|
+
const pointer = info.argPointers[index];
|
|
68536
|
+
if (pointer === void 0) {
|
|
68537
|
+
throw new NSGetterRuntimeError(
|
|
68538
|
+
`Math.${fn} is missing argument ${index + 1}.`
|
|
68539
|
+
);
|
|
68540
|
+
}
|
|
68541
|
+
return pointer;
|
|
68542
|
+
}
|
|
68543
|
+
function mathNumberArg(value, fn) {
|
|
68544
|
+
if (value === null || value === void 0) {
|
|
68545
|
+
throw new NSGetterRuntimeError(`Math.${fn} argument is null.`);
|
|
68546
|
+
}
|
|
68547
|
+
if (typeof value !== "number") {
|
|
68548
|
+
throw new NSGetterRuntimeError(
|
|
68549
|
+
`Math.${fn} argument is not numeric: ${typeof value}.`
|
|
68550
|
+
);
|
|
68551
|
+
}
|
|
68552
|
+
return value;
|
|
68553
|
+
}
|
|
68554
|
+
function mathDecimalArg(value, fn) {
|
|
68555
|
+
if (value === null || value === void 0) {
|
|
68556
|
+
throw new NSGetterRuntimeError(`Math.${fn} argument is null.`);
|
|
68557
|
+
}
|
|
68558
|
+
if (typeof value !== "string" && typeof value !== "number") {
|
|
68559
|
+
throw new NSGetterRuntimeError(
|
|
68560
|
+
`Math.${fn} argument is not numeric: ${typeof value}.`
|
|
68561
|
+
);
|
|
68562
|
+
}
|
|
68563
|
+
return coerceDecimalOperand(value, `Math.${fn}`);
|
|
68564
|
+
}
|
|
68565
|
+
function requireFiniteMathArg(value, fn) {
|
|
68566
|
+
if (!Number.isFinite(value)) {
|
|
68567
|
+
throw new NSGetterRuntimeError(`Math.${fn} requires a finite argument.`);
|
|
68568
|
+
}
|
|
68569
|
+
return value;
|
|
68570
|
+
}
|
|
68571
|
+
function roundHalfEven(value) {
|
|
68572
|
+
if (Math.abs(value) >= DOUBLE_INTEGRAL_MAGNITUDE) return value;
|
|
68573
|
+
const integral = Math.floor(value);
|
|
68574
|
+
const fraction = value - integral;
|
|
68575
|
+
if (fraction > 0.5) return integral + 1;
|
|
68576
|
+
if (fraction < 0.5) return integral;
|
|
68577
|
+
if (integral % 2 === 0) return integral;
|
|
68578
|
+
return integral + 1;
|
|
68579
|
+
}
|
|
68580
|
+
function evalMathOp(info, scope, ctx) {
|
|
68581
|
+
const fn = NS_MATH_OP_NAMES[info.op];
|
|
68582
|
+
if (info.decimal === true) return evalDecimalMathOp(info, fn, scope, ctx);
|
|
68583
|
+
const value = mathNumberArg(
|
|
68584
|
+
evalPointer(mathArgPointer(info, 0, fn), scope, ctx),
|
|
68585
|
+
fn
|
|
68586
|
+
);
|
|
68587
|
+
switch (info.op) {
|
|
68588
|
+
case "min":
|
|
68589
|
+
return Math.min(
|
|
68590
|
+
value,
|
|
68591
|
+
mathNumberArg(evalPointer(mathArgPointer(info, 1, fn), scope, ctx), fn)
|
|
68592
|
+
);
|
|
68593
|
+
case "max":
|
|
68594
|
+
return Math.max(
|
|
68595
|
+
value,
|
|
68596
|
+
mathNumberArg(evalPointer(mathArgPointer(info, 1, fn), scope, ctx), fn)
|
|
68597
|
+
);
|
|
68598
|
+
case "clamp": {
|
|
68599
|
+
const min = mathNumberArg(
|
|
68600
|
+
evalPointer(mathArgPointer(info, 1, fn), scope, ctx),
|
|
68601
|
+
fn
|
|
68602
|
+
);
|
|
68603
|
+
const max = mathNumberArg(
|
|
68604
|
+
evalPointer(mathArgPointer(info, 2, fn), scope, ctx),
|
|
68605
|
+
fn
|
|
68606
|
+
);
|
|
68607
|
+
if (min > max) {
|
|
68608
|
+
throw new NSGetterRuntimeError(MATH_CLAMP_RANGE_MESSAGE);
|
|
68609
|
+
}
|
|
68610
|
+
if (value < min) return min;
|
|
68611
|
+
if (value > max) return max;
|
|
68612
|
+
return value;
|
|
68613
|
+
}
|
|
68614
|
+
case "round":
|
|
68615
|
+
return roundHalfEven(requireFiniteMathArg(value, fn));
|
|
68616
|
+
case "floor":
|
|
68617
|
+
return Math.floor(requireFiniteMathArg(value, fn));
|
|
68618
|
+
case "ceiling":
|
|
68619
|
+
return Math.ceil(requireFiniteMathArg(value, fn));
|
|
68620
|
+
case "truncate":
|
|
68621
|
+
return Math.trunc(requireFiniteMathArg(value, fn));
|
|
68622
|
+
case "abs":
|
|
68623
|
+
return Math.abs(value);
|
|
68624
|
+
case "sign":
|
|
68625
|
+
if (Number.isNaN(value)) {
|
|
68626
|
+
throw new NSGetterRuntimeError("Math.Sign is undefined for NaN.");
|
|
68627
|
+
}
|
|
68628
|
+
if (value > 0) return 1;
|
|
68629
|
+
if (value < 0) return -1;
|
|
68630
|
+
return 0;
|
|
68631
|
+
case "sqrt":
|
|
68632
|
+
return Math.sqrt(value);
|
|
68633
|
+
}
|
|
68634
|
+
}
|
|
68635
|
+
function evalDecimalMathOp(info, fn, scope, ctx) {
|
|
68636
|
+
const value = mathDecimalArg(
|
|
68637
|
+
evalPointer(mathArgPointer(info, 0, fn), scope, ctx),
|
|
68638
|
+
fn
|
|
68639
|
+
);
|
|
68640
|
+
try {
|
|
68641
|
+
switch (info.op) {
|
|
68642
|
+
case "min":
|
|
68643
|
+
return minDecimalStrings(
|
|
68644
|
+
value,
|
|
68645
|
+
mathDecimalArg(
|
|
68646
|
+
evalPointer(mathArgPointer(info, 1, fn), scope, ctx),
|
|
68647
|
+
fn
|
|
68648
|
+
)
|
|
68649
|
+
);
|
|
68650
|
+
case "max":
|
|
68651
|
+
return maxDecimalStrings(
|
|
68652
|
+
value,
|
|
68653
|
+
mathDecimalArg(
|
|
68654
|
+
evalPointer(mathArgPointer(info, 1, fn), scope, ctx),
|
|
68655
|
+
fn
|
|
68656
|
+
)
|
|
68657
|
+
);
|
|
68658
|
+
case "clamp":
|
|
68659
|
+
return clampDecimalStrings(
|
|
68660
|
+
value,
|
|
68661
|
+
mathDecimalArg(
|
|
68662
|
+
evalPointer(mathArgPointer(info, 1, fn), scope, ctx),
|
|
68663
|
+
fn
|
|
68664
|
+
),
|
|
68665
|
+
mathDecimalArg(
|
|
68666
|
+
evalPointer(mathArgPointer(info, 2, fn), scope, ctx),
|
|
68667
|
+
fn
|
|
68668
|
+
)
|
|
68669
|
+
);
|
|
68670
|
+
case "round":
|
|
68671
|
+
return roundDecimalString(value, 0);
|
|
68672
|
+
case "floor":
|
|
68673
|
+
return floorDecimalString(value);
|
|
68674
|
+
case "ceiling":
|
|
68675
|
+
return ceilingDecimalString(value);
|
|
68676
|
+
case "truncate":
|
|
68677
|
+
return truncateDecimalString(value);
|
|
68678
|
+
case "abs":
|
|
68679
|
+
return absDecimalString(value);
|
|
68680
|
+
case "sign":
|
|
68681
|
+
return compareDecimalStrings(value, "0");
|
|
68682
|
+
case "sqrt":
|
|
68683
|
+
throw new NSGetterRuntimeError(
|
|
68684
|
+
"Math.Sqrt does not accept decimal arguments."
|
|
68685
|
+
);
|
|
68686
|
+
}
|
|
68687
|
+
} catch (error) {
|
|
68688
|
+
rethrowDecimalError(error);
|
|
68689
|
+
}
|
|
68690
|
+
}
|
|
68084
68691
|
function stringifyForInterp(v) {
|
|
68085
68692
|
if (v === null || v === void 0) return "";
|
|
68086
68693
|
if (typeof v === "string") return v;
|
|
@@ -68600,6 +69207,8 @@ function evalFunction(fn, scope, ctx) {
|
|
|
68600
69207
|
}
|
|
68601
69208
|
break;
|
|
68602
69209
|
}
|
|
69210
|
+
case "mathOp" /* mathOp */:
|
|
69211
|
+
return evalMathOp(fn.info, scope, ctx);
|
|
68603
69212
|
case "stringOp" /* stringOp */: {
|
|
68604
69213
|
const receiver = evalPointer(fn.info.receiverPointer, scope, ctx);
|
|
68605
69214
|
if (typeof receiver !== "string") {
|
|
@@ -71812,7 +72421,7 @@ function iterateCollection(c, ctx, callback) {
|
|
|
71812
72421
|
return callback(entry, key, valueId);
|
|
71813
72422
|
});
|
|
71814
72423
|
}
|
|
71815
|
-
var DELEGATE_LEXICAL_THIS, DELEGATE_LEXICAL_ROOT, NonCatchableNSGetterRuntimeError, NativeFunctionDelegateUnavailableError, CorruptNeoScriptIRError, NeoScriptResourceLimitError, NeoScriptWallClockTimeoutError, DEFAULT_NEO_SCRIPT_EXECUTION_BUDGET_LIMITS, liveListIndexesByProject, evaluatorOwnershipCachesByBase, MAX_CONSTRUCTION_DEPTH, MAX_LOOP_ITERATIONS, resolutionCacheByMembers, NO_SCHEMA_REVISION, LazyValueOverlay, READONLY_FOREACH_BINDING_ERROR, READONLY_CATCH_BINDING_ERROR, EMPTY_SUPPLIED_CONSTRUCTOR_FIELDS;
|
|
72424
|
+
var DELEGATE_LEXICAL_THIS, DELEGATE_LEXICAL_ROOT, NonCatchableNSGetterRuntimeError, NativeFunctionDelegateUnavailableError, CorruptNeoScriptIRError, NeoScriptResourceLimitError, NeoScriptWallClockTimeoutError, DEFAULT_NEO_SCRIPT_EXECUTION_BUDGET_LIMITS, liveListIndexesByProject, evaluatorOwnershipCachesByBase, MAX_CONSTRUCTION_DEPTH, MAX_LOOP_ITERATIONS, resolutionCacheByMembers, NO_SCHEMA_REVISION, LazyValueOverlay, READONLY_FOREACH_BINDING_ERROR, READONLY_CATCH_BINDING_ERROR, NS_MATH_OP_NAMES, DOUBLE_INTEGRAL_MAGNITUDE, EMPTY_SUPPLIED_CONSTRUCTOR_FIELDS;
|
|
71816
72425
|
var init_evaluateNSGetter = __esm({
|
|
71817
72426
|
"../src/view-models/neoscript-evaluator/evaluateNSGetter.ts"() {
|
|
71818
72427
|
"use strict";
|
|
@@ -71956,6 +72565,19 @@ var init_evaluateNSGetter = __esm({
|
|
|
71956
72565
|
};
|
|
71957
72566
|
READONLY_FOREACH_BINDING_ERROR = "Cannot assign to a read-only foreach iterator binding.";
|
|
71958
72567
|
READONLY_CATCH_BINDING_ERROR = "Cannot assign to a read-only catch message binding.";
|
|
72568
|
+
NS_MATH_OP_NAMES = {
|
|
72569
|
+
min: "Min",
|
|
72570
|
+
max: "Max",
|
|
72571
|
+
clamp: "Clamp",
|
|
72572
|
+
round: "Round",
|
|
72573
|
+
floor: "Floor",
|
|
72574
|
+
ceiling: "Ceiling",
|
|
72575
|
+
truncate: "Truncate",
|
|
72576
|
+
abs: "Abs",
|
|
72577
|
+
sign: "Sign",
|
|
72578
|
+
sqrt: "Sqrt"
|
|
72579
|
+
};
|
|
72580
|
+
DOUBLE_INTEGRAL_MAGNITUDE = 2 ** 53;
|
|
71959
72581
|
EMPTY_SUPPLIED_CONSTRUCTOR_FIELDS = [];
|
|
71960
72582
|
}
|
|
71961
72583
|
});
|
|
@@ -71980,7 +72602,7 @@ function initializerEvaluatorLookups(document) {
|
|
|
71980
72602
|
});
|
|
71981
72603
|
return lookups;
|
|
71982
72604
|
}
|
|
71983
|
-
function
|
|
72605
|
+
function buildInitializerRootValueWithLookups(document, lookups) {
|
|
71984
72606
|
const rootValue = {};
|
|
71985
72607
|
for (const { root, memberId } of projectRootMembersInDisplayOrder(
|
|
71986
72608
|
document.project
|
|
@@ -72020,7 +72642,7 @@ function evaluateMemberInitializer(args) {
|
|
|
72020
72642
|
databaseVM
|
|
72021
72643
|
},
|
|
72022
72644
|
thisValue: null,
|
|
72023
|
-
rootValue:
|
|
72645
|
+
rootValue: buildInitializerRootValueWithLookups(args.document, databaseVM),
|
|
72024
72646
|
saveStaticBindings: args.saveStaticBindings,
|
|
72025
72647
|
sessionStaticBindings: args.sessionStaticBindings,
|
|
72026
72648
|
...args.storedConstructionReplay === true ? {
|
|
@@ -111630,7 +112252,7 @@ var init_registry2 = __esm({
|
|
|
111630
112252
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
111631
112253
|
formatVersion: 3,
|
|
111632
112254
|
contractVersion: "3.13",
|
|
111633
|
-
cliVersion: "0.
|
|
112255
|
+
cliVersion: "0.32.0",
|
|
111634
112256
|
projectFileUploadBatchSize: 32,
|
|
111635
112257
|
documentRecords: {
|
|
111636
112258
|
member: {
|
|
@@ -118225,7 +118847,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
118225
118847
|
async function main() {
|
|
118226
118848
|
const args = parseArgs(process.argv.slice(2));
|
|
118227
118849
|
if (args.command === "--version") {
|
|
118228
|
-
console.log("0.
|
|
118850
|
+
console.log("0.32.0");
|
|
118229
118851
|
return;
|
|
118230
118852
|
}
|
|
118231
118853
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@ description: >-
|
|
|
9
9
|
`@neocompose/cli` or `node cli/bin/neo.mjs` in the neo-compose repository.
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
<!-- reviewed-through-cli: 0.
|
|
12
|
+
<!-- reviewed-through-cli: 0.32.0 -->
|
|
13
13
|
|
|
14
14
|
# Neo Compose CLI
|
|
15
15
|
|
|
@@ -138,7 +138,8 @@ completely before editing:
|
|
|
138
138
|
variant folders, partial animation overrides, segments, tracks, and NeoFlow
|
|
139
139
|
dialogues.
|
|
140
140
|
- [NeoScript](references/neoscript.md): inline bodies, snippets, nullability,
|
|
141
|
-
loops, switch, try/catch, ownership, evaluation, and
|
|
141
|
+
numeric builtins, loops, switch, try/catch, ownership, evaluation, and
|
|
142
|
+
migrations.
|
|
142
143
|
- [Commands and synchronization](references/commands-and-sync.md): pull/push,
|
|
143
144
|
conflicts, low-level repair, branches, releases, and history.
|
|
144
145
|
- [CLI development](references/cli-development.md): implementation source of
|
|
@@ -83,7 +83,7 @@ wrappers.
|
|
|
83
83
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
84
84
|
|
|
85
85
|
```html
|
|
86
|
-
<!-- reviewed-through-cli: 0.
|
|
86
|
+
<!-- reviewed-through-cli: 0.32.0 -->
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -7,6 +7,7 @@ runtime ownership, evaluation, and migrations.
|
|
|
7
7
|
|
|
8
8
|
- Inline bodies and snippets
|
|
9
9
|
- Nullability and ownership
|
|
10
|
+
- Numeric builtins
|
|
10
11
|
- Logical operators
|
|
11
12
|
- Loops and transfer
|
|
12
13
|
- Switch
|
|
@@ -56,6 +57,11 @@ or narrowing guard before the next access.
|
|
|
56
57
|
|
|
57
58
|
Treat lookup-return values with the same nullable narrowing rules.
|
|
58
59
|
|
|
60
|
+
Runtime declaration patterns follow the possible runtime type, not only the
|
|
61
|
+
static declaration. An open Class value may match an otherwise unrelated
|
|
62
|
+
interface through a derived Class that implements it; a sealed Class with no
|
|
63
|
+
such relationship remains a compile-time impossible pattern.
|
|
64
|
+
|
|
59
65
|
A declaration pattern introduced by `is` stays available after a guard when
|
|
60
66
|
every path that falls through matched the pattern, including when the guard's
|
|
61
67
|
other paths return from a nested block:
|
|
@@ -76,6 +82,27 @@ Save, Session, Setter, or otherwise writable. A constructor writes only its
|
|
|
76
82
|
`this` instance. A writable structured-leaf field still inherits the receiver's
|
|
77
83
|
effective storage restrictions.
|
|
78
84
|
|
|
85
|
+
## Numeric builtins
|
|
86
|
+
|
|
87
|
+
Use the `Math` namespace for numeric utilities with C# names and C# semantics:
|
|
88
|
+
`Min`, `Max`, `Clamp`, `Round`, `Floor`, `Ceiling`, `Truncate`, `Abs`, `Sign`,
|
|
89
|
+
`Sqrt`, and the `PI` and `E` constants.
|
|
90
|
+
|
|
91
|
+
```neo
|
|
92
|
+
return Math.Clamp(this.Quality + bonus, 0, 10);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Each result follows the arithmetic join of its argument types: all-`int` gives
|
|
96
|
+
`int`, any `float` gives `float`, any `decimal` gives `decimal`, and `decimal`
|
|
97
|
+
never mixes with `float`. `Round`, `Floor`, `Ceiling`, and `Truncate` are the
|
|
98
|
+
language's `float`-to-`int` conversions: they return `int` for `int` and
|
|
99
|
+
`float` input, keep a `decimal` a `decimal`, and reject a non-finite argument
|
|
100
|
+
at runtime. `Round` rounds midpoints to even, matching `decimal.Round(0)`.
|
|
101
|
+
`Sign` always returns `int`; `Sqrt` takes `int` or `float` only.
|
|
102
|
+
|
|
103
|
+
`Math` is a qualifier, never a type or a value, and the name is reserved: no
|
|
104
|
+
Class, enum, member, parameter, or local may be named `Math`.
|
|
105
|
+
|
|
79
106
|
## Logical operators
|
|
80
107
|
|
|
81
108
|
Use `&&` and `||` with C# precedence: `&&` binds tighter than `||`, and
|