@neocompose/cli 0.84.3 → 0.84.5

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.
@@ -3302,14 +3302,14 @@ function isNSFunctionContains(value) {
3302
3302
  if (v?.type !== "contains" /* contains */) return false;
3303
3303
  const info = v.info;
3304
3304
  if (typeof info !== "object" || info === null) return false;
3305
- return isNSPointer(info.collectionPointer) && isNSPointer(info.valuePointer) && isReferenceFlag(info.reference);
3305
+ return isNSPointer(info.collectionPointer) && isNSPointer(info.valuePointer) && isReferenceFlag(info.reference) && (info.float === void 0 || info.float === true) && (info.decimal === void 0 || info.decimal === true);
3306
3306
  }
3307
3307
  function isNSFunctionIndexOf(value) {
3308
3308
  const v = value;
3309
3309
  if (v?.type !== "indexOf" /* indexOf */) return false;
3310
3310
  const info = v.info;
3311
3311
  if (typeof info !== "object" || info === null) return false;
3312
- return isNSPointer(info.collectionPointer) && isNSPointer(info.valuePointer) && isReferenceFlag(info.reference);
3312
+ return isNSPointer(info.collectionPointer) && isNSPointer(info.valuePointer) && isReferenceFlag(info.reference) && (info.float === void 0 || info.float === true) && (info.decimal === void 0 || info.decimal === true);
3313
3313
  }
3314
3314
  var NS_STRING_OPS = [
3315
3315
  "toLower",
@@ -3483,7 +3483,7 @@ function isNSFunctionCollectionQuery(value) {
3483
3483
  case "Reverse":
3484
3484
  return true;
3485
3485
  case "ToSet":
3486
- return info.reference === void 0 || info.reference === true;
3486
+ return (info.reference === void 0 || info.reference === true) && (info.decimalEntries === void 0 || info.decimalEntries === true);
3487
3487
  default:
3488
3488
  return false;
3489
3489
  }
@@ -15963,13 +15963,22 @@ function neoScriptMemberLookupType(type) {
15963
15963
  nullable2 ||= current.constraint.nullable === true;
15964
15964
  current = current.constraint;
15965
15965
  }
15966
+ if (current.kind === "named" && type.narrowedInterfaces !== void 0) {
15967
+ current = {
15968
+ ...current,
15969
+ narrowedInterfaces: {
15970
+ ...current.narrowedInterfaces,
15971
+ ...type.narrowedInterfaces
15972
+ }
15973
+ };
15974
+ }
15966
15975
  return nullable2 && current.nullable !== true ? { ...current, nullable: true } : current;
15967
15976
  }
15968
15977
  function neoScriptMemberReceiverType(type, memberName, project) {
15969
15978
  const primary = neoScriptMemberLookupType(type);
15970
- if (primary.kind !== "named" || primary.narrowedInterfaces === void 0)
15979
+ if (primary.kind !== "named" && primary.kind !== "typeParameter" || primary.narrowedInterfaces === void 0)
15971
15980
  return primary;
15972
- const declaration = project.typeById.get(primary.typeId);
15981
+ const declaration = primary.kind === "named" ? project.typeById.get(primary.typeId) : void 0;
15973
15982
  if (declaration?.kind === "class" && (memberName === NEOSCRIPT_CLASS_ID_MEMBER || memberName === "Clone"))
15974
15983
  return primary;
15975
15984
  if (declaration?.members.some((member) => member.name === memberName))
@@ -16304,12 +16313,12 @@ function isNeoScriptTypeAssignable(source, target, project) {
16304
16313
  if (isUnknownType(source) || isUnknownType(target)) return false;
16305
16314
  if (isNullType(source)) return isNullableType2(target);
16306
16315
  if (isNullableType2(source) && !isNullableType2(target)) return false;
16307
- if (target.kind === "named" && target.narrowedInterfaces !== void 0) {
16316
+ if ((target.kind === "named" || target.kind === "typeParameter") && target.narrowedInterfaces !== void 0) {
16308
16317
  for (const bound of Object.values(target.narrowedInterfaces)) {
16309
16318
  if (!isNeoScriptTypeAssignable(source, bound, project)) return false;
16310
16319
  }
16311
16320
  }
16312
- if (source.kind === "named" && source.narrowedInterfaces !== void 0) {
16321
+ if ((source.kind === "named" || source.kind === "typeParameter") && source.narrowedInterfaces !== void 0) {
16313
16322
  const direct = target.kind === "named" ? source.narrowedInterfaces[target.typeId] : void 0;
16314
16323
  if (direct !== void 0 && isNeoScriptTypeAssignable(direct, target, project))
16315
16324
  return true;
@@ -16337,7 +16346,7 @@ function isNeoScriptTypeAssignable(source, target, project) {
16337
16346
  project
16338
16347
  );
16339
16348
  }
16340
- if (!target.typeArguments?.length || project.typeById.get(target.typeId)?.kind !== "interface") {
16349
+ if (!target.typeArguments?.length) {
16341
16350
  return isTypeDerivedFrom(
16342
16351
  project.typeById.get(source.typeId),
16343
16352
  target.typeId,
@@ -16345,7 +16354,7 @@ function isNeoScriptTypeAssignable(source, target, project) {
16345
16354
  /* @__PURE__ */ new Set()
16346
16355
  );
16347
16356
  }
16348
- const construction = interfaceConstruction(source, target.typeId, project);
16357
+ const construction = supertypeConstruction(source, target.typeId, project);
16349
16358
  return construction !== void 0 && invariantTypeArguments(construction, target.typeArguments, project);
16350
16359
  }
16351
16360
  if (source.kind === "typeParameter" && target.kind === "typeParameter") {
@@ -16403,7 +16412,7 @@ function isNeoScriptTypeAssignable(source, target, project) {
16403
16412
  return false;
16404
16413
  }
16405
16414
  function withoutNeoScriptInterfaceProofs(type) {
16406
- if (type.kind !== "named" || type.narrowedInterfaces === void 0)
16415
+ if (type.kind !== "named" && type.kind !== "typeParameter" || type.narrowedInterfaces === void 0)
16407
16416
  return type;
16408
16417
  const { narrowedInterfaces: _proofs, ...declared } = type;
16409
16418
  return declared;
@@ -16411,7 +16420,7 @@ function withoutNeoScriptInterfaceProofs(type) {
16411
16420
  function commonNeoScriptAssignableType(left, right, project) {
16412
16421
  if (isNeoScriptTypeAssignable(left, right, project)) return right;
16413
16422
  if (isNeoScriptTypeAssignable(right, left, project)) return left;
16414
- if (left.kind === "named" && right.kind === "named" && (left.narrowedInterfaces !== void 0 || right.narrowedInterfaces !== void 0)) {
16423
+ if ((left.kind === "named" || left.kind === "typeParameter") && (right.kind === "named" || right.kind === "typeParameter") && (left.narrowedInterfaces !== void 0 || right.narrowedInterfaces !== void 0)) {
16415
16424
  const declaredLeft = withoutNeoScriptInterfaceProofs(left);
16416
16425
  const declaredRight = withoutNeoScriptInterfaceProofs(right);
16417
16426
  const common = commonNeoScriptAssignableType(
@@ -16419,7 +16428,8 @@ function commonNeoScriptAssignableType(left, right, project) {
16419
16428
  declaredRight,
16420
16429
  project
16421
16430
  );
16422
- if (common?.kind !== "named") return null;
16431
+ if (common?.kind !== "named" && common?.kind !== "typeParameter")
16432
+ return null;
16423
16433
  const proofs = {};
16424
16434
  for (const [source, other] of [
16425
16435
  [left, right],
@@ -16472,41 +16482,53 @@ function interfaceInstantiationMessage(declared, expected, project) {
16472
16482
  }
16473
16483
  return message;
16474
16484
  }
16475
- function interfaceConstruction(source, interfaceId, project, seen = /* @__PURE__ */ new Set()) {
16476
- if (source.typeId === interfaceId) return source.typeArguments ?? [];
16477
- const type = project.typeById.get(source.typeId);
16478
- if (type === void 0 || seen.has(type.id)) return void 0;
16479
- seen.add(type.id);
16480
- const bindings = /* @__PURE__ */ new Map();
16481
- type.typeParameters?.forEach((parameter3, index) => {
16482
- const argument2 = source.typeArguments?.[index];
16483
- if (argument2 !== void 0)
16484
- bindings.set(parameter3.id ?? parameter3.name, argument2);
16485
- });
16486
- for (const id of [
16487
- ...type.baseTypeIds ?? [],
16488
- ...type.interfaceTypeIds ?? []
16489
- ]) {
16490
- const supertype = {
16491
- kind: "named",
16492
- typeId: id,
16493
- typeArguments: (type.supertypeArguments?.[id] ?? []).map(
16494
- (argument2) => substituteNeoScriptTypeParameters(
16495
- argument2,
16496
- (parameter3) => bindings.get(parameter3.id),
16497
- project
16498
- )
16499
- )
16500
- };
16501
- const found = interfaceConstruction(supertype, interfaceId, project, seen);
16502
- if (found !== void 0) return found;
16485
+ function supertypeConstruction(source, supertypeId, project) {
16486
+ for (const type of constructedSupertypes(source, project)) {
16487
+ if (type.typeId === supertypeId) return type.typeArguments ?? [];
16503
16488
  }
16504
16489
  return void 0;
16505
16490
  }
16491
+ function* constructedSupertypes(source, project) {
16492
+ const pending = [source];
16493
+ const seen = /* @__PURE__ */ new Set();
16494
+ while (true) {
16495
+ const current = pending.pop();
16496
+ if (current === void 0) return;
16497
+ if (seen.has(current.typeId)) continue;
16498
+ seen.add(current.typeId);
16499
+ yield current;
16500
+ const type = project.typeById.get(current.typeId);
16501
+ if (type === void 0) continue;
16502
+ const bindings = /* @__PURE__ */ new Map();
16503
+ type.typeParameters?.forEach((parameter3, index) => {
16504
+ const argument2 = current.typeArguments?.[index];
16505
+ if (argument2 !== void 0)
16506
+ bindings.set(parameter3.id ?? parameter3.name, argument2);
16507
+ });
16508
+ const parents = [
16509
+ ...type.baseTypeIds ?? [],
16510
+ ...type.interfaceTypeIds ?? []
16511
+ ];
16512
+ for (const id of parents.reverse()) {
16513
+ if (seen.has(id)) continue;
16514
+ pending.push({
16515
+ kind: "named",
16516
+ typeId: id,
16517
+ typeArguments: (type.supertypeArguments?.[id] ?? []).map(
16518
+ (argument2) => substituteNeoScriptTypeParameters(
16519
+ argument2,
16520
+ (parameter3) => bindings.get(parameter3.id),
16521
+ project
16522
+ )
16523
+ )
16524
+ });
16525
+ }
16526
+ }
16527
+ }
16506
16528
  function interfaceUndeterminedReason(classType, interfaceType2, project) {
16507
16529
  const params = classType.typeParameters ?? [];
16508
16530
  if (params.length === 0) return null;
16509
- const construction = interfaceConstruction(
16531
+ const construction = supertypeConstruction(
16510
16532
  {
16511
16533
  kind: "named",
16512
16534
  typeId: classType.id,
@@ -17029,16 +17051,18 @@ var UncompiledInitializerRuntimeError = class extends NSGetterRuntimeError {
17029
17051
 
17030
17052
  // ../packages/neoscript-runtime/src/neoscript/runtime-set.ts
17031
17053
  var RuntimeSet = class {
17032
- constructor(source, reference, enumEntries, slotReferences = null) {
17054
+ constructor(source, reference, enumEntries, slotReferences = null, decimalEntries = false) {
17033
17055
  this.source = source;
17034
17056
  this.reference = reference;
17035
17057
  this.enumEntries = enumEntries;
17036
17058
  this.slotReferences = slotReferences;
17059
+ this.decimalEntries = decimalEntries;
17037
17060
  }
17038
17061
  source;
17039
17062
  reference;
17040
17063
  enumEntries;
17041
17064
  slotReferences;
17065
+ decimalEntries;
17042
17066
  entries = /* @__PURE__ */ new Map();
17043
17067
  validations = /* @__PURE__ */ new Map();
17044
17068
  snapshot;
@@ -17048,6 +17072,9 @@ var RuntimeSet = class {
17048
17072
  has(key) {
17049
17073
  return this.entries.has(key);
17050
17074
  }
17075
+ *values() {
17076
+ for (const entry of this.entries.values()) yield entry.raw;
17077
+ }
17051
17078
  add(key, raw, reference) {
17052
17079
  if (this.entries.has(key)) return;
17053
17080
  this.entries.set(key, { raw, reference });
@@ -17566,12 +17593,15 @@ function initializerOwnerContext(document2, valueId, rootOwners, valuesById, rec
17566
17593
  currentId = sourceValueId;
17567
17594
  lexicalRoot = rootOwners.get(sourceValueId) ?? lexicalRoot;
17568
17595
  }
17569
- if (lexicalRoot === void 0 || isStaticMember(lexicalRoot)) {
17570
- return { ownerClass: null, lexicalThisClass: null };
17596
+ if (lexicalRoot === void 0) {
17597
+ return { declaringClass: null, lexicalThisClass: null };
17571
17598
  }
17572
17599
  const lexicalRootId = getField(lexicalRoot, "id");
17573
17600
  const ownerClass = typeof lexicalRootId === "string" ? findSchemaPlacement(lexicalRootId, document2.classes)?.ownerClass ?? null : null;
17574
- return { ownerClass, lexicalThisClass: ownerClass };
17601
+ return {
17602
+ declaringClass: ownerClass,
17603
+ lexicalThisClass: isStaticMember(lexicalRoot) ? null : ownerClass
17604
+ };
17575
17605
  }
17576
17606
  function isClassRecordValue(value) {
17577
17607
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -21440,7 +21470,14 @@ function evaluateNSGetterWithEffects(getter, ctx, argumentValues = [], options =
21440
21470
  for (let index = 0; index < argumentValues.length; index += 1) {
21441
21471
  const parameter3 = parameters[index];
21442
21472
  if (parameter3 === void 0) continue;
21443
- scope.setLocal(parameter3.id, argumentValues[index]);
21473
+ scope.setLocal(
21474
+ parameter3.id,
21475
+ coerceAssignmentValue(
21476
+ argumentValues[index],
21477
+ parameter3.typeInfo,
21478
+ "getter argument"
21479
+ )
21480
+ );
21444
21481
  }
21445
21482
  try {
21446
21483
  const result = evalBody(
@@ -21450,9 +21487,11 @@ function evaluateNSGetterWithEffects(getter, ctx, argumentValues = [], options =
21450
21487
  evaluationOptions(runtimeCtx, false)
21451
21488
  );
21452
21489
  if (result.kind === "return") {
21453
- if (getter.typeInfo.type === 20 /* Decimal */ && typeof result.value === "number") {
21454
- result.value = coerceDecimalOperand(result.value, "return");
21455
- }
21490
+ result.value = coerceAssignmentValue(
21491
+ result.value,
21492
+ getter.typeInfo,
21493
+ "return"
21494
+ );
21456
21495
  if (ownsInvocationState) {
21457
21496
  flushRuntimeSets(runtimeCtx);
21458
21497
  result.value = exportRuntimeSetValue(result.value, runtimeCtx);
@@ -22324,7 +22363,11 @@ function executeCompiledFunction(action, ctx, args, allowFallthroughReturn, runt
22324
22363
  const parameter3 = action.parameters[index + 2];
22325
22364
  const runtimeTypeInfo = runtimeArgumentTypes[index];
22326
22365
  const value2 = asDeclaredRuntimeSet(
22327
- restoreExportedReferences(filledArgs[index], runtimeTypeInfo, ctx),
22366
+ coerceAssignmentValue(
22367
+ restoreExportedReferences(filledArgs[index], runtimeTypeInfo, ctx),
22368
+ runtimeTypeInfo,
22369
+ "function argument"
22370
+ ),
22328
22371
  runtimeTypeInfo,
22329
22372
  ctx
22330
22373
  );
@@ -22358,9 +22401,7 @@ function executeCompiledFunction(action, ctx, args, allowFallthroughReturn, runt
22358
22401
  }
22359
22402
  return null;
22360
22403
  }
22361
- if (runtimeReturnType.type === 20 /* Decimal */ && typeof value === "number") {
22362
- value = coerceDecimalOperand(value, "function return");
22363
- }
22404
+ value = coerceAssignmentValue(value, runtimeReturnType, "function return");
22364
22405
  if (!runtimeValueMatchesType(value, runtimeReturnType, ctx)) {
22365
22406
  throw new NSGetterRuntimeError(
22366
22407
  "NSFunction returned a value that does not match its compiled return type."
@@ -22702,9 +22743,11 @@ function evalInstructions(instructions, scope, ctx, options) {
22702
22743
  }
22703
22744
  case "variable" /* variable */: {
22704
22745
  let value = evalPointer(ins.variable.pointer, scope, ctx);
22705
- if (ins.variable.typeInfo.type === 20 /* Decimal */ && typeof value === "number") {
22706
- value = coerceDecimalOperand(value, "variable initialization");
22707
- }
22746
+ value = coerceAssignmentValue(
22747
+ value,
22748
+ ins.variable.typeInfo,
22749
+ "variable initialization"
22750
+ );
22708
22751
  value = asDeclaredRuntimeSet(value, ins.variable.typeInfo, ctx);
22709
22752
  scope.setLocal(ins.variable.id, value);
22710
22753
  break;
@@ -22740,9 +22783,11 @@ function evalInstructions(instructions, scope, ctx, options) {
22740
22783
  }
22741
22784
  case "assign" /* assign */: {
22742
22785
  let value = evalPointer(ins.pointer, scope, ctx);
22743
- if (ins.target.typeInfo.type === 20 /* Decimal */ && typeof value === "number") {
22744
- value = coerceDecimalOperand(value, "assignment");
22745
- }
22786
+ value = coerceAssignmentValue(
22787
+ value,
22788
+ ins.target.typeInfo,
22789
+ "assignment"
22790
+ );
22746
22791
  if (ins.target.pointer.type === "variable" /* variable */) {
22747
22792
  assertVariableBindingWritable(scope, ins.target.pointer.variableId);
22748
22793
  scope.setLocal(ins.target.pointer.variableId, value);
@@ -24524,6 +24569,21 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
24524
24569
  );
24525
24570
  }
24526
24571
  const args = ins.args.map((arg) => evalPointer(arg, scope, ctx));
24572
+ const decimalEntries = "entryTypeInfo" in ins.target.typeInfo && ins.target.typeInfo.entryTypeInfo.type === 20 /* Decimal */;
24573
+ let entryArgumentIndex = null;
24574
+ const dictionary = ins.target.typeInfo.type === 5 /* Dictionary */;
24575
+ if (ins.mutation === "Add" /* Add */)
24576
+ entryArgumentIndex = dictionary ? 1 : 0;
24577
+ if (ins.mutation === "Insert" /* Insert */) entryArgumentIndex = 1;
24578
+ if (ins.mutation === "Remove" /* Remove */ && !dictionary)
24579
+ entryArgumentIndex = 0;
24580
+ if (entryArgumentIndex !== null && "entryTypeInfo" in ins.target.typeInfo) {
24581
+ args[entryArgumentIndex] = coerceAssignmentValue(
24582
+ args[entryArgumentIndex],
24583
+ ins.target.typeInfo.entryTypeInfo,
24584
+ "collection mutation entry"
24585
+ );
24586
+ }
24527
24587
  const setEntryMember = mutatesLocalVariable ? null : storedSetEntryMember(targetValue, ctx);
24528
24588
  const isLookupSet = setEntryMember === null && ins.target.typeInfo.type === 9 /* Lookup */;
24529
24589
  if (isLookupSet && Array.isArray(targetValue)) {
@@ -24531,7 +24591,8 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
24531
24591
  targetValue,
24532
24592
  ins.reference === true,
24533
24593
  ins.target.typeInfo.type === 9 /* Lookup */ && (ins.target.typeInfo.entryTypeInfo.type === 8 /* Enum */ || ins.target.typeInfo.entryTypeInfo.type === 18 /* DialogueLookup */),
24534
- ctx
24594
+ ctx,
24595
+ decimalEntries
24535
24596
  );
24536
24597
  }
24537
24598
  const setMatch = setEntryMember !== null && Array.isArray(targetValue) && (ins.mutation === "Add" /* Add */ || ins.mutation === "Remove" /* Remove */) ? findStoredSetEntry(targetValue, args[0], setEntryMember, ctx) : null;
@@ -24550,7 +24611,8 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
24550
24611
  ctx,
24551
24612
  isLookupSet,
24552
24613
  false,
24553
- ins.reference === true
24614
+ ins.reference === true,
24615
+ decimalEntries
24554
24616
  );
24555
24617
  updateCollectionReferenceProvenance(
24556
24618
  targetValue,
@@ -24628,7 +24690,8 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
24628
24690
  ctx,
24629
24691
  isLookupSet,
24630
24692
  ins.reference !== true && ins.mutation === "Remove" /* Remove */ && isArrayCollection(targetValue) && setEntryMember === null && !isLookupSet && findKnownRowIdByValueReference(args[0], ctx) === null,
24631
- ins.reference === true
24693
+ ins.reference === true,
24694
+ setEntryMember === null && decimalEntries
24632
24695
  );
24633
24696
  updateCollectionReferenceProvenance(
24634
24697
  targetValue,
@@ -24904,21 +24967,28 @@ function asDeclaredRuntimeSet(value, type, ctx) {
24904
24967
  value,
24905
24968
  entry === 7 /* Class */ || entry === 22 /* Interface */ || entry === 6 /* List */ || entry === 5 /* Dictionary */ || entry === 9 /* Lookup */,
24906
24969
  entry === 8 /* Enum */ || entry === 18 /* DialogueLookup */,
24907
- ctx
24970
+ ctx,
24971
+ entry === 20 /* Decimal */
24908
24972
  );
24909
24973
  }
24910
24974
  function runtimeSetKey(value, set, ctx) {
24911
24975
  if (set.slotReferences !== null) return slotReferenceKey(value);
24912
24976
  if (set.enumEntries && Array.isArray(value) && value.length === 1)
24913
24977
  value = value[0];
24914
- return toSetEntryKey(value, null, set.reference, ctx);
24978
+ return toSetEntryKey(value, null, set.reference, ctx, set.decimalEntries);
24915
24979
  }
24916
- function runtimeSet(array2, reference, enumEntries, ctx) {
24980
+ function runtimeSet(array2, reference, enumEntries, ctx, decimalEntries = false) {
24917
24981
  const sets = ctx.__runtimeSets ??= /* @__PURE__ */ new WeakMap();
24918
24982
  ctx.__dirtyRuntimeSets ??= /* @__PURE__ */ new Set();
24919
24983
  const existing = sets.get(array2);
24920
24984
  if (existing !== void 0) return existing;
24921
- const set = new RuntimeSet(array2, reference, enumEntries);
24985
+ const set = new RuntimeSet(
24986
+ array2,
24987
+ reference,
24988
+ enumEntries,
24989
+ null,
24990
+ decimalEntries
24991
+ );
24922
24992
  const references = collectionReferences(array2, ctx);
24923
24993
  for (let index = 0; index < array2.length; index++) {
24924
24994
  const raw = array2[index];
@@ -25037,7 +25107,7 @@ function removableEntryRowIds(targetValue, mutation, args, ctx) {
25037
25107
  }
25038
25108
  return rowIds;
25039
25109
  }
25040
- function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique = false, resolveRemovalEntries = false, reference = false) {
25110
+ function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique = false, resolveRemovalEntries = false, reference = false, decimal = false) {
25041
25111
  if (targetValue instanceof RuntimeSet) {
25042
25112
  (ctx.__dirtyRuntimeSets ??= /* @__PURE__ */ new Set()).add(targetValue);
25043
25113
  switch (mutation) {
@@ -25089,6 +25159,7 @@ function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique =
25089
25159
  case "Remove" /* Remove */:
25090
25160
  if (Array.isArray(targetValue)) {
25091
25161
  const references = resolveRemovalEntries ? collectionReferences(targetValue, ctx) : recordedReferenceEntries(targetValue, ctx) ?? 1 /* Values */;
25162
+ const targetKey = decimal ? decimalCollectionKey(args[0]) : args[0];
25092
25163
  let index = -1;
25093
25164
  for (let candidate = 0; candidate < targetValue.length; candidate += 1) {
25094
25165
  const entry = targetValue[candidate];
@@ -25099,10 +25170,8 @@ function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique =
25099
25170
  }
25100
25171
  continue;
25101
25172
  }
25102
- if (jsEqual(
25103
- typeof entry === "string" && isReferenceEntry(references, candidate) ? resolveValueIfId(entry, ctx) : entry,
25104
- args[0]
25105
- )) {
25173
+ const value = typeof entry === "string" && isReferenceEntry(references, candidate) ? resolveValueIfId(entry, ctx) : entry;
25174
+ if (jsEqual(decimal ? decimalCollectionKey(value) : value, targetKey)) {
25106
25175
  index = candidate;
25107
25176
  break;
25108
25177
  }
@@ -25589,12 +25658,22 @@ function evalPointerCore(pointer, scope, ctx, resultUsage = "value") {
25589
25658
  case "function" /* function */:
25590
25659
  return evalFunction(pointer.function, scope, ctx);
25591
25660
  case "listLiteral" /* listLiteral */:
25592
- return pointer.entries.map((e) => evalPointer(e, scope, ctx));
25661
+ return pointer.entries.map(
25662
+ (entry) => coerceAssignmentValue(
25663
+ evalPointer(entry, scope, ctx),
25664
+ pointer.typeInfo.entryTypeInfo,
25665
+ "list entry"
25666
+ )
25667
+ );
25593
25668
  case "dictLiteral" /* dictLiteral */: {
25594
25669
  const out = {};
25595
25670
  for (const e of pointer.entries) {
25596
25671
  const k = evalPointer(e.key, scope, ctx);
25597
- out[String(k)] = evalPointer(e.value, scope, ctx);
25672
+ out[String(k)] = coerceAssignmentValue(
25673
+ evalPointer(e.value, scope, ctx),
25674
+ pointer.typeInfo.entryTypeInfo,
25675
+ "dictionary entry"
25676
+ );
25598
25677
  }
25599
25678
  return out;
25600
25679
  }
@@ -27257,9 +27336,9 @@ function readRecordKey(receiver, k, memberId, ctx) {
27257
27336
  if (receiver === ctx.thisValue && typeof ctx.thisValueRowId === "string") {
27258
27337
  return ctx.thisValueRowId;
27259
27338
  }
27260
- const rowId = findKnownRowIdByValueReference(receiver, ctx);
27261
- if (rowId) return rowId;
27262
- throw new NSGetterRuntimeError("Class value has no backing row id.");
27339
+ const row = trackedRowForValueReference(receiver, ctx);
27340
+ if (row !== null && classIdForValueRow(row, ctx) !== void 0)
27341
+ return row.id;
27263
27342
  }
27264
27343
  const assetMember = resolveAssetRuntimeMember(receiver, k, ctx);
27265
27344
  if (assetMember.kind === "ok") return assetMember.value;
@@ -28690,7 +28769,11 @@ function evalDecimalMathOp(info, fn, scope, ctx) {
28690
28769
  }
28691
28770
  }
28692
28771
  function evalListRepeat(info, scope, ctx) {
28693
- const value = evalPointer(info.valuePointer, scope, ctx);
28772
+ const value = coerceAssignmentValue(
28773
+ evalPointer(info.valuePointer, scope, ctx),
28774
+ info.entryTypeInfo,
28775
+ "List.Repeat entry"
28776
+ );
28694
28777
  const count = numberArg(
28695
28778
  evalPointer(info.countPointer, scope, ctx),
28696
28779
  "List.Repeat count"
@@ -28778,13 +28861,18 @@ function jsEqual(a, b) {
28778
28861
  return a instanceof NSSlotReference && b instanceof NSSlotReference && a.targetId === b.targetId;
28779
28862
  }
28780
28863
  if (a === b) return true;
28781
- if (Array.isArray(a) && Array.isArray(b)) {
28782
- if (a.length !== b.length) return false;
28783
- for (let i = 0; i < a.length; i++) {
28784
- if (!jsEqual(a[i], b[i])) return false;
28864
+ if (Array.isArray(a) || a instanceof RuntimeSet) {
28865
+ if (!Array.isArray(b) && !(b instanceof RuntimeSet)) return false;
28866
+ const aSize = a instanceof RuntimeSet ? a.size : a.length;
28867
+ const bSize = b instanceof RuntimeSet ? b.size : b.length;
28868
+ if (aSize !== bSize) return false;
28869
+ const other = b.values();
28870
+ for (const entry of a.values()) {
28871
+ if (!jsEqual(entry, other.next().value)) return false;
28785
28872
  }
28786
28873
  return true;
28787
28874
  }
28875
+ if (b instanceof RuntimeSet) return false;
28788
28876
  if (typeof a === "object" && typeof b === "object" && a !== null && b !== null && !Array.isArray(a) && !Array.isArray(b)) {
28789
28877
  const aKeys = Object.keys(a);
28790
28878
  const bKeys = Object.keys(b);
@@ -29220,7 +29308,8 @@ function evalCollectionQuery(info, scope, ctx) {
29220
29308
  output,
29221
29309
  info.reference === true,
29222
29310
  info.enumEntries === true,
29223
- ctx
29311
+ ctx,
29312
+ info.decimalEntries === true
29224
29313
  ) : output;
29225
29314
  };
29226
29315
  if (info.op === "OrderBy" || info.op === "OrderByDescending") {
@@ -29272,7 +29361,8 @@ function evalCollectionQuery(info, scope, ctx) {
29272
29361
  entry,
29273
29362
  valueId,
29274
29363
  info.reference === true,
29275
- ctx
29364
+ ctx,
29365
+ info.decimalEntries === true
29276
29366
  );
29277
29367
  if (seenSetKeys.has(setKey)) return 0 /* Continue */;
29278
29368
  seenSetKeys.add(setKey);
@@ -29327,10 +29417,15 @@ function evalCollectionQuery(info, scope, ctx) {
29327
29417
  }
29328
29418
  return finish();
29329
29419
  }
29330
- function toSetEntryKey(entry, valueId, reference, ctx) {
29420
+ function toSetEntryKey(entry, valueId, reference, ctx, decimal = false) {
29331
29421
  if (reference) return valueId ?? referenceIdOf(entry, ctx) ?? entry;
29422
+ if (decimal) return decimalCollectionKey(entry);
29332
29423
  return typeof entry === "object" && entry !== null ? canonicalJsonStringify(entry) : entry;
29333
29424
  }
29425
+ function decimalCollectionKey(value) {
29426
+ if (value === null) return null;
29427
+ return decimalKey(coerceDecimalOperand(value, "decimal collection entry"));
29428
+ }
29334
29429
  function compareCollectionKeys(left, right, keyType) {
29335
29430
  if (left === null) return right === null ? 0 : -1;
29336
29431
  if (right === null) return 1;
@@ -29448,7 +29543,11 @@ function evalFunction(fn, scope, ctx) {
29448
29543
  }
29449
29544
  case "contains" /* contains */: {
29450
29545
  let c = evalPointer(fn.info.collectionPointer, scope, ctx);
29451
- const target = evalPointer(fn.info.valuePointer, scope, ctx);
29546
+ let target = evalPointer(fn.info.valuePointer, scope, ctx);
29547
+ if (fn.info.float === true && typeof target === "number")
29548
+ target = Math.fround(target);
29549
+ if (fn.info.decimal === true && target !== null)
29550
+ target = coerceDecimalOperand(target, "collection search");
29452
29551
  if (typeof c === "string") {
29453
29552
  if (typeof target !== "string") {
29454
29553
  throw new NSGetterRuntimeError(
@@ -29481,9 +29580,13 @@ function evalFunction(fn, scope, ctx) {
29481
29580
  return referenceIndexOf(c, target, ctx) !== null;
29482
29581
  }
29483
29582
  const targetReferenceId = typeof target === "string" ? null : findKnownRowIdByValueReference(target, ctx);
29583
+ const targetKey = fn.info.decimal ? decimalCollectionKey(target) : target;
29484
29584
  let containsResolvedEntry = false;
29485
29585
  iterateCollection(c, ctx, (entry, _key, valueId) => {
29486
- if (valueId !== null && valueId === targetReferenceId || jsEqual(entry, target)) {
29586
+ if (valueId !== null && valueId === targetReferenceId || jsEqual(
29587
+ fn.info.decimal ? decimalCollectionKey(entry) : entry,
29588
+ targetKey
29589
+ )) {
29487
29590
  containsResolvedEntry = true;
29488
29591
  return 1 /* Break */;
29489
29592
  }
@@ -29496,15 +29599,21 @@ function evalFunction(fn, scope, ctx) {
29496
29599
  evalPointer(fn.info.collectionPointer, scope, ctx),
29497
29600
  "IndexOf receiver"
29498
29601
  );
29499
- const target = evalPointer(fn.info.valuePointer, scope, ctx);
29602
+ let target = evalPointer(fn.info.valuePointer, scope, ctx);
29603
+ if (fn.info.float === true && typeof target === "number")
29604
+ target = Math.fround(target);
29500
29605
  if (fn.info.reference === true) {
29501
29606
  const index = referenceIndexOf(collection, target, ctx);
29502
29607
  return index === null ? -1 : numberArg(index, "IndexOf index");
29503
29608
  }
29504
29609
  const targetReferenceId = typeof target === "string" ? null : findKnownRowIdByValueReference(target, ctx);
29610
+ const targetKey = fn.info.decimal ? decimalCollectionKey(target) : target;
29505
29611
  let found = -1;
29506
29612
  iterateCollection(collection, ctx, (entry, key, valueId) => {
29507
- if (valueId !== null && valueId === targetReferenceId || jsEqual(entry, target)) {
29613
+ if (valueId !== null && valueId === targetReferenceId || jsEqual(
29614
+ fn.info.decimal ? decimalCollectionKey(entry) : entry,
29615
+ targetKey
29616
+ )) {
29508
29617
  found = numberArg(key, "IndexOf index");
29509
29618
  return 1 /* Break */;
29510
29619
  }
@@ -29712,7 +29821,19 @@ function evalFunction(fn, scope, ctx) {
29712
29821
  );
29713
29822
  iterateCollection(c, ctx, callback);
29714
29823
  }
29715
- if (found !== sentinel) return found;
29824
+ if (found !== sentinel) {
29825
+ if (typeof found === "string") {
29826
+ if (c instanceof RuntimeSet) {
29827
+ if (c.enumEntries) return [found];
29828
+ } else {
29829
+ const row = trackedRowForValueReference(c, ctx);
29830
+ const member = row === null ? null : memberForValueRow(row, ctx);
29831
+ if (member?.kind === 8 /* Enum */ || member?.kind === 18 /* DialogueLookup */)
29832
+ return [found];
29833
+ }
29834
+ }
29835
+ return found;
29836
+ }
29716
29837
  if (fn.type === "first" /* first */) {
29717
29838
  throw new NSGetterRuntimeError(
29718
29839
  innerFn ? "First() found no matching entry. Use FirstOrDefault() and handle null if no match is expected." : "First() called on an empty collection. Check that it has entries, or use FirstOrDefault() and handle null."
@@ -30926,10 +31047,19 @@ function constructionInitEvaluator(ctx, createdValues, argumentScopes, construct
30926
31047
  }
30927
31048
  return null;
30928
31049
  };
31050
+ const defaultScopeMemberId = (memberId) => walkExtendsMemberChain(
31051
+ memberId,
31052
+ ctx.vm.members,
31053
+ (declaration) => declaration.defaultValue === void 0 ? void 0 : declaration.id,
31054
+ {
31055
+ memberById: (id) => indexes4.schemaIndex.member(id) ?? null,
31056
+ maxHops: ctx.vm.members.length
31057
+ }
31058
+ );
30929
31059
  return (member, init, sourceValueId, genericEnv = instanceEnv) => {
30930
31060
  const memberId = Reflect.get(member, "id");
30931
31061
  const effectiveMemberId = typeof memberId === "string" ? memberId : null;
30932
- const scopeMemberId = indexes4.initializerScopeMemberIds.get(init) ?? (typeof sourceValueId !== "string" ? void 0 : indexes4.initializerScopeMemberIdsByValueId.get(sourceValueId)) ?? effectiveMemberId;
31062
+ const scopeMemberId = indexes4.initializerScopeMemberIds.get(init) ?? (typeof sourceValueId !== "string" ? void 0 : indexes4.initializerScopeMemberIdsByValueId.get(sourceValueId)) ?? (sourceValueId === void 0 && effectiveMemberId !== null ? defaultScopeMemberId(effectiveMemberId) : void 0) ?? effectiveMemberId;
30933
31063
  const compiled = ensureInitializerCompiled({
30934
31064
  init,
30935
31065
  member,
@@ -36342,7 +36472,7 @@ function materializeMemberDefaultValue(args) {
36342
36472
  rootOwners,
36343
36473
  valuesById,
36344
36474
  (id) => args.readTracking?.valueIds.add(id)
36345
- ).ownerClass : typeof Reflect.get(member, "id") === "string" && !isStaticMember(member) ? findSchemaPlacement(
36475
+ ).lexicalThisClass : typeof Reflect.get(member, "id") === "string" && !isStaticMember(member) ? findSchemaPlacement(
36346
36476
  String(Reflect.get(member, "id")),
36347
36477
  args.document.classes
36348
36478
  )?.ownerClass ?? null : null;
@@ -43826,7 +43956,7 @@ function implementerConstruction(implementer, slotInterface, slot, project) {
43826
43956
  );
43827
43957
  if (reason !== null) return void 0;
43828
43958
  }
43829
- const implemented = interfaceConstruction(
43959
+ const implemented = supertypeConstruction(
43830
43960
  {
43831
43961
  kind: "named",
43832
43962
  typeId: implementer.id,
@@ -44018,10 +44148,12 @@ var Scope = class {
44018
44148
  constructor(parent, probe = parent?.probe ?? false) {
44019
44149
  this.parent = parent;
44020
44150
  this.probe = probe;
44151
+ this.externalRoots = parent?.externalRoots ?? /* @__PURE__ */ new Map();
44021
44152
  this.patternBindings = parent?.patternBindings ?? null;
44022
44153
  }
44023
44154
  parent;
44024
44155
  probe;
44156
+ externalRoots;
44025
44157
  entries = /* @__PURE__ */ new Map();
44026
44158
  invalidatedRoots = /* @__PURE__ */ new Set();
44027
44159
  hiddenNarrowingRoots = /* @__PURE__ */ new Set();
@@ -44044,7 +44176,15 @@ var Scope = class {
44044
44176
  lookup(name) {
44045
44177
  return this.entries.get(name) ?? this.parent?.lookup(name) ?? null;
44046
44178
  }
44179
+ registerExternalRoot(name, type) {
44180
+ if (!this.externalRoots.has(name))
44181
+ this.externalRoots.set(name, { name, type, variableId: name });
44182
+ }
44183
+ lookupFlowRoot(name) {
44184
+ return this.lookup(name) ?? this.externalRoots.get(name) ?? null;
44185
+ }
44047
44186
  containsEntry(entry) {
44187
+ if (this.externalRoots.get(entry.name) === entry) return true;
44048
44188
  for (const candidate of this.entries.values()) {
44049
44189
  if (candidate === entry) return true;
44050
44190
  }
@@ -44102,6 +44242,7 @@ var Scope = class {
44102
44242
  if (path === rootEntry.name) this.updatePatternType(rootEntry, type);
44103
44243
  }
44104
44244
  updatePatternType(entry, type) {
44245
+ if (this.externalRoots.get(entry.name) === entry) return;
44105
44246
  if (this.probe || entry.patternBinding)
44106
44247
  this.patternBindings = {
44107
44248
  name: entry.name,
@@ -44745,7 +44886,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
44745
44886
  branchExitNarrowings,
44746
44887
  this.project
44747
44888
  )) {
44748
- const rootEntry = scope.lookup(pathRoot(path));
44889
+ const rootEntry = scope.lookupFlowRoot(pathRoot(path));
44749
44890
  if (rootEntry === narrowed.rootEntry) {
44750
44891
  scope.narrow(path, rootEntry, narrowed.type);
44751
44892
  }
@@ -45678,7 +45819,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
45678
45819
  }
45679
45820
  for (const [path, narrowed] of merged) {
45680
45821
  if (!parent.containsEntry(narrowed.rootEntry)) continue;
45681
- const rootEntry = parent.lookup(pathRoot(path));
45822
+ const rootEntry = parent.lookupFlowRoot(pathRoot(path));
45682
45823
  if (rootEntry === narrowed.rootEntry) {
45683
45824
  parent.narrow(path, rootEntry, narrowed.type);
45684
45825
  }
@@ -45905,7 +46046,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
45905
46046
  scope
45906
46047
  );
45907
46048
  if (assignedPath) {
45908
- const rootEntry = scope.lookup(pathRoot(assignedPath));
46049
+ const rootEntry = scope.lookupFlowRoot(pathRoot(assignedPath));
45909
46050
  if (rootEntry) {
45910
46051
  const retainedFacts = unaffectedNarrowings(
45911
46052
  assignedPath,
@@ -45952,11 +46093,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
45952
46093
  referenceAssignment(statement, place, storageType, scope) {
45953
46094
  const source = statement.op === "=" ? statement.value ?? void 0 : void 0;
45954
46095
  const nullLiteral = source?.kind === "litNull";
45955
- const assigned = source === void 0 ? void 0 : this.resolveReferenceExpression(
45956
- source,
45957
- scope,
45958
- nullLiteral ? void 0 : neoScriptReadType(storageType)
45959
- );
46096
+ const assigned = source === void 0 ? void 0 : this.resolveReferenceAssignmentValue(source, scope, storageType);
45960
46097
  const valueAt = (type) => {
45961
46098
  if (source === void 0 || assigned === void 0) return void 0;
45962
46099
  return nullLiteral ? this.resolveReferenceExpression(source, scope, type) : this.readReferences(assigned, type);
@@ -46000,6 +46137,30 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
46000
46137
  }
46001
46138
  return { target: layer, value: valueAt(layer.type), through };
46002
46139
  }
46140
+ resolveReferenceAssignmentValue(expression, scope, storageType) {
46141
+ if (expression.kind === "conditional") {
46142
+ return this.resolveConditionalExpression(
46143
+ expression,
46144
+ scope,
46145
+ neoScriptReadType(storageType),
46146
+ storageType
46147
+ );
46148
+ }
46149
+ if (expression.kind === "coalesce") {
46150
+ return this.resolveCoalesceExpression(
46151
+ expression,
46152
+ scope,
46153
+ void 0,
46154
+ storageType
46155
+ );
46156
+ }
46157
+ const expected = neoScriptReadType(storageType);
46158
+ return this.resolveReferenceExpression(
46159
+ expression,
46160
+ scope,
46161
+ expression.kind === "litNull" ? void 0 : expected
46162
+ );
46163
+ }
46003
46164
  /** `Reference<target>` as an expression type (P112 §3.1). */
46004
46165
  referenceType(target, nullable2) {
46005
46166
  return neoScriptReferenceType(
@@ -46160,7 +46321,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
46160
46321
  false
46161
46322
  ).type;
46162
46323
  }
46163
- return resolvedTarget.type;
46324
+ return this.resolveIdentifierNatural(targetAst.name, scope, targetAst.pos).type;
46164
46325
  }
46165
46326
  if (targetAst.kind !== "member") return resolvedTarget.type;
46166
46327
  return this.resolveMemberNatural(
@@ -46403,7 +46564,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
46403
46564
  scope
46404
46565
  );
46405
46566
  if (assignedPath) {
46406
- const rootEntry = scope.lookup(pathRoot(assignedPath));
46567
+ const rootEntry = scope.lookupFlowRoot(pathRoot(assignedPath));
46407
46568
  if (rootEntry) {
46408
46569
  const retainedFacts = unaffectedNarrowings(
46409
46570
  assignedPath,
@@ -47139,34 +47300,8 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
47139
47300
  ...operand.writeRoot ? { writeRoot: operand.writeRoot } : {}
47140
47301
  };
47141
47302
  }
47142
- case "coalesce": {
47143
- const left = this.resolveExpression(expression.left, scope);
47144
- const leftOptional = { ...left.type, nullable: true };
47145
- const nullLeft = isNull(left.type);
47146
- const right = this.resolveExpression(
47147
- expression.right,
47148
- scope,
47149
- nullLeft ? expected : leftOptional
47150
- );
47151
- if (!nullLeft && !isNeoScriptTypeAssignable(right.type, leftOptional, this.project)) {
47152
- throw new CompileError(
47153
- `\`??\` right operand ${this.describe(right.type)} is not assignable to ${this.describe(leftOptional)}`,
47154
- expression.pos
47155
- );
47156
- }
47157
- const resultType = nullLeft ? right.type : {
47158
- ...left.type,
47159
- nullable: isNullable(left.type) && isNullable(right.type)
47160
- };
47161
- return {
47162
- pointer: {
47163
- type: "coalesce" /* Coalesce */,
47164
- left: left.pointer,
47165
- right: right.pointer
47166
- },
47167
- type: resultType
47168
- };
47169
- }
47303
+ case "coalesce":
47304
+ return this.resolveCoalesceExpression(expression, scope, expected);
47170
47305
  case "conditional":
47171
47306
  return this.resolveConditionalExpression(expression, scope, expected);
47172
47307
  case "is": {
@@ -47743,6 +47878,21 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
47743
47878
  };
47744
47879
  }
47745
47880
  resolveIdentifier(name, scope, pos, usage = "value") {
47881
+ const natural = this.resolveIdentifierNatural(name, scope, pos, usage);
47882
+ if (scope.lookup(name)) return natural;
47883
+ const path = this.narrowingPath(name, scope);
47884
+ const root = path === null ? null : scope.lookupFlowRoot(pathRoot(path));
47885
+ const narrowed = root && path ? scope.lookupNarrowedType(path, root) : null;
47886
+ const resolved = narrowed ? { ...natural, type: narrowed } : natural;
47887
+ this.options.onFlowScope?.({
47888
+ name,
47889
+ position: pos,
47890
+ type: resolved.type,
47891
+ bindings: scope.patternBindings
47892
+ });
47893
+ return resolved;
47894
+ }
47895
+ resolveIdentifierNatural(name, scope, pos, usage = "value") {
47746
47896
  if (name === "this" && this.context.kind === "initializer" && this.delegateCaptureContexts.length === 0 && usage === "value") {
47747
47897
  throw new CompileError(
47748
47898
  "'this' is unavailable while an initializer runs. Defer instance access with a lambda or method group.",
@@ -47775,7 +47925,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
47775
47925
  };
47776
47926
  }
47777
47927
  const global = this.context.project.globals.find(
47778
- (candidate) => candidate.name === name
47928
+ (symbol) => symbol.name === name
47779
47929
  );
47780
47930
  if (global) return this.symbolValue(global);
47781
47931
  const implicit = this.implicitMember(name);
@@ -47917,11 +48067,29 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
47917
48067
  if (path === null) return null;
47918
48068
  const root = pathRoot(path);
47919
48069
  if (scope.lookup(root)) return path;
47920
- if (this.context.project.globals.some((symbol) => symbol.name === root)) {
47921
- return path;
48070
+ const global = this.context.project.globals.find(
48071
+ (symbol) => symbol.name === root
48072
+ );
48073
+ if (global) {
48074
+ const key = `global:${root}`;
48075
+ scope.registerExternalRoot(key, global.type);
48076
+ return key + path.slice(root.length);
47922
48077
  }
47923
48078
  const implicit = this.implicitMember(root);
47924
- return implicit && implicit.symbol.static !== true ? `this.${path}` : path;
48079
+ if (implicit && implicit.symbol.static !== true) return `this.${path}`;
48080
+ const owner = implicit?.owner ?? this.project.typeByName.get(root);
48081
+ if (owner) {
48082
+ const memberName = implicit?.symbol.name ?? path.slice(root.length + 1).split(".")[0];
48083
+ const member = implicit?.symbol ?? owner.members.find((candidate) => candidate.name === memberName);
48084
+ const declaring = member?.inheritedFrom;
48085
+ const key = `static:${declaring?.typeName ?? owner.name}`;
48086
+ scope.registerExternalRoot(key, {
48087
+ kind: "named",
48088
+ typeId: declaring?.typeId ?? owner.id
48089
+ });
48090
+ return implicit ? `${key}.${path}` : key + path.slice(root.length);
48091
+ }
48092
+ return path;
47925
48093
  }
47926
48094
  conditionFacts(expression, scope, whenTrue) {
47927
48095
  const pathOf = (value) => this.narrowingPath(canonicalPath(value), scope);
@@ -47939,7 +48107,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
47939
48107
  locals
47940
48108
  )) {
47941
48109
  const path = this.narrowingPath(assignedPath, outerScope);
47942
- const outerEntry = path === null ? null : outerScope.lookup(pathRoot(path));
48110
+ const outerEntry = path === null ? null : outerScope.lookupFlowRoot(pathRoot(path));
47943
48111
  if (outerEntry && path !== null) {
47944
48112
  const retained = unaffectedNarrowings(path, outerEntry, loopEntryScope);
47945
48113
  loopEntryScope.hideInheritedNarrowing(outerEntry);
@@ -47957,7 +48125,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
47957
48125
  targetScope
47958
48126
  );
47959
48127
  const natural = this.readReferences(place, void 0);
47960
- const rootEntry = fact.path === null ? null : targetScope.lookup(pathRoot(fact.path));
48128
+ const rootEntry = fact.path === null ? null : targetScope.lookupFlowRoot(pathRoot(fact.path));
47961
48129
  if (fact.nullValue) {
47962
48130
  if (fact.path === null || rootEntry === null) continue;
47963
48131
  if (place.type.kind === "reference" && !isNullable(place.type)) {
@@ -47978,7 +48146,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
47978
48146
  const targetDefinition = target.kind === "named" ? this.project.typeById.get(target.typeId) : void 0;
47979
48147
  const naturalDefinition = natural.type.kind === "named" ? this.project.typeById.get(natural.type.typeId) : void 0;
47980
48148
  let narrowed = { ...target, nullable: false };
47981
- if (!fact.bindingName && natural.type.kind === "named" && (naturalDefinition?.kind === "class" || naturalDefinition?.kind === "interface") && target.kind === "named" && targetDefinition?.kind === "interface") {
48149
+ if ((natural.type.kind === "typeParameter" || natural.type.kind === "named" && (naturalDefinition?.kind === "class" || naturalDefinition?.kind === "interface")) && target.kind === "named" && targetDefinition?.kind === "interface") {
47982
48150
  narrowed = { ...natural.type, nullable: false };
47983
48151
  if (!isNeoScriptTypeAssignable(narrowed, target, this.project)) {
47984
48152
  narrowed = {
@@ -47990,6 +48158,22 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
47990
48158
  };
47991
48159
  }
47992
48160
  }
48161
+ if (target.kind === "named" && targetDefinition?.kind === "class") {
48162
+ const lookup = neoScriptMemberLookupType(natural.type);
48163
+ if (lookup.kind === "named" || lookup.kind === "typeParameter") {
48164
+ const { narrowedInterfaces, ...declared } = lookup;
48165
+ const proofs = declared.kind === "named" && this.project.typeById.get(declared.typeId)?.kind === "interface" ? {
48166
+ ...narrowedInterfaces,
48167
+ [declared.typeId]: declared
48168
+ } : narrowedInterfaces;
48169
+ if (proofs !== void 0)
48170
+ narrowed = {
48171
+ ...target,
48172
+ nullable: false,
48173
+ narrowedInterfaces: proofs
48174
+ };
48175
+ }
48176
+ }
47993
48177
  if (mode === "all" && fact.path !== null && rootEntry !== null && place.type.kind !== "reference") {
47994
48178
  targetScope.narrow(fact.path, rootEntry, narrowed);
47995
48179
  }
@@ -47999,7 +48183,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
47999
48183
  }
48000
48184
  targetScope.definePattern({
48001
48185
  name: fact.bindingName,
48002
- type: narrowed,
48186
+ type: { ...target, nullable: false },
48003
48187
  variableId: fact.bindingTest ? this.patternBindingId(fact.bindingTest) : fact.bindingName,
48004
48188
  writeRoot: this.expressionWriteRoot(natural, targetScope),
48005
48189
  pointer: fact.bindingTest ? {
@@ -48279,7 +48463,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
48279
48463
  return wire;
48280
48464
  }
48281
48465
  resolveMember(receiverAst, name, scope, pos, optional2, receiverValue) {
48282
- const resolved = this.resolveMemberNatural(
48466
+ let resolved = this.resolveMemberNatural(
48283
48467
  receiverAst,
48284
48468
  name,
48285
48469
  scope,
@@ -48288,21 +48472,25 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
48288
48472
  receiverValue
48289
48473
  );
48290
48474
  if (!optional2) {
48291
- const receiverPath = this.narrowingPath(
48292
- canonicalPath(receiverAst),
48475
+ const receiverPath = canonicalPath(receiverAst);
48476
+ const path = this.narrowingPath(
48477
+ receiverPath === null ? null : `${receiverPath}.${name}`,
48293
48478
  scope
48294
48479
  );
48295
- if (receiverPath) {
48296
- const rootEntry = scope.lookup(pathRoot(receiverPath));
48480
+ if (path) {
48481
+ const rootEntry = scope.lookupFlowRoot(pathRoot(path));
48297
48482
  if (rootEntry) {
48298
- const narrowed = scope.lookupNarrowedType(
48299
- `${receiverPath}.${name}`,
48300
- rootEntry
48301
- );
48302
- if (narrowed) return { ...resolved, type: narrowed };
48483
+ const narrowed = scope.lookupNarrowedType(path, rootEntry);
48484
+ if (narrowed) resolved = { ...resolved, type: narrowed };
48303
48485
  }
48304
48486
  }
48305
48487
  }
48488
+ this.options.onFlowScope?.({
48489
+ name,
48490
+ position: pos,
48491
+ type: resolved.type,
48492
+ bindings: scope.patternBindings
48493
+ });
48306
48494
  return resolved;
48307
48495
  }
48308
48496
  resolveStaticMemberValue(staticType, member, pos) {
@@ -50069,7 +50257,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
50069
50257
  scope
50070
50258
  )
50071
50259
  );
50072
- const schemaClassInfo = toWireType(targetType, this.project);
50260
+ const schemaClassInfo = this.constructorWireType(targetType, expression);
50073
50261
  if (schemaClassInfo.type !== 7 /* Class */) {
50074
50262
  throw new Error(
50075
50263
  `NeoScript constructor ${className} has non-Class return type ${this.describe(signature.returnType)}.`
@@ -50087,6 +50275,16 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
50087
50275
  writability: "session" /* Session */
50088
50276
  };
50089
50277
  }
50278
+ /** Constructor storage arguments stay distinct from their expression read types. */
50279
+ constructorWireType(target, expression) {
50280
+ const typeArguments = expression.typeArguments?.map(
50281
+ (argument2) => resolveStoredReferenceTarget(argument2, this.context, this.project)
50282
+ );
50283
+ return toWireType(
50284
+ typeArguments === void 0 ? target : { ...target, typeArguments },
50285
+ this.project
50286
+ );
50287
+ }
50090
50288
  constructorTargetType(schemaClass2, expression, expected) {
50091
50289
  const typeArguments = expression.typeArguments?.map(
50092
50290
  (argument2) => this.resolveType(argument2)
@@ -50217,7 +50415,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
50217
50415
  scope
50218
50416
  );
50219
50417
  const classType = targetType;
50220
- const schemaClassInfo = toWireType(classType, this.project);
50418
+ const schemaClassInfo = this.constructorWireType(classType, expression);
50221
50419
  if (schemaClassInfo.type !== 7 /* Class */) {
50222
50420
  throw new Error(
50223
50421
  `NeoScript declared constructor ${className} projected a non-Class wire type.`
@@ -51080,6 +51278,8 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
51080
51278
  {
51081
51279
  collectionPointer: receiver.pointer,
51082
51280
  valuePointer: value.pointer,
51281
+ ...isPrimitive(expectedValueType, "float") ? { float: true } : {},
51282
+ ...isPrimitive(expectedValueType, "decimal") ? { decimal: true } : {},
51083
51283
  ...hasReferenceEquality(collection.valueType, this.project) ? { reference: true } : {}
51084
51284
  },
51085
51285
  { kind: "primitive", name: "int" }
@@ -51109,6 +51309,8 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
51109
51309
  {
51110
51310
  collectionPointer: receiver.pointer,
51111
51311
  valuePointer: value.pointer,
51312
+ ...isPrimitive(expectedValueType, "float") ? { float: true } : {},
51313
+ ...isPrimitive(expectedValueType, "decimal") ? { decimal: true } : {},
51112
51314
  ...hasReferenceEquality(collection.valueType, this.project) ? { reference: true } : {}
51113
51315
  },
51114
51316
  { kind: "primitive", name: "bool" }
@@ -51341,6 +51543,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
51341
51543
  info = {
51342
51544
  ...base,
51343
51545
  op: name,
51546
+ ...isPrimitive(collection.valueType, "decimal") ? { decimalEntries: true } : {},
51344
51547
  ...hasReferenceEquality(collection.valueType, this.project) ? { reference: true } : {}
51345
51548
  };
51346
51549
  resultType = {
@@ -52280,7 +52483,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
52280
52483
  scope
52281
52484
  );
52282
52485
  if (path) {
52283
- const rootEntry = scope.lookup(pathRoot(path));
52486
+ const rootEntry = scope.lookupFlowRoot(pathRoot(path));
52284
52487
  if (rootEntry) scope.invalidate(rootEntry);
52285
52488
  }
52286
52489
  const actionTypeInfo = receiver.wireType ?? toWireType(receiver.type, this.project);
@@ -52332,7 +52535,74 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
52332
52535
  pos
52333
52536
  );
52334
52537
  }
52335
- resolveConditionalExpression(expression, scope, expected) {
52538
+ referenceAssignmentBranches(left, right, storageType, operator) {
52539
+ let layer = storageType;
52540
+ while (true) {
52541
+ const expected = operator === "coalesce" ? { ...layer, nullable: true } : layer;
52542
+ const resolvedLeft = this.readReferences(left, expected);
52543
+ const resolvedRight = this.readReferences(right, expected);
52544
+ if (isNeoScriptTypeAssignable(resolvedLeft.type, expected, this.project) && isNeoScriptTypeAssignable(resolvedRight.type, expected, this.project)) {
52545
+ return { left: resolvedLeft, right: resolvedRight, type: expected };
52546
+ }
52547
+ if (layer.kind !== "reference") break;
52548
+ layer = layer.target;
52549
+ }
52550
+ return { left, right, type: neoScriptReadType(storageType) };
52551
+ }
52552
+ resolveCoalesceExpression(expression, scope, expected, assignmentType) {
52553
+ let left;
52554
+ let right;
52555
+ if (assignmentType) {
52556
+ const branches = this.referenceAssignmentBranches(
52557
+ this.resolveReferenceAssignmentValue(
52558
+ expression.left,
52559
+ scope,
52560
+ assignmentType
52561
+ ),
52562
+ this.resolveReferenceAssignmentValue(
52563
+ expression.right,
52564
+ scope,
52565
+ assignmentType
52566
+ ),
52567
+ assignmentType,
52568
+ "coalesce"
52569
+ );
52570
+ left = branches.left;
52571
+ right = branches.right;
52572
+ } else {
52573
+ left = this.resolveExpression(
52574
+ expression.left,
52575
+ scope,
52576
+ expected?.kind === "reference" ? { ...expected, nullable: true } : void 0
52577
+ );
52578
+ right = this.resolveExpression(
52579
+ expression.right,
52580
+ scope,
52581
+ isNull(left.type) ? expected : { ...left.type, nullable: true }
52582
+ );
52583
+ }
52584
+ const leftOptional = { ...left.type, nullable: true };
52585
+ const nullLeft = isNull(left.type);
52586
+ if (!nullLeft && !isNeoScriptTypeAssignable(right.type, leftOptional, this.project)) {
52587
+ throw new CompileError(
52588
+ `\`??\` right operand ${this.describe(right.type)} is not assignable to ${this.describe(leftOptional)}`,
52589
+ expression.pos
52590
+ );
52591
+ }
52592
+ const resultType = nullLeft ? right.type : {
52593
+ ...left.type,
52594
+ nullable: isNullable(left.type) && isNullable(right.type)
52595
+ };
52596
+ return {
52597
+ pointer: {
52598
+ type: "coalesce" /* Coalesce */,
52599
+ left: left.pointer,
52600
+ right: right.pointer
52601
+ },
52602
+ type: resultType
52603
+ };
52604
+ }
52605
+ resolveConditionalExpression(expression, scope, expected, assignmentType) {
52336
52606
  const condition = this.toBool(
52337
52607
  this.resolveExpression(expression.condition, scope),
52338
52608
  expression.condition.pos
@@ -52349,7 +52619,38 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
52349
52619
  );
52350
52620
  let whenTrue;
52351
52621
  let whenFalse;
52352
- if (expected) {
52622
+ if (assignmentType) {
52623
+ whenTrue = this.resolveReferenceAssignmentValue(
52624
+ expression.whenTrue,
52625
+ trueScope,
52626
+ assignmentType
52627
+ );
52628
+ whenFalse = this.resolveReferenceAssignmentValue(
52629
+ expression.whenFalse,
52630
+ falseScope,
52631
+ assignmentType
52632
+ );
52633
+ let common2 = commonNeoScriptAssignableType(
52634
+ whenTrue.type,
52635
+ whenFalse.type,
52636
+ this.project
52637
+ );
52638
+ if (isNull(whenTrue.type)) common2 = { ...whenFalse.type, nullable: true };
52639
+ if (isNull(whenFalse.type)) common2 = { ...whenTrue.type, nullable: true };
52640
+ if (common2) {
52641
+ expected = common2;
52642
+ } else {
52643
+ const branches = this.referenceAssignmentBranches(
52644
+ whenTrue,
52645
+ whenFalse,
52646
+ assignmentType,
52647
+ "conditional"
52648
+ );
52649
+ whenTrue = branches.left;
52650
+ whenFalse = branches.right;
52651
+ expected = branches.type;
52652
+ }
52653
+ } else if (expected) {
52353
52654
  whenTrue = this.resolveExpression(
52354
52655
  expression.whenTrue,
52355
52656
  trueScope,
@@ -52386,7 +52687,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
52386
52687
  expression.pos
52387
52688
  );
52388
52689
  }
52389
- if (expected) {
52690
+ if (expected && !assignmentType) {
52390
52691
  this.requireAssignable(
52391
52692
  whenTrue.type,
52392
52693
  expected,
@@ -53274,9 +53575,7 @@ function typeRefsEqual(left, right) {
53274
53575
  if (left.kind === "primitive" && right.kind === "primitive") {
53275
53576
  return left.name === right.name;
53276
53577
  }
53277
- if (left.kind === "named" && right.kind === "named") {
53278
- const leftArgs = left.typeArguments ?? [];
53279
- const rightArgs = right.typeArguments ?? [];
53578
+ if ((left.kind === "named" || left.kind === "typeParameter") && (right.kind === "named" || right.kind === "typeParameter")) {
53280
53579
  if (left.narrowedInterfaces !== right.narrowedInterfaces) {
53281
53580
  const leftBounds = Object.entries(left.narrowedInterfaces ?? {});
53282
53581
  const rightBounds = right.narrowedInterfaces ?? {};
@@ -53287,6 +53586,10 @@ function typeRefsEqual(left, right) {
53287
53586
  return false;
53288
53587
  }
53289
53588
  }
53589
+ }
53590
+ if (left.kind === "named" && right.kind === "named") {
53591
+ const leftArgs = left.typeArguments ?? [];
53592
+ const rightArgs = right.typeArguments ?? [];
53290
53593
  return left.typeId === right.typeId && leftArgs.length === rightArgs.length && leftArgs.every((item, index) => {
53291
53594
  const other = rightArgs[index];
53292
53595
  return other !== void 0 && typeRefsEqual(item, other);
@@ -54268,6 +54571,20 @@ function typesOverlap(left, right, project) {
54268
54571
  if (isNull(right)) return isNullable(left);
54269
54572
  left = neoScriptMemberLookupType(left);
54270
54573
  right = neoScriptMemberLookupType(right);
54574
+ const declaredLeft = withoutNeoScriptInterfaceProofs(left);
54575
+ const declaredRight = withoutNeoScriptInterfaceProofs(right);
54576
+ if (left.kind === "named" || left.kind === "typeParameter") {
54577
+ for (const proof of Object.values(left.narrowedInterfaces ?? {})) {
54578
+ if (!typesOverlap(proof, declaredRight, project)) return false;
54579
+ }
54580
+ }
54581
+ if (right.kind === "named" || right.kind === "typeParameter") {
54582
+ for (const proof of Object.values(right.narrowedInterfaces ?? {})) {
54583
+ if (!typesOverlap(declaredLeft, proof, project)) return false;
54584
+ }
54585
+ }
54586
+ left = declaredLeft;
54587
+ right = declaredRight;
54271
54588
  if (left.kind === "typeParameter" || right.kind === "typeParameter")
54272
54589
  return true;
54273
54590
  if (isNeoScriptTypeAssignable(left, right, project) || isNeoScriptTypeAssignable(right, left, project))
@@ -54281,11 +54598,29 @@ function typesOverlap(left, right, project) {
54281
54598
  const classDeclaration = leftDeclaration?.kind === "class" ? leftDeclaration : rightDeclaration?.kind === "class" ? rightDeclaration : null;
54282
54599
  const interfaceDeclaration = leftDeclaration?.kind === "interface" ? leftDeclaration : rightDeclaration?.kind === "interface" ? rightDeclaration : null;
54283
54600
  if (classDeclaration !== null && interfaceDeclaration !== null) {
54601
+ if (conflictingInterfaceConstructions(left, right, project)) return false;
54284
54602
  return classDeclaration.sealed !== true;
54285
54603
  }
54286
54604
  }
54287
54605
  return isNumeric(left) && isNumeric(right);
54288
54606
  }
54607
+ function conflictingInterfaceConstructions(left, right, project) {
54608
+ const constructions = /* @__PURE__ */ new Map();
54609
+ for (const type of constructedSupertypes(left, project)) {
54610
+ if (project.typeById.get(type.typeId)?.kind === "interface" && type.typeArguments?.length)
54611
+ constructions.set(type.typeId, type.typeArguments);
54612
+ }
54613
+ for (const type of constructedSupertypes(right, project)) {
54614
+ const argumentsList2 = constructions.get(type.typeId);
54615
+ if (!argumentsList2) continue;
54616
+ if (argumentsList2.some((argument2, index) => {
54617
+ const other = type.typeArguments?.[index];
54618
+ return other !== void 0 && !containsTypeParameter(argument2) && !containsTypeParameter(other) && !(isNeoScriptTypeAssignable(argument2, other, project) && isNeoScriptTypeAssignable(other, argument2, project));
54619
+ }))
54620
+ return true;
54621
+ }
54622
+ return false;
54623
+ }
54289
54624
  function isUnknown(type) {
54290
54625
  return type.kind === "primitive" && type.name === "unknown";
54291
54626
  }
@@ -59344,7 +59679,7 @@ function compileNSInitializer(code, ctx) {
59344
59679
  {
59345
59680
  ...compilerContext,
59346
59681
  thisClass: lexicalThisClass ?? null,
59347
- implicitMemberAccess: lexicalThisClass !== null,
59682
+ implicitMemberAccess: lexicalThisClass != null || declaringClass != null,
59348
59683
  staticMember: false
59349
59684
  },
59350
59685
  {
@@ -59615,7 +59950,7 @@ function compileMemberInitializerBody(args) {
59615
59950
  returnTypeInfo,
59616
59951
  initializerName: args.member.name,
59617
59952
  lexicalThisClass: parseExpression(defaultValue.init.code).kind === "lambda" ? instanceClass : null,
59618
- declaringClass: instanceClass,
59953
+ declaringClass: args.thisClass,
59619
59954
  argumentTypes: initializerArgumentTypes(
59620
59955
  instanceClass,
59621
59956
  args.constructors ?? []
@@ -59664,7 +59999,7 @@ function compileValueRowInitializerBody(args) {
59664
59999
  lexicalThisClass: args.lexicalThisClass ?? null,
59665
60000
  declaringClass: args.initializerOwnerClass,
59666
60001
  argumentTypes: initializerArgumentTypes(
59667
- args.initializerOwnerClass,
60002
+ args.lexicalThisClass === null ? null : args.initializerOwnerClass,
59668
60003
  args.constructors ?? []
59669
60004
  ),
59670
60005
  ...args.storedConstructionReplay === true ? { storedConstructionReplay: true } : {}
@@ -59869,7 +60204,7 @@ function valueInitializerCompilationSites(document2) {
59869
60204
  sites.set(row.id, {
59870
60205
  row,
59871
60206
  member,
59872
- ownerClass: ownerContext.ownerClass,
60207
+ ownerClass: ownerContext.declaringClass,
59873
60208
  lexicalThisClass: ownerContext.lexicalThisClass
59874
60209
  });
59875
60210
  }