@neocompose/cli 0.65.1 → 0.67.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 +16 -0
- package/dist/neo.mjs +686 -115
- package/dist/test-worker.mjs +140 -51
- package/package.json +1 -1
- package/skills/neocompose-cli/SKILL.md +1 -1
- package/skills/neocompose-cli/references/cli-development.md +1 -1
- package/skills/neocompose-cli/references/declarations-and-construction.md +10 -0
- package/skills/neocompose-cli/references/neoscript.md +8 -0
package/dist/test-worker.mjs
CHANGED
|
@@ -1755,7 +1755,7 @@ var TEST_GLOBALS = [
|
|
|
1755
1755
|
];
|
|
1756
1756
|
|
|
1757
1757
|
// ../packages/neoscript-language/src/strict-ir.ts
|
|
1758
|
-
var NEOSCRIPT_COMPILER_REVISION =
|
|
1758
|
+
var NEOSCRIPT_COMPILER_REVISION = 17;
|
|
1759
1759
|
|
|
1760
1760
|
// ../src/models/members/member-storage.ts
|
|
1761
1761
|
function isMemberStorageKind(value) {
|
|
@@ -2124,7 +2124,8 @@ var SystemProtectionKind = {
|
|
|
2124
2124
|
DialogueMemoryContainer: "dialogueMemoryContainer",
|
|
2125
2125
|
DialoguePriorityDefault: "dialoguePriorityDefault",
|
|
2126
2126
|
PolicyImmutable: "policyImmutable",
|
|
2127
|
-
PolicyDeleteBlocked: "policyDeleteBlocked"
|
|
2127
|
+
PolicyDeleteBlocked: "policyDeleteBlocked",
|
|
2128
|
+
ScriptRuntime: "scriptRuntime"
|
|
2128
2129
|
};
|
|
2129
2130
|
function isWithId(value) {
|
|
2130
2131
|
return typeof value?.id === "string";
|
|
@@ -2141,7 +2142,7 @@ function isEpochMillis(value) {
|
|
|
2141
2142
|
return Number.isFinite(value);
|
|
2142
2143
|
}
|
|
2143
2144
|
function isSystemProtectionKind(value) {
|
|
2144
|
-
return value === SystemProtectionKind.WorldAuthoring || value === SystemProtectionKind.DialogueMemorySchema || value === SystemProtectionKind.DialogueMemoryContainer || value === SystemProtectionKind.DialoguePriorityDefault || value === SystemProtectionKind.PolicyImmutable || value === SystemProtectionKind.PolicyDeleteBlocked;
|
|
2145
|
+
return value === SystemProtectionKind.WorldAuthoring || value === SystemProtectionKind.DialogueMemorySchema || value === SystemProtectionKind.DialogueMemoryContainer || value === SystemProtectionKind.DialoguePriorityDefault || value === SystemProtectionKind.PolicyImmutable || value === SystemProtectionKind.PolicyDeleteBlocked || value === SystemProtectionKind.ScriptRuntime;
|
|
2145
2146
|
}
|
|
2146
2147
|
function isSystemMetadata(value) {
|
|
2147
2148
|
const v = value;
|
|
@@ -2166,6 +2167,11 @@ function isValidDocsText(value) {
|
|
|
2166
2167
|
return textEncoder.encode(value).byteLength <= DOCS_TEXT_MAX_UTF8_BYTES;
|
|
2167
2168
|
}
|
|
2168
2169
|
|
|
2170
|
+
// ../src/models/members/float32.ts
|
|
2171
|
+
function isFloat32(value) {
|
|
2172
|
+
return typeof value === "number" && Number.isFinite(value) && Math.fround(value) === value;
|
|
2173
|
+
}
|
|
2174
|
+
|
|
2169
2175
|
// ../packages/neoscript-language/src/project-source-identifiers.ts
|
|
2170
2176
|
var PROJECT_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
2171
2177
|
var PROJECT_RESERVED_NAMES = /* @__PURE__ */ new Set([
|
|
@@ -2506,7 +2512,7 @@ function hasValidParameterDefault(value) {
|
|
|
2506
2512
|
case 2 /* Int */:
|
|
2507
2513
|
return typeof payload === "number" && Number.isInteger(payload);
|
|
2508
2514
|
case 4 /* Float */:
|
|
2509
|
-
return
|
|
2515
|
+
return isFloat32(payload);
|
|
2510
2516
|
case 20 /* Decimal */:
|
|
2511
2517
|
case 3 /* String */:
|
|
2512
2518
|
case 8 /* Enum */:
|
|
@@ -2792,6 +2798,9 @@ function isNSArithmeticOperationInfo(value) {
|
|
|
2792
2798
|
const v = value;
|
|
2793
2799
|
if (typeof v !== "object" || v === null) return false;
|
|
2794
2800
|
if (!isNSArithmeticOperationType(v.type)) return false;
|
|
2801
|
+
if (v.numeric !== void 0 && v.numeric !== "int" && v.numeric !== "float") {
|
|
2802
|
+
return false;
|
|
2803
|
+
}
|
|
2795
2804
|
return isNSPointers(v.pointers);
|
|
2796
2805
|
}
|
|
2797
2806
|
function isNSArithmeticOperation(value) {
|
|
@@ -3702,6 +3711,9 @@ var STRUCTURED_LEAF_FIELDS = {
|
|
|
3702
3711
|
function isStructuredLeafKind(kind) {
|
|
3703
3712
|
return Object.prototype.hasOwnProperty.call(STRUCTURED_LEAF_FIELDS, kind);
|
|
3704
3713
|
}
|
|
3714
|
+
function structuredLeafFields(kind) {
|
|
3715
|
+
return STRUCTURED_LEAF_FIELDS[kind];
|
|
3716
|
+
}
|
|
3705
3717
|
function structuredLeafFieldKeys(kind) {
|
|
3706
3718
|
return STRUCTURED_LEAF_FIELDS[kind].map((entry) => entry.key);
|
|
3707
3719
|
}
|
|
@@ -3714,10 +3726,10 @@ function isStructuredLeafFieldValue(type, value) {
|
|
|
3714
3726
|
return typeof value === "string" && value.length > 0;
|
|
3715
3727
|
}
|
|
3716
3728
|
if (typeof value !== "number" || !Number.isFinite(value)) return false;
|
|
3717
|
-
if (type === "float") return
|
|
3729
|
+
if (type === "float") return isFloat32(value);
|
|
3718
3730
|
if (type === "int") return Number.isInteger(value);
|
|
3719
3731
|
if (type === "sliceIndex") return Number.isInteger(value) && value >= 0;
|
|
3720
|
-
return value >= 0 && value <= 1;
|
|
3732
|
+
return isFloat32(value) && value >= 0 && value <= 1;
|
|
3721
3733
|
}
|
|
3722
3734
|
var STRUCTURED_LEAF_PARTIAL_KEY = "~partial";
|
|
3723
3735
|
function isStructuredLeafPartialValue(value) {
|
|
@@ -3737,16 +3749,36 @@ function structuredLeafPartialViolation(kind, value, legalKeysLabel) {
|
|
|
3737
3749
|
return `has no field "${key}"; ${legalKeysLabel} accepts ${structuredLeafFieldKeys(kind).join(", ")}`;
|
|
3738
3750
|
}
|
|
3739
3751
|
if (isStructuredLeafFieldValue(field.type, fieldValue)) continue;
|
|
3740
|
-
return `field "${key}" ${structuredLeafFieldViolation(field.type)}`;
|
|
3752
|
+
return `field "${key}" ${structuredLeafFieldViolation(field.type, fieldValue)}`;
|
|
3741
3753
|
}
|
|
3742
3754
|
return null;
|
|
3743
3755
|
}
|
|
3744
|
-
function
|
|
3756
|
+
function structuredLeafRecordFieldViolation(kind, value) {
|
|
3757
|
+
if (typeof value !== "object" || value === null) return null;
|
|
3758
|
+
if (Array.isArray(value)) return null;
|
|
3759
|
+
const entries = Object.entries(value);
|
|
3760
|
+
if (entries.length !== structuredLeafFields(kind).length) return null;
|
|
3761
|
+
let found = null;
|
|
3762
|
+
for (const [key, fieldValue] of entries) {
|
|
3763
|
+
const field = structuredLeafField(kind, key);
|
|
3764
|
+
if (field === null) return null;
|
|
3765
|
+
if (typeof fieldValue !== "number") return null;
|
|
3766
|
+
if (found !== null) continue;
|
|
3767
|
+
if (isStructuredLeafFieldValue(field.type, fieldValue)) continue;
|
|
3768
|
+
found = {
|
|
3769
|
+
key,
|
|
3770
|
+
value: fieldValue,
|
|
3771
|
+
violation: structuredLeafFieldViolation(field.type, fieldValue)
|
|
3772
|
+
};
|
|
3773
|
+
}
|
|
3774
|
+
return found;
|
|
3775
|
+
}
|
|
3776
|
+
function structuredLeafFieldViolation(type, value) {
|
|
3745
3777
|
if (type === "fileId") return "must be a non-empty file id";
|
|
3746
|
-
if (type === "float") return "must be a finite number";
|
|
3747
3778
|
if (type === "int") return "must be a whole number";
|
|
3748
3779
|
if (type === "sliceIndex") return "must be a whole number 0 or greater";
|
|
3749
|
-
return "must be a
|
|
3780
|
+
if (!isFloat32(value)) return "must be a 32-bit float";
|
|
3781
|
+
return "must be between 0 and 1";
|
|
3750
3782
|
}
|
|
3751
3783
|
|
|
3752
3784
|
// ../src/models/members/member-kinds.ts
|
|
@@ -3893,9 +3925,9 @@ function isMemberString(value) {
|
|
|
3893
3925
|
function isMemberFloatBase(value) {
|
|
3894
3926
|
const v = asMemberBaseForKind(value, 4 /* Float */);
|
|
3895
3927
|
if (v === null) return false;
|
|
3896
|
-
if (v.minValue !== void 0 && v.minValue !== null &&
|
|
3928
|
+
if (v.minValue !== void 0 && v.minValue !== null && !isFloat32(v.minValue))
|
|
3897
3929
|
return false;
|
|
3898
|
-
if (v.maxValue !== void 0 && v.maxValue !== null &&
|
|
3930
|
+
if (v.maxValue !== void 0 && v.maxValue !== null && !isFloat32(v.maxValue))
|
|
3899
3931
|
return false;
|
|
3900
3932
|
return v.decimalPoints === void 0 || v.decimalPoints === null || typeof v.decimalPoints === "number";
|
|
3901
3933
|
}
|
|
@@ -3904,12 +3936,8 @@ function hasExactKeys(value, keys) {
|
|
|
3904
3936
|
if (actual.length !== keys.length) return false;
|
|
3905
3937
|
return keys.every((key) => Object.prototype.hasOwnProperty.call(value, key));
|
|
3906
3938
|
}
|
|
3907
|
-
function isFiniteNumberValue(value) {
|
|
3908
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
3909
|
-
}
|
|
3910
3939
|
function isVectorComponentValue(value, integer2) {
|
|
3911
|
-
if (!
|
|
3912
|
-
if (!integer2) return true;
|
|
3940
|
+
if (!integer2) return isFloat32(value);
|
|
3913
3941
|
return Number.isInteger(value);
|
|
3914
3942
|
}
|
|
3915
3943
|
function isVector2ValueWithComponents(value, integer2) {
|
|
@@ -3943,7 +3971,7 @@ function isVector3IntValue(value) {
|
|
|
3943
3971
|
return isVector3ValueWithComponents(value, true);
|
|
3944
3972
|
}
|
|
3945
3973
|
function isColorComponentValue(value) {
|
|
3946
|
-
if (!
|
|
3974
|
+
if (!isFloat32(value)) return false;
|
|
3947
3975
|
return value >= 0 && value <= 1;
|
|
3948
3976
|
}
|
|
3949
3977
|
function isColorValue(value) {
|
|
@@ -10037,6 +10065,9 @@ function structuredLeafPartialMemberViolation(member, value, position) {
|
|
|
10037
10065
|
}
|
|
10038
10066
|
return structuredLeafPartialViolation(kind, value, MemberKind[kind]);
|
|
10039
10067
|
}
|
|
10068
|
+
function storedLeafFieldIssueMessage(issue) {
|
|
10069
|
+
return `${MemberKind[issue.leaf]} field "${issue.key}" ${issue.violation}, not ${issue.value}.`;
|
|
10070
|
+
}
|
|
10040
10071
|
function* storedValueChildEntries(args) {
|
|
10041
10072
|
const entryMemberId = args.member.entryMemberId;
|
|
10042
10073
|
if (args.member.kind === 6 /* List */ && typeof entryMemberId === "string") {
|
|
@@ -10070,16 +10101,19 @@ function* storedValueChildEntries(args) {
|
|
|
10070
10101
|
}
|
|
10071
10102
|
function storedLeafShapeIssue(member, value) {
|
|
10072
10103
|
switch (member.kind) {
|
|
10104
|
+
// Null is an optional Float's absent value.
|
|
10105
|
+
case 4 /* Float */:
|
|
10106
|
+
return value === null || isFloat32(value) ? null : { kind: "float" };
|
|
10073
10107
|
case 14 /* Vector2 */:
|
|
10074
|
-
return isVector2Value(value) ? null :
|
|
10108
|
+
return isVector2Value(value) ? null : leafIssue(member.kind, "vector2", value);
|
|
10075
10109
|
case 15 /* Vector2Int */:
|
|
10076
|
-
return isVector2IntValue(value) ? null :
|
|
10110
|
+
return isVector2IntValue(value) ? null : leafIssue(member.kind, "vector2Int", value);
|
|
10077
10111
|
case 16 /* Vector3 */:
|
|
10078
|
-
return isVector3Value(value) ? null :
|
|
10112
|
+
return isVector3Value(value) ? null : leafIssue(member.kind, "vector3", value);
|
|
10079
10113
|
case 17 /* Vector3Int */:
|
|
10080
|
-
return isVector3IntValue(value) ? null :
|
|
10114
|
+
return isVector3IntValue(value) ? null : leafIssue(member.kind, "vector3Int", value);
|
|
10081
10115
|
case 19 /* Color */:
|
|
10082
|
-
return isColorValue(value) ? null :
|
|
10116
|
+
return isColorValue(value) ? null : leafIssue(member.kind, "color", value);
|
|
10083
10117
|
case 20 /* Decimal */: {
|
|
10084
10118
|
const violation = getDecimalStringViolation(value);
|
|
10085
10119
|
return violation === null ? null : { kind: "decimal", violation };
|
|
@@ -10092,6 +10126,10 @@ function storedLeafShapeIssue(member, value) {
|
|
|
10092
10126
|
return null;
|
|
10093
10127
|
}
|
|
10094
10128
|
}
|
|
10129
|
+
function leafIssue(leaf, shape, value) {
|
|
10130
|
+
const field = structuredLeafRecordFieldViolation(leaf, value);
|
|
10131
|
+
return field === null ? { kind: shape } : { kind: "field", leaf, ...field };
|
|
10132
|
+
}
|
|
10095
10133
|
|
|
10096
10134
|
// ../src/models/members/build-default-member-value.ts
|
|
10097
10135
|
var DECLARATION_DEFAULT_POSITION = {
|
|
@@ -11173,16 +11211,24 @@ function validateProjectDocumentFileMemberValue(document2, member, body, positio
|
|
|
11173
11211
|
return;
|
|
11174
11212
|
}
|
|
11175
11213
|
const shapeIssue = storedLeafShapeIssue(member, body.value);
|
|
11214
|
+
if (shapeIssue?.kind === "float") {
|
|
11215
|
+
throw new Error(
|
|
11216
|
+
`Float value for member "${member.name}" must be a 32-bit float, not ${String(body.value)}.`
|
|
11217
|
+
);
|
|
11218
|
+
}
|
|
11219
|
+
if (shapeIssue?.kind === "field") {
|
|
11220
|
+
throw new Error(
|
|
11221
|
+
`Member "${member.name}" ${storedLeafFieldIssueMessage(shapeIssue)}`
|
|
11222
|
+
);
|
|
11223
|
+
}
|
|
11176
11224
|
if (shapeIssue?.kind === "vector2") {
|
|
11177
|
-
throw new Error("Vector2 value must be { x:
|
|
11225
|
+
throw new Error("Vector2 value must be { x: float, y: float }.");
|
|
11178
11226
|
}
|
|
11179
11227
|
if (shapeIssue?.kind === "vector2Int") {
|
|
11180
11228
|
throw new Error("Vector2Int value must be { x: integer, y: integer }.");
|
|
11181
11229
|
}
|
|
11182
11230
|
if (shapeIssue?.kind === "vector3") {
|
|
11183
|
-
throw new Error(
|
|
11184
|
-
"Vector3 value must be { x: number, y: number, z: number }."
|
|
11185
|
-
);
|
|
11231
|
+
throw new Error("Vector3 value must be { x: float, y: float, z: float }.");
|
|
11186
11232
|
}
|
|
11187
11233
|
if (shapeIssue?.kind === "vector3Int") {
|
|
11188
11234
|
throw new Error(
|
|
@@ -11191,7 +11237,7 @@ function validateProjectDocumentFileMemberValue(document2, member, body, positio
|
|
|
11191
11237
|
}
|
|
11192
11238
|
if (shapeIssue?.kind === "color") {
|
|
11193
11239
|
throw new Error(
|
|
11194
|
-
"Color value must be { r, g, b, a } with each component in [0, 1]."
|
|
11240
|
+
"Color value must be { r, g, b, a } with each component a 32-bit float in [0, 1]."
|
|
11195
11241
|
);
|
|
11196
11242
|
}
|
|
11197
11243
|
if (shapeIssue?.kind === "decimal") {
|
|
@@ -17453,7 +17499,8 @@ function evalPointer(pointer, scope, ctx, resultUsage = "value") {
|
|
|
17453
17499
|
callSiteId: pointer.callSiteId,
|
|
17454
17500
|
invokeDelegate: (delegate, delegateArgs = []) => invokeDelegateValue(delegate, delegateArgs, ctx, pointer.callSiteId)
|
|
17455
17501
|
});
|
|
17456
|
-
if (intercepted?.handled === true)
|
|
17502
|
+
if (intercepted?.handled === true)
|
|
17503
|
+
return hostCallResult(member, intercepted.value, ctx);
|
|
17457
17504
|
if (member === null) {
|
|
17458
17505
|
if (pointer.missingMemberFallback === "valueEquality") {
|
|
17459
17506
|
return jsEqual(innerThis, suppliedArgs[0]);
|
|
@@ -17489,7 +17536,8 @@ function evalPointer(pointer, scope, ctx, resultUsage = "value") {
|
|
|
17489
17536
|
pointer.callSiteId
|
|
17490
17537
|
)
|
|
17491
17538
|
});
|
|
17492
|
-
if (hosted?.handled === true)
|
|
17539
|
+
if (hosted?.handled === true)
|
|
17540
|
+
return hostCallResult(member, hosted.value, ctx);
|
|
17493
17541
|
const receiverId = trackedRowForValueReference(innerThis, ctx)?.id;
|
|
17494
17542
|
throw new NativeFunctionDelegateUnavailableError(
|
|
17495
17543
|
`No native delegate handled Function '${member.name}' (member id '${member.id}'${nativeReceiverDescription(member, innerThis, receiverId)}). Web preview and other non-native evaluator hosts must configure a native handler or call interceptor before evaluation.`,
|
|
@@ -17780,7 +17828,8 @@ function invokeDelegateValue(value, args, ctx, callSiteId, ownerReceiver, result
|
|
|
17780
17828
|
callSiteId,
|
|
17781
17829
|
invokeDelegate: (delegate, delegateArgs = []) => invokeDelegateValue(delegate, delegateArgs, ctx, callSiteId)
|
|
17782
17830
|
});
|
|
17783
|
-
if (intercepted?.handled === true)
|
|
17831
|
+
if (intercepted?.handled === true)
|
|
17832
|
+
return hostCallResult(member, intercepted.value, ctx);
|
|
17784
17833
|
state.delegateStack.push(frame);
|
|
17785
17834
|
try {
|
|
17786
17835
|
if (member.kind === 13 /* Function */) {
|
|
@@ -17795,7 +17844,8 @@ function invokeDelegateValue(value, args, ctx, callSiteId, ownerReceiver, result
|
|
|
17795
17844
|
callSiteId,
|
|
17796
17845
|
invokeDelegate: (delegate, delegateArgs = []) => invokeDelegateValue(delegate, delegateArgs, ctx, callSiteId)
|
|
17797
17846
|
});
|
|
17798
|
-
if (hosted?.handled === true)
|
|
17847
|
+
if (hosted?.handled === true)
|
|
17848
|
+
return hostCallResult(member, hosted.value, ctx);
|
|
17799
17849
|
const receiverId = trackedRowForValueReference(receiver, ctx)?.id;
|
|
17800
17850
|
throw new NativeFunctionDelegateUnavailableError(
|
|
17801
17851
|
`No native delegate handled Function '${member.name}' (member id '${member.id}'${nativeReceiverDescription(member, receiver, receiverId)}). Web preview and other non-native evaluator hosts must configure a native handler or call interceptor before evaluation.`,
|
|
@@ -18664,13 +18714,14 @@ function runtimeCollectionEntryMatchesType(value, typeInfo, ctx, seenCollections
|
|
|
18664
18714
|
return resolved !== value && runtimeValueMatchesType(resolved, typeInfo, ctx, seenCollections);
|
|
18665
18715
|
}
|
|
18666
18716
|
function evalVectorConstructor(vectorType, componentPointers, scope, ctx) {
|
|
18667
|
-
const
|
|
18668
|
-
|
|
18717
|
+
const integer2 = vectorType === 15 /* Vector2Int */ || vectorType === 17 /* Vector3Int */;
|
|
18718
|
+
const values = componentPointers.map((pointer) => {
|
|
18719
|
+
const value = finiteNumberArg(
|
|
18669
18720
|
evalPointer(pointer, scope, ctx),
|
|
18670
18721
|
`${MemberKind[vectorType]} component`
|
|
18671
|
-
)
|
|
18672
|
-
|
|
18673
|
-
|
|
18722
|
+
);
|
|
18723
|
+
return integer2 ? value : Math.fround(value);
|
|
18724
|
+
});
|
|
18674
18725
|
if (integer2 && values.some((value) => !Number.isInteger(value))) {
|
|
18675
18726
|
throw new NSGetterRuntimeError(
|
|
18676
18727
|
`${MemberKind[vectorType]} components must be integers`
|
|
@@ -19561,11 +19612,17 @@ function evalOperation(operation, scope, ctx) {
|
|
|
19561
19612
|
if (operation.type === "arithmetic" /* arithmetic */) {
|
|
19562
19613
|
const op = operation.arithmetic;
|
|
19563
19614
|
const operands = op.pointers.map((p) => evalPointer(p, scope, ctx));
|
|
19564
|
-
return applyArithmetic(
|
|
19615
|
+
return applyArithmetic(
|
|
19616
|
+
op.type,
|
|
19617
|
+
operands,
|
|
19618
|
+
op.decimal === true,
|
|
19619
|
+
ctx,
|
|
19620
|
+
op.numeric
|
|
19621
|
+
);
|
|
19565
19622
|
}
|
|
19566
19623
|
return evalBooleanExpression(operation.expression, scope, ctx);
|
|
19567
19624
|
}
|
|
19568
|
-
function applyArithmetic(op, operands, decimal, ctx) {
|
|
19625
|
+
function applyArithmetic(op, operands, decimal, ctx, numeric) {
|
|
19569
19626
|
if (operands.length === 0) {
|
|
19570
19627
|
throw new NSGetterRuntimeError("Arithmetic operation with no operands");
|
|
19571
19628
|
}
|
|
@@ -19598,31 +19655,43 @@ function applyArithmetic(op, operands, decimal, ctx) {
|
|
|
19598
19655
|
`Arithmetic operand is not numeric: ${typeof o}`
|
|
19599
19656
|
);
|
|
19600
19657
|
});
|
|
19658
|
+
const round = numeric === "float" ? Math.fround : (value) => value;
|
|
19601
19659
|
switch (op) {
|
|
19602
19660
|
case "+" /* addition */:
|
|
19603
|
-
return numbers.reduce((a, b) => a + b, 0);
|
|
19661
|
+
return numbers.reduce((a, b) => round(a + b), 0);
|
|
19604
19662
|
case "-" /* subtraction */:
|
|
19605
|
-
return numbers.reduce((a, b, i) => i === 0 ? b : a - b);
|
|
19663
|
+
return numbers.reduce((a, b, i) => i === 0 ? b : round(a - b));
|
|
19606
19664
|
case "*" /* multiplication */:
|
|
19607
|
-
return numbers.reduce((a, b) => a * b, 1);
|
|
19665
|
+
return numbers.reduce((a, b) => round(a * b), 1);
|
|
19608
19666
|
case "/" /* division */:
|
|
19609
19667
|
return numbers.reduce((a, b, i) => {
|
|
19610
19668
|
if (i === 0) return b;
|
|
19611
19669
|
if (b === 0) throw new NSGetterRuntimeError("Division by zero");
|
|
19612
|
-
return a / b;
|
|
19670
|
+
return numeric === "int" ? Math.trunc(a / b) : round(a / b);
|
|
19613
19671
|
});
|
|
19614
19672
|
case "%" /* remainder */:
|
|
19615
19673
|
return numbers.reduce((a, b, i) => {
|
|
19616
19674
|
if (i === 0) return b;
|
|
19617
19675
|
if (b === 0) throw new NSGetterRuntimeError("Modulo by zero");
|
|
19618
|
-
return a % b;
|
|
19676
|
+
return round(a % b);
|
|
19619
19677
|
});
|
|
19620
19678
|
}
|
|
19621
19679
|
}
|
|
19680
|
+
function hostCallResult(member, value, ctx) {
|
|
19681
|
+
if (typeof value !== "number" || member === null) return value;
|
|
19682
|
+
if (member.kind !== 13 /* Function */ && member.kind !== 23 /* NSFunction */) {
|
|
19683
|
+
return value;
|
|
19684
|
+
}
|
|
19685
|
+
const signature = resolveCallableSignature(member.id, member.kind, ctx);
|
|
19686
|
+
return signature?.returnTypeInfo.type === 4 /* Float */ ? Math.fround(value) : value;
|
|
19687
|
+
}
|
|
19622
19688
|
function coerceAssignmentValue(value, targetTypeInfo, context) {
|
|
19623
19689
|
if (targetTypeInfo.type === 8 /* Enum */ && typeof value === "string") {
|
|
19624
19690
|
return [value];
|
|
19625
19691
|
}
|
|
19692
|
+
if (targetTypeInfo.type === 4 /* Float */ && typeof value === "number") {
|
|
19693
|
+
return Math.fround(value);
|
|
19694
|
+
}
|
|
19626
19695
|
return targetTypeInfo.type === 20 /* Decimal */ && typeof value === "number" ? coerceDecimalOperand(value, context) : value;
|
|
19627
19696
|
}
|
|
19628
19697
|
function coerceDecimalOperand(value, context) {
|
|
@@ -19785,7 +19854,7 @@ function evalMathOp(info, scope, ctx) {
|
|
|
19785
19854
|
if (value < 0) return -1;
|
|
19786
19855
|
return 0;
|
|
19787
19856
|
case "sqrt":
|
|
19788
|
-
return Math.sqrt(value);
|
|
19857
|
+
return Math.fround(Math.sqrt(value));
|
|
19789
19858
|
}
|
|
19790
19859
|
}
|
|
19791
19860
|
function evalDecimalMathOp(info, fn, scope, ctx) {
|
|
@@ -20426,8 +20495,10 @@ function evalFunction(fn, scope, ctx) {
|
|
|
20426
20495
|
);
|
|
20427
20496
|
}
|
|
20428
20497
|
case "toFloat":
|
|
20429
|
-
return
|
|
20430
|
-
|
|
20498
|
+
return Math.fround(
|
|
20499
|
+
floatFromDecimalString(
|
|
20500
|
+
coerceDecimalOperand(receiverRaw, "ToFloat")
|
|
20501
|
+
)
|
|
20431
20502
|
);
|
|
20432
20503
|
case "toDecimal": {
|
|
20433
20504
|
if (typeof receiverRaw !== "number") {
|
|
@@ -20936,6 +21007,9 @@ function evaluateConstructorFields(descriptor, scope, ctx) {
|
|
|
20936
21007
|
`constructor field '${validated.schemaKey}'`
|
|
20937
21008
|
);
|
|
20938
21009
|
}
|
|
21010
|
+
if (typeof value === "number" && validated.typeInfo.type === 4 /* Float */) {
|
|
21011
|
+
value = Math.fround(value);
|
|
21012
|
+
}
|
|
20939
21013
|
if (value === null || value === void 0) {
|
|
20940
21014
|
if (validated.requiredWithoutDefault) {
|
|
20941
21015
|
throw new NSGetterRuntimeError(
|
|
@@ -21556,8 +21630,9 @@ function evaluateDeclaredConstructorArguments(info, record2, scope, ctx) {
|
|
|
21556
21630
|
);
|
|
21557
21631
|
}
|
|
21558
21632
|
const value = byName.get(parameter3.name);
|
|
21559
|
-
if (parameter3.type !== 20 /* Decimal */) return value;
|
|
21560
21633
|
if (typeof value !== "number") return value;
|
|
21634
|
+
if (parameter3.type === 4 /* Float */) return Math.fround(value);
|
|
21635
|
+
if (parameter3.type !== 20 /* Decimal */) return value;
|
|
21561
21636
|
return coerceDecimalOperand(
|
|
21562
21637
|
value,
|
|
21563
21638
|
`constructor argument '${parameter3.name}'`
|
|
@@ -32598,7 +32673,10 @@ var StrictNeoScriptResolver = class {
|
|
|
32598
32673
|
canonicalDecimal(expression.raw, expression.pos)
|
|
32599
32674
|
);
|
|
32600
32675
|
}
|
|
32601
|
-
return literal(
|
|
32676
|
+
return literal(
|
|
32677
|
+
{ kind: "primitive", name: "float" },
|
|
32678
|
+
Math.fround(expression.value)
|
|
32679
|
+
);
|
|
32602
32680
|
}
|
|
32603
32681
|
case "litString":
|
|
32604
32682
|
return literal({ kind: "primitive", name: "string" }, expression.value);
|
|
@@ -37232,7 +37310,9 @@ var StrictNeoScriptResolver = class {
|
|
|
37232
37310
|
arithmetic: {
|
|
37233
37311
|
type: operator,
|
|
37234
37312
|
pointers: [left.pointer, right.pointer],
|
|
37235
|
-
...isPrimitive(result, "decimal") ? { decimal: true } : {}
|
|
37313
|
+
...isPrimitive(result, "decimal") ? { decimal: true } : {},
|
|
37314
|
+
...isPrimitive(result, "int") ? { numeric: "int" } : {},
|
|
37315
|
+
...isPrimitive(result, "float") ? { numeric: "float" } : {}
|
|
37236
37316
|
}
|
|
37237
37317
|
}
|
|
37238
37318
|
},
|
|
@@ -44835,6 +44915,14 @@ var SYSTEM_PROTECTION_RULES = {
|
|
|
44835
44915
|
disallow: [SystemDisallowedOperation.DeleteRecord],
|
|
44836
44916
|
reasonKey: "systemProtection.reasons.policyDeleteBlocked",
|
|
44837
44917
|
serverReason: "System default policy may be edited but must keep one default row."
|
|
44918
|
+
},
|
|
44919
|
+
[SystemProtectionKind.ScriptRuntime]: {
|
|
44920
|
+
disallow: [
|
|
44921
|
+
SystemDisallowedOperation.EditRecord,
|
|
44922
|
+
SystemDisallowedOperation.DeleteRecord
|
|
44923
|
+
],
|
|
44924
|
+
reasonKey: "systemProtection.reasons.scriptRuntime",
|
|
44925
|
+
serverReason: "Lifecycle interface the Neo Compose script runtime calls."
|
|
44838
44926
|
}
|
|
44839
44927
|
};
|
|
44840
44928
|
|
|
@@ -46080,7 +46168,8 @@ function isSchemaSystemMetadata(value) {
|
|
|
46080
46168
|
"dialogueMemoryContainer",
|
|
46081
46169
|
"dialoguePriorityDefault",
|
|
46082
46170
|
"policyImmutable",
|
|
46083
|
-
"policyDeleteBlocked"
|
|
46171
|
+
"policyDeleteBlocked",
|
|
46172
|
+
"scriptRuntime"
|
|
46084
46173
|
]);
|
|
46085
46174
|
const worlds = /* @__PURE__ */ new Set([
|
|
46086
46175
|
"cellPattern",
|
package/package.json
CHANGED
|
@@ -110,7 +110,7 @@ wrappers.
|
|
|
110
110
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
111
111
|
|
|
112
112
|
```html
|
|
113
|
-
<!-- reviewed-through-cli: 0.
|
|
113
|
+
<!-- reviewed-through-cli: 0.67.0 -->
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -197,6 +197,16 @@ itself; both are durable writes deduplicated by target identity, so
|
|
|
197
197
|
re-running a subscription cannot double-subscribe. Invoke it as a statement —
|
|
198
198
|
an action is never a value, never a return type, and never assigned with `=`.
|
|
199
199
|
|
|
200
|
+
Implement a system lifecycle interface to run code when the runtime does.
|
|
201
|
+
`INeoOnLoad` and `INeoOnUnload` run when an instance becomes live and when it
|
|
202
|
+
stops being live. The `INeoUnity*` interfaces, such as `INeoUnityUpdate` and
|
|
203
|
+
`INeoUnityOnTriggerEnter2D`, run for a rendered `NeoObjectBase` in play mode.
|
|
204
|
+
Their member names, such as `OnLoad` and `Update`, are reserved: declare one
|
|
205
|
+
only as the public, immediate instance method that implements its interface,
|
|
206
|
+
and never mark it `@effect`. Subscribe Session actions in `OnLoad` and remove
|
|
207
|
+
them in `OnUnload`. React to data changes with `@effect`, and keep `Update`
|
|
208
|
+
for work that really happens every frame.
|
|
209
|
+
|
|
200
210
|
Keep generic project relations as typed top-level declarations in
|
|
201
211
|
`Relations.neo`. Let the compiler derive identities for owned descriptors and
|
|
202
212
|
concrete generic bindings.
|
|
@@ -202,6 +202,14 @@ Save, Session, Setter, or otherwise writable. A constructor writes only its
|
|
|
202
202
|
`this` instance. A writable structured-leaf field still inherits the receiver's
|
|
203
203
|
effective storage restrictions.
|
|
204
204
|
|
|
205
|
+
## Numeric types
|
|
206
|
+
|
|
207
|
+
`int` is a 32-bit integer and `float` is a 32-bit float, matching C#. Float
|
|
208
|
+
literals, stored values, and every arithmetic step round to 32 bits, so
|
|
209
|
+
`0.1f + 0.2f` behaves like Unity. `int` division truncates toward zero.
|
|
210
|
+
`decimal` is exact base-10 and is the only type to use for currency or other
|
|
211
|
+
values that must not drift.
|
|
212
|
+
|
|
205
213
|
## Numeric builtins
|
|
206
214
|
|
|
207
215
|
Use the `Math` namespace for numeric utilities with C# names and C# semantics:
|