@neocompose/cli 0.71.0 → 0.71.2

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/dist/neo.mjs CHANGED
@@ -14206,7 +14206,8 @@ var init_neoflow_graph_parser = __esm({
14206
14206
  this.baseOffset + valueStartToken.start,
14207
14207
  this.baseOffset + end.end
14208
14208
  ),
14209
- range: this.absoluteRange(start, end)
14209
+ range: this.absoluteRange(start, end),
14210
+ valueRange: this.absoluteRange(valueStartToken, end)
14210
14211
  });
14211
14212
  }
14212
14213
  if (!this.eat(",") && !this.at(")")) {
@@ -14405,6 +14406,12 @@ var init_neoflow_graph_parser = __esm({
14405
14406
  name: name.text,
14406
14407
  nameRange: this.absoluteRange(name, name),
14407
14408
  initializer,
14409
+ initializerRange: {
14410
+ start: this.source.positionAt(
14411
+ equalsOffset + this.source.text.slice(equalsOffset, this.baseOffset + last.start).indexOf(initializer)
14412
+ ),
14413
+ end: this.source.positionAt(this.baseOffset + last.start)
14414
+ },
14408
14415
  range: this.absoluteRange(first, last)
14409
14416
  });
14410
14417
  } else {
@@ -15804,7 +15811,9 @@ var init_project_source_parser = __esm({
15804
15811
  const type = this.parseType();
15805
15812
  const name = this.expectName("global name");
15806
15813
  this.expect("=");
15814
+ const initializerStart = this.cursor;
15807
15815
  const initializer = this.captureInitializer();
15816
+ const dialogueGroup = type.name === "DialogueGroup" ? this.parseDialogueGroupBody(initializerStart, initializer) : void 0;
15808
15817
  this.reportNestedTypes(initializer);
15809
15818
  return {
15810
15819
  kind: "global",
@@ -15813,9 +15822,53 @@ var init_project_source_parser = __esm({
15813
15822
  name: name.text,
15814
15823
  nameRange: name.range,
15815
15824
  initializer,
15825
+ ...dialogueGroup ? { dialogueGroup } : {},
15816
15826
  range: rangeFrom(start, this.previous())
15817
15827
  };
15818
15828
  }
15829
+ parseDialogueGroupBody(start, initializer) {
15830
+ const end = this.cursor;
15831
+ let depth = 0;
15832
+ let open = -1;
15833
+ for (let index = start; index < end; index++) {
15834
+ const text = this.tokens[index].text;
15835
+ if (text === "(" || text === "[") depth++;
15836
+ else if (text === ")" || text === "]") depth--;
15837
+ else if (text === "{" && depth === 0) {
15838
+ open = index;
15839
+ break;
15840
+ }
15841
+ }
15842
+ if (open < 0) return void 0;
15843
+ const functions = [];
15844
+ this.cursor = open + 1;
15845
+ try {
15846
+ while (!this.done() && !this.at("}") && !this.at("when") && this.cursor < end) {
15847
+ const before = this.cursor;
15848
+ try {
15849
+ const member = this.parseMember("DialogueGroup", "class");
15850
+ if (member?.kind === "function") functions.push(member);
15851
+ } catch (error) {
15852
+ this.report(error);
15853
+ this.recoverMember();
15854
+ }
15855
+ if (this.cursor === before) this.cursor++;
15856
+ }
15857
+ } finally {
15858
+ this.cursor = end;
15859
+ }
15860
+ const openToken = this.tokens[open];
15861
+ return {
15862
+ constructor: {
15863
+ text: this.source.text.slice(
15864
+ this.tokens[start].start,
15865
+ openToken.start
15866
+ ),
15867
+ range: { start: initializer.range.start, end: openToken.range.start }
15868
+ },
15869
+ functions
15870
+ };
15871
+ }
15819
15872
  parseGenericParameters() {
15820
15873
  this.expect("<");
15821
15874
  const parameters = [];
@@ -20490,7 +20543,7 @@ function optionalTestConfig(value) {
20490
20543
  `"${NEO_CONFIG_FILE}" field "test.${unknown}" is not recognized.`
20491
20544
  );
20492
20545
  }
20493
- const stringArray2 = (field) => {
20546
+ const stringArray3 = (field) => {
20494
20547
  const entry = config[field];
20495
20548
  if (entry === void 0) return void 0;
20496
20549
  if (!Array.isArray(entry) || entry.some((item) => typeof item !== "string" || item.length === 0)) {
@@ -20510,8 +20563,8 @@ function optionalTestConfig(value) {
20510
20563
  }
20511
20564
  return entry;
20512
20565
  };
20513
- const include = stringArray2("include");
20514
- const exclude = stringArray2("exclude");
20566
+ const include = stringArray3("include");
20567
+ const exclude = stringArray3("exclude");
20515
20568
  const invalidInclude = include?.find(
20516
20569
  (pattern) => !pattern.endsWith(".spec.neo")
20517
20570
  );
@@ -23195,7 +23248,7 @@ var init_project = __esm({
23195
23248
  });
23196
23249
 
23197
23250
  // ../packages/neoscript-language/src/source-map.ts
23198
- function createNeoScriptSourceMap(code, fileText, range2, source) {
23251
+ function createNeoScriptSourceMap(code, fileText, range2, source, thisAlias) {
23199
23252
  const text = typeof fileText === "string" ? new SourceText(fileText) : fileText;
23200
23253
  const start = text.offsetAt(range2.start);
23201
23254
  const end = text.offsetAt(range2.end);
@@ -23218,7 +23271,8 @@ function createNeoScriptSourceMap(code, fileText, range2, source) {
23218
23271
  for (let i2 = first; i2 < last; i2++) {
23219
23272
  const body = canonical[i2];
23220
23273
  const file = authored[i2 - first];
23221
- if (body.kind !== file.kind || body.raw !== file.raw) return void 0;
23274
+ if (body.kind !== file.kind || body.raw !== file.raw && !(body.kind === "identifier" && body.text === "this" && file.text === thisAlias))
23275
+ return void 0;
23222
23276
  const at3 = position(file.start);
23223
23277
  positions.push([
23224
23278
  body.range.start.line + 1,
@@ -26062,6 +26116,7 @@ var init_strict_resolver = __esm({
26062
26116
  tryMutationContexts = [];
26063
26117
  functionControlBoundaries = [];
26064
26118
  debugSource;
26119
+ inferredExpressionReturnType;
26065
26120
  initialScope() {
26066
26121
  const scope = new Scope(null, this.options.onFlowScope !== void 0);
26067
26122
  scope.define(
@@ -26266,6 +26321,23 @@ var init_strict_resolver = __esm({
26266
26321
  this.context.kind === "action" || this.context.kind === "setter" || this.context.kind === "constructor" || isVoid(this.context.returnType),
26267
26322
  describeUnitKind(this.context.kind)
26268
26323
  );
26324
+ if (this.options.inferExpressionReturnType) {
26325
+ if (this.context.kind !== "getter")
26326
+ throw new CompileError(
26327
+ "Expression inference requires a getter.",
26328
+ body.pos
26329
+ );
26330
+ if (statements.length !== 1)
26331
+ throw new CompileError(
26332
+ "Expression inference requires one return expression.",
26333
+ body.pos
26334
+ );
26335
+ if (statements[0]?.kind !== "return" || statements[0].expr === null)
26336
+ throw new CompileError(
26337
+ "Expression inference requires a returned value.",
26338
+ body.pos
26339
+ );
26340
+ }
26269
26341
  const instructions = this.resolveStatements(statements, scope);
26270
26342
  if ((this.context.kind === "function" || this.context.kind === "getter" || this.context.kind === "condition" || this.context.kind === "initializer") && !isVoid(this.context.returnType) && !instructionsTerminate(instructions)) {
26271
26343
  throw new CompileError(
@@ -26282,7 +26354,10 @@ var init_strict_resolver = __esm({
26282
26354
  source: this.debugSource,
26283
26355
  parameters,
26284
26356
  instructions,
26285
- typeInfo: toWireType(returnType, this.project)
26357
+ typeInfo: toWireType(
26358
+ this.inferredExpressionReturnType ?? returnType,
26359
+ this.project
26360
+ )
26286
26361
  };
26287
26362
  } finally {
26288
26363
  this.expectedReturnStack.pop();
@@ -27084,10 +27159,11 @@ var init_strict_resolver = __esm({
27084
27159
  }
27085
27160
  const inference = this.lambdaReturnInference.at(-1);
27086
27161
  const inferring = inference?.depth === this.lambdaDepth;
27162
+ const inferExpression = this.options.inferExpressionReturnType && this.lambdaDepth === 0;
27087
27163
  const value = this.resolveExpression(
27088
27164
  statement.expr,
27089
27165
  scope,
27090
- inferring ? void 0 : expected
27166
+ inferring || inferExpression ? void 0 : expected
27091
27167
  );
27092
27168
  if (inferring) {
27093
27169
  inference.returns.push({
@@ -27107,12 +27183,21 @@ var init_strict_resolver = __esm({
27107
27183
  statement.pos
27108
27184
  );
27109
27185
  }
27110
- this.requireAssignable(
27111
- value.type,
27112
- expected,
27113
- statement.expr.pos,
27114
- "return"
27115
- );
27186
+ if (inferExpression) {
27187
+ if (isVoid(value.type))
27188
+ throw new CompileError(
27189
+ "A text expression must return a value, not void.",
27190
+ statement.expr.pos
27191
+ );
27192
+ this.inferredExpressionReturnType = value.type;
27193
+ } else {
27194
+ this.requireAssignable(
27195
+ value.type,
27196
+ expected,
27197
+ statement.expr.pos,
27198
+ "return"
27199
+ );
27200
+ }
27116
27201
  return {
27117
27202
  type: "return" /* Return */,
27118
27203
  pointer: value.pointer
@@ -40091,6 +40176,14 @@ function referenceTypeAssignable(actual, expected, environment) {
40091
40176
  )
40092
40177
  );
40093
40178
  }
40179
+ const actualType = environment.projectIndex.typeByName.get(actual.name);
40180
+ const expectedType = environment.projectIndex.typeByName.get(expected.name);
40181
+ if (actualType && expectedType?.kind === "interface")
40182
+ return isNeoScriptTypeAssignable(
40183
+ { kind: "named", typeId: actualType.id },
40184
+ { kind: "named", typeId: expectedType.id },
40185
+ environment.projectIndex
40186
+ );
40094
40187
  return classExtends(actual.name, expected.name, environment, /* @__PURE__ */ new Set());
40095
40188
  }
40096
40189
  function classExtends(actual, expected, environment, visited) {
@@ -40637,7 +40730,8 @@ function compileNeoScriptStrict(document, context, options = {}) {
40637
40730
  {
40638
40731
  source: options.source,
40639
40732
  onFlowScope: options.onFlowScope,
40640
- sourceUri: document.uri
40733
+ sourceUri: document.uri,
40734
+ inferExpressionReturnType: options.inferExpressionReturnType
40641
40735
  }
40642
40736
  ).compile(ast);
40643
40737
  const ir = attachDependencyManifest(
@@ -40965,13 +41059,60 @@ function isPrimitiveName(name) {
40965
41059
  }
40966
41060
  function compileProjectSourceBodies(documents) {
40967
41061
  const graph = buildProjectGraph(documents);
40968
- const projectIndex = createProjectIndex(graph.project);
41062
+ const groupContexts = dialogueGroupContexts(documents, graph);
41063
+ const project = {
41064
+ ...graph.project,
41065
+ types: [
41066
+ ...graph.project.types,
41067
+ ...[...groupContexts.values()].map((group) => group.contextType)
41068
+ ]
41069
+ };
41070
+ const projectIndex = createProjectIndex(project);
40969
41071
  const bodies = [];
40970
41072
  const contexts = [];
40971
41073
  const diagnostics = [];
40972
41074
  for (const [uri, document] of documents) {
40973
41075
  if (document.kind !== "definition") continue;
40974
41076
  for (const declaration of document.declarations) {
41077
+ if (declaration.kind === "global") {
41078
+ const group = groupContexts.get(declaration);
41079
+ if (group) {
41080
+ for (const member of declaration.dialogueGroup?.functions ?? []) {
41081
+ if (!member.body) continue;
41082
+ const expression = member.body.expression;
41083
+ compileBody({
41084
+ uri,
41085
+ document,
41086
+ owner: { declaration },
41087
+ memberName: member.name,
41088
+ declarationRange: member.nameRange,
41089
+ memberId: sourceIdentity2(
41090
+ member.annotations,
41091
+ `dialogue-group:${uri}:${declaration.name}:${member.name}`
41092
+ ),
41093
+ unit: "function",
41094
+ range: expression?.range ?? innerBodyRange(document.sourceText, member.body.range),
41095
+ ...expression ? { bodyMode: "expression" } : {},
41096
+ context: {
41097
+ project,
41098
+ kind: "function",
41099
+ returnType: { kind: "primitive", name: "bool" },
41100
+ ...group.thisType ? { thisClass: group.thisType } : {},
41101
+ dialogueContextType: {
41102
+ kind: "named",
41103
+ typeId: group.contextType.id
41104
+ },
41105
+ functionName: member.name
41106
+ },
41107
+ projectIndex,
41108
+ bodies,
41109
+ contexts,
41110
+ diagnostics
41111
+ });
41112
+ }
41113
+ }
41114
+ continue;
41115
+ }
40975
41116
  if (declaration.kind !== "class") continue;
40976
41117
  const owner = graph.declarationsByName.get(declaration.name);
40977
41118
  if (!owner) continue;
@@ -41003,7 +41144,7 @@ function compileProjectSourceBodies(documents) {
41003
41144
  unit: "constructor",
41004
41145
  range: innerBodyRange(document.sourceText, constructor2.body.range),
41005
41146
  context: {
41006
- project: graph.project,
41147
+ project,
41007
41148
  declaringType,
41008
41149
  thisClass: declaringType,
41009
41150
  implicitMemberAccess: true,
@@ -41038,7 +41179,7 @@ function compileProjectSourceBodies(documents) {
41038
41179
  unit: "init",
41039
41180
  range: innerBodyRange(document.sourceText, initBlock.body.range),
41040
41181
  context: {
41041
- project: graph.project,
41182
+ project,
41042
41183
  declaringType,
41043
41184
  thisClass: declaringType,
41044
41185
  implicitMemberAccess: true,
@@ -41065,7 +41206,7 @@ function compileProjectSourceBodies(documents) {
41065
41206
  if (!info) continue;
41066
41207
  const staticMember = member.modifiers.includes("static");
41067
41208
  const baseContext2 = {
41068
- project: graph.project,
41209
+ project,
41069
41210
  declaringType,
41070
41211
  ...staticMember ? {} : { thisClass: declaringType },
41071
41212
  returnType: sourceTypeRef(member.type, owner, graph.typeIdsByName),
@@ -41134,7 +41275,78 @@ function compileProjectSourceBodies(documents) {
41134
41275
  }
41135
41276
  }
41136
41277
  }
41137
- return { project: graph.project, bodies, contexts, diagnostics };
41278
+ return { project, bodies, contexts, diagnostics };
41279
+ }
41280
+ function dialogueGroupContexts(documents, graph) {
41281
+ const result = /* @__PURE__ */ new Map();
41282
+ let index;
41283
+ let membersByType;
41284
+ const collectionMembersByType = () => membersByType ??= new Map(
41285
+ graph.project.types.map((type) => [
41286
+ type.name,
41287
+ new Map(type.members.map((member) => [member.name, member]))
41288
+ ])
41289
+ );
41290
+ for (const [uri, document] of documents) {
41291
+ for (const declaration of document.declarations) {
41292
+ if (declaration.kind !== "global" || !declaration.dialogueGroup) continue;
41293
+ let thisType;
41294
+ try {
41295
+ const constructor2 = parseExpression(
41296
+ declaration.dialogueGroup.constructor.text
41297
+ );
41298
+ if (constructor2.kind === "new") {
41299
+ const kind = constructor2.args[constructor2.argumentNames?.indexOf("kind") ?? -1];
41300
+ const collection = constructor2.args[constructor2.argumentNames?.indexOf("collection") ?? -1];
41301
+ if (kind?.kind === "contextualEnum" && kind.name === "Lookup") {
41302
+ let member;
41303
+ if (collection?.kind === "member" && collection.receiver.kind === "ident") {
41304
+ member = collectionMembersByType().get(collection.receiver.name)?.get(collection.name);
41305
+ } else if (collection?.kind === "call" && collection.callee.kind === "ident" && collection.callee.name === "Reference") {
41306
+ const id3 = collection.args[collection.argumentNames?.indexOf("id") ?? -1];
41307
+ if (id3?.kind === "litString")
41308
+ member = (index ??= createProjectIndex(
41309
+ graph.project
41310
+ )).symbolById.get(id3.value);
41311
+ }
41312
+ let entry;
41313
+ if (member?.type.kind === "list") entry = member.type.elementType;
41314
+ if (member?.type.kind === "dictionary")
41315
+ entry = member.type.valueType;
41316
+ if (entry?.kind === "named")
41317
+ thisType = { ...entry, nullable: false };
41318
+ }
41319
+ }
41320
+ } catch {
41321
+ }
41322
+ const id2 = `dialogue-context:${uri}:${declaration.name}`;
41323
+ result.set(declaration, {
41324
+ ...thisType ? { thisType } : {},
41325
+ contextType: {
41326
+ id: id2,
41327
+ name: "DialogueContext",
41328
+ kind: "synthetic",
41329
+ members: [
41330
+ {
41331
+ id: `${id2}:primary`,
41332
+ name: "primary",
41333
+ kind: "property",
41334
+ type: { kind: "primitive", name: "unknown" },
41335
+ writable: false
41336
+ },
41337
+ {
41338
+ id: `${id2}:trigger`,
41339
+ name: "trigger",
41340
+ kind: "property",
41341
+ type: thisType ?? { kind: "primitive", name: "null" },
41342
+ writable: false
41343
+ }
41344
+ ]
41345
+ }
41346
+ });
41347
+ }
41348
+ }
41349
+ return result;
41138
41350
  }
41139
41351
  function compileBody(args) {
41140
41352
  args.contexts.push({
@@ -41938,6 +42150,7 @@ var init_project_source_script_compiler = __esm({
41938
42150
  "use strict";
41939
42151
  init_project_source_settlement();
41940
42152
  init_debug_info();
42153
+ init_executable_parser();
41941
42154
  init_compiler();
41942
42155
  init_declared_constructors();
41943
42156
  init_language_spec();
@@ -44950,7 +45163,9 @@ function memberManifest(uri, member) {
44950
45163
  modifiers: member.modifiers,
44951
45164
  annotations: manifestAnnotations(member.annotations),
44952
45165
  initializer: member.kind === "field" ? member.initializer?.text ?? null : null,
45166
+ ...member.kind === "field" && member.initializer ? { initializerSource: { uri, range: member.initializer.range } } : {},
44953
45167
  body: member.kind === "field" ? null : member.body?.text ?? null,
45168
+ ...member.kind !== "field" && member.body ? { bodySource: { uri, range: member.body.range } } : {},
44954
45169
  parameters: member.kind === "function" ? member.parameters.map(
44955
45170
  (parameter4) => manifestParameter(uri, parameter4)
44956
45171
  ) : []
@@ -44988,7 +45203,7 @@ function dialogueManifest(uri, declaration) {
44988
45203
  graphType: member.type.name,
44989
45204
  destination: member.flowInitializer?.body?.destination?.name ?? null,
44990
45205
  initializer: member.initializer?.text ?? "",
44991
- arguments: flowArguments(member.flowInitializer?.arguments ?? []),
45206
+ arguments: flowArguments(uri, member.flowInitializer?.arguments ?? []),
44992
45207
  content: member.flowInitializer?.body?.kind === "block" ? dialogueContent(uri, member.flowInitializer.body.content) : null
44993
45208
  }))
44994
45209
  };
@@ -44996,18 +45211,20 @@ function dialogueManifest(uri, declaration) {
44996
45211
  function dialogueContent(uri, content) {
44997
45212
  return {
44998
45213
  prose: content.prose.map((entry) => entry.text),
45214
+ proseSources: content.prose.map((entry) => ({ uri, range: entry.range })),
44999
45215
  bindings: content.bindings.map((binding) => ({
45000
45216
  name: binding.name,
45001
45217
  type: binding.typeText,
45002
45218
  primary: binding.primary,
45003
- initializer: binding.initializer
45219
+ initializer: binding.initializer,
45220
+ source: { uri, range: binding.initializerRange }
45004
45221
  })),
45005
45222
  children: content.children.map((child2) => ({
45006
45223
  ...identity(uri, child2.range, child2.annotations),
45007
45224
  name: child2.name,
45008
45225
  graphType: child2.graphType,
45009
45226
  destination: child2.initializer.body?.destination?.name ?? null,
45010
- arguments: flowArguments(child2.initializer.arguments),
45227
+ arguments: flowArguments(uri, child2.initializer.arguments),
45011
45228
  content: child2.initializer.body?.kind === "block" ? dialogueContent(uri, child2.initializer.body.content) : null
45012
45229
  })),
45013
45230
  statements: content.statements.map((statement) => ({
@@ -45017,10 +45234,11 @@ function dialogueContent(uri, content) {
45017
45234
  }))
45018
45235
  };
45019
45236
  }
45020
- function flowArguments(argumentsValue) {
45237
+ function flowArguments(uri, argumentsValue) {
45021
45238
  return argumentsValue.map((argument2) => ({
45022
45239
  ...argument2.name ? { name: argument2.name } : {},
45023
- expression: argument2.text
45240
+ expression: argument2.text,
45241
+ source: { uri, range: argument2.valueRange ?? argument2.range }
45024
45242
  }));
45025
45243
  }
45026
45244
  function manifestType(type) {
@@ -45389,9 +45607,13 @@ function assertMember(value, path) {
45389
45607
  "body",
45390
45608
  "parameters"
45391
45609
  ],
45392
- ["docsText"]
45610
+ ["docsText", "bodySource", "initializerSource"]
45393
45611
  );
45394
45612
  assertIdentity(member, path);
45613
+ if (member.initializerSource !== void 0)
45614
+ assertLocation(member.initializerSource, `${path}.initializerSource`);
45615
+ if (member.bodySource !== void 0)
45616
+ assertLocation(member.bodySource, `${path}.bodySource`);
45395
45617
  string(member.name, `${path}.name`);
45396
45618
  assertOptionalDocsText(member.docsText, `${path}.docsText`);
45397
45619
  assertType(member.type, `${path}.type`);
@@ -45508,14 +45730,30 @@ function assertDialogue(value, path) {
45508
45730
  }
45509
45731
  function assertDialogueContent(value, path) {
45510
45732
  const content = record(value, path);
45511
- exactKeys(content, path, ["prose", "bindings", "children", "statements"]);
45733
+ exactKeysWithOptional(
45734
+ content,
45735
+ path,
45736
+ ["prose", "bindings", "children", "statements"],
45737
+ ["proseSources"]
45738
+ );
45739
+ if (content.proseSources !== void 0)
45740
+ array(content.proseSources, `${path}.proseSources`).forEach(
45741
+ (entry, index) => assertLocation(entry, `${path}.proseSources[${index}]`)
45742
+ );
45512
45743
  array(content.prose, `${path}.prose`).forEach(
45513
45744
  (entry, index) => string(entry, `${path}.prose[${index}]`)
45514
45745
  );
45515
45746
  array(content.bindings, `${path}.bindings`).forEach((entry, index) => {
45516
45747
  const bindingPath = `${path}.bindings[${index}]`;
45517
45748
  const binding = record(entry, bindingPath);
45518
- exactKeys(binding, bindingPath, ["name", "type", "primary", "initializer"]);
45749
+ exactKeysWithOptional(
45750
+ binding,
45751
+ bindingPath,
45752
+ ["name", "type", "primary", "initializer"],
45753
+ ["source"]
45754
+ );
45755
+ if (binding.source !== void 0)
45756
+ assertLocation(binding.source, `${bindingPath}.source`);
45519
45757
  string(binding.name, `${bindingPath}.name`);
45520
45758
  string(binding.type, `${bindingPath}.type`);
45521
45759
  if (typeof binding.primary !== "boolean") {
@@ -45573,11 +45811,12 @@ function assertFlowArguments(value, path) {
45573
45811
  exactKeys(
45574
45812
  argument2,
45575
45813
  argumentPath,
45576
- Object.hasOwn(argument2, "name") ? ["name", "expression"] : ["expression"]
45814
+ Object.hasOwn(argument2, "name") ? ["name", "expression", "source"] : ["expression", "source"]
45577
45815
  );
45578
45816
  if (argument2.name !== void 0)
45579
45817
  string(argument2.name, `${argumentPath}.name`);
45580
45818
  string(argument2.expression, `${argumentPath}.expression`);
45819
+ assertLocation(argument2.source, `${argumentPath}.source`);
45581
45820
  });
45582
45821
  }
45583
45822
  function assertType(value, path) {
@@ -45759,7 +45998,7 @@ var init_registry = __esm({
45759
45998
  "../packages/manifest/schema-contract/registry.mjs"() {
45760
45999
  "use strict";
45761
46000
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
45762
- cliVersion: "0.71.0",
46001
+ cliVersion: "0.71.2",
45763
46002
  projectFileUploadBatchSize: 32,
45764
46003
  documentRecords: {
45765
46004
  member: {
@@ -47208,7 +47447,7 @@ var init_source_diagnostics = __esm({
47208
47447
  "neoflow-incomplete-draft"
47209
47448
  ]);
47210
47449
  SchemaSourceError = class extends Error {
47211
- constructor(detail, file, line, column, code, severity = "error") {
47450
+ constructor(detail, file, line, column, code, severity = "error", range2) {
47212
47451
  super(`${file}:${line}:${column} \u2014 ${detail}`);
47213
47452
  this.detail = detail;
47214
47453
  this.file = file;
@@ -47216,6 +47455,7 @@ var init_source_diagnostics = __esm({
47216
47455
  this.column = column;
47217
47456
  this.code = code;
47218
47457
  this.severity = severity;
47458
+ this.range = range2;
47219
47459
  this.name = "SchemaSourceError";
47220
47460
  }
47221
47461
  detail;
@@ -47224,6 +47464,7 @@ var init_source_diagnostics = __esm({
47224
47464
  column;
47225
47465
  code;
47226
47466
  severity;
47467
+ range;
47227
47468
  };
47228
47469
  }
47229
47470
  });
@@ -57633,6 +57874,8 @@ function isDialogueLogicCompileTextVariableContext(value) {
57633
57874
  if (!isNSPointer(v.pointer)) return false;
57634
57875
  if (typeof v.sourcePath !== "string") return false;
57635
57876
  if (!isNSTypeInfo(v.typeInfo)) return false;
57877
+ if (v.sourceInline !== void 0 && typeof v.sourceInline !== "boolean")
57878
+ return false;
57636
57879
  if (typeof v.variableId !== "string") return false;
57637
57880
  return isOptionalNullableString2(v.optionId);
57638
57881
  }
@@ -65451,6 +65694,898 @@ var init_dialogue_sources = __esm({
65451
65694
  }
65452
65695
  });
65453
65696
 
65697
+ // ../src/models/classes/constructor-parameter-settlement.ts
65698
+ function createConstructorSettlementResolver(view) {
65699
+ const classesById = new Map(
65700
+ view.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
65701
+ );
65702
+ const membersById = new Map(
65703
+ view.members.map((member) => [member.id, member])
65704
+ );
65705
+ const constructorsById = new Map(
65706
+ (view.constructors ?? []).map((constructor2) => [
65707
+ constructor2.id,
65708
+ constructor2
65709
+ ])
65710
+ );
65711
+ const directResultByClassAndParameter = /* @__PURE__ */ new Map();
65712
+ const recordedResultByConstructorAndParameter = /* @__PURE__ */ new Map();
65713
+ const directSettlement = (classId, parameterName) => {
65714
+ const cacheKey = `${classId}\0${parameterName}`;
65715
+ if (directResultByClassAndParameter.has(cacheKey)) {
65716
+ return directResultByClassAndParameter.get(cacheKey) ?? null;
65717
+ }
65718
+ const visited = /* @__PURE__ */ new Set();
65719
+ let currentId = classId;
65720
+ while (currentId !== null && !visited.has(currentId)) {
65721
+ visited.add(currentId);
65722
+ const schemaClass2 = classesById.get(currentId);
65723
+ if (schemaClass2 === void 0) break;
65724
+ for (const [schemaKey, memberId] of Object.entries(
65725
+ schemaClass2.schema ?? {}
65726
+ )) {
65727
+ if (typeof memberId !== "string") continue;
65728
+ const member = membersById.get(memberId);
65729
+ const defaultRecord = asRecord(member?.defaultValue);
65730
+ const initRecord = asRecord(defaultRecord?.init);
65731
+ if (initRecord !== null && typeof initRecord.code === "string" && initRecord.code.trim() === parameterName) {
65732
+ const result = { schemaKey, memberId };
65733
+ directResultByClassAndParameter.set(cacheKey, result);
65734
+ return result;
65735
+ }
65736
+ }
65737
+ currentId = schemaClass2.extendsClassId ?? null;
65738
+ }
65739
+ directResultByClassAndParameter.set(cacheKey, null);
65740
+ return null;
65741
+ };
65742
+ const memberIdForSchemaKey = (classId, schemaKey) => {
65743
+ const visited = /* @__PURE__ */ new Set();
65744
+ let currentId = classId;
65745
+ while (currentId !== null && !visited.has(currentId)) {
65746
+ visited.add(currentId);
65747
+ const schemaClass2 = classesById.get(currentId);
65748
+ if (schemaClass2 === void 0) return null;
65749
+ const memberId = schemaClass2.schema?.[schemaKey];
65750
+ if (typeof memberId === "string") return memberId;
65751
+ currentId = schemaClass2.extendsClassId ?? null;
65752
+ }
65753
+ return null;
65754
+ };
65755
+ const recordedSettlement = (classId, parameterName, constructorId, resolving) => {
65756
+ const cacheKey = `${classId}\0${constructorId}\0${parameterName}`;
65757
+ if (recordedResultByConstructorAndParameter.has(cacheKey)) {
65758
+ return recordedResultByConstructorAndParameter.get(cacheKey) ?? null;
65759
+ }
65760
+ if (resolving.has(cacheKey)) return null;
65761
+ const constructor2 = constructorsById.get(constructorId);
65762
+ if (constructor2?.classId !== classId) {
65763
+ recordedResultByConstructorAndParameter.set(cacheKey, null);
65764
+ return null;
65765
+ }
65766
+ const direct = directSettlement(classId, parameterName);
65767
+ if (direct !== null) {
65768
+ recordedResultByConstructorAndParameter.set(cacheKey, direct);
65769
+ return direct;
65770
+ }
65771
+ const schemaClass2 = classesById.get(classId);
65772
+ const baseClassId = schemaClass2?.extendsClassId;
65773
+ if (typeof baseClassId !== "string") {
65774
+ recordedResultByConstructorAndParameter.set(cacheKey, null);
65775
+ return null;
65776
+ }
65777
+ for (const field of constructor2.baseInitializerFields ?? []) {
65778
+ const record7 = asRecord(field);
65779
+ if (typeof record7?.name !== "string" || typeof record7.code !== "string" || record7.code.trim() !== parameterName) {
65780
+ continue;
65781
+ }
65782
+ const memberId = memberIdForSchemaKey(baseClassId, record7.name);
65783
+ if (memberId !== null) {
65784
+ const result = { schemaKey: record7.name, memberId };
65785
+ recordedResultByConstructorAndParameter.set(cacheKey, result);
65786
+ return result;
65787
+ }
65788
+ }
65789
+ const baseConstructorId = classesById.get(baseClassId)?.requiredConstructorId;
65790
+ if (typeof baseConstructorId !== "string") {
65791
+ recordedResultByConstructorAndParameter.set(cacheKey, null);
65792
+ return null;
65793
+ }
65794
+ resolving.add(cacheKey);
65795
+ for (const argument2 of constructor2.baseArguments ?? []) {
65796
+ const record7 = asRecord(argument2);
65797
+ if (typeof record7?.name !== "string" || typeof record7.code !== "string" || record7.code.trim() !== parameterName) {
65798
+ continue;
65799
+ }
65800
+ const result = recordedSettlement(
65801
+ baseClassId,
65802
+ record7.name,
65803
+ baseConstructorId,
65804
+ resolving
65805
+ );
65806
+ resolving.delete(cacheKey);
65807
+ recordedResultByConstructorAndParameter.set(cacheKey, result);
65808
+ return result;
65809
+ }
65810
+ resolving.delete(cacheKey);
65811
+ recordedResultByConstructorAndParameter.set(cacheKey, null);
65812
+ return null;
65813
+ };
65814
+ return (classId, parameterName, constructorId) => constructorId === void 0 ? directSettlement(classId, parameterName) : recordedSettlement(classId, parameterName, constructorId, /* @__PURE__ */ new Set());
65815
+ }
65816
+ function constructorSettledSchemaEntry(view, classId, parameterName, constructorId) {
65817
+ return createConstructorSettlementResolver(view)(
65818
+ classId,
65819
+ parameterName,
65820
+ constructorId
65821
+ );
65822
+ }
65823
+ function asRecord(value) {
65824
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
65825
+ return null;
65826
+ }
65827
+ return value;
65828
+ }
65829
+ var init_constructor_parameter_settlement = __esm({
65830
+ "../src/models/classes/constructor-parameter-settlement.ts"() {
65831
+ "use strict";
65832
+ }
65833
+ });
65834
+
65835
+ // ../src/database/neo-script-derived-bodies.ts
65836
+ function cloneAndStripClientDerivedBodies(change) {
65837
+ if (change.operation === "delete" || change.nextData === void 0) {
65838
+ return { ...change };
65839
+ }
65840
+ return {
65841
+ ...change,
65842
+ nextData: stripClientDerivedBodies(change.recordKind, change.nextData)
65843
+ };
65844
+ }
65845
+ function stripClientDerivedBodies(recordKind, nextData) {
65846
+ const record7 = asRecord2(nextData);
65847
+ return record7 === null ? nextData : strippedClone(recordKind, record7);
65848
+ }
65849
+ function hasPendingNeoScriptDerivation(recordKind, data) {
65850
+ const record7 = asRecord2(data);
65851
+ if (record7 === null) return false;
65852
+ return collectDerivedBodySites(recordKind, record7).some(
65853
+ (site) => site.authored && !(site.key in site.container)
65854
+ );
65855
+ }
65856
+ function strippedClone(recordKind, record7) {
65857
+ const next = structuredClone(record7);
65858
+ const container = asRecord2(next);
65859
+ if (container === null) return next;
65860
+ for (const site of collectDerivedBodySites(recordKind, container)) {
65861
+ delete site.container[site.key];
65862
+ }
65863
+ return next;
65864
+ }
65865
+ function collectDerivedBodySites(recordKind, record7) {
65866
+ const sites = [];
65867
+ if (recordKind === "migration") {
65868
+ sites.push({
65869
+ container: record7,
65870
+ key: "action",
65871
+ authored: typeof record7.code === "string"
65872
+ });
65873
+ return sites;
65874
+ }
65875
+ if (recordKind === "dialogue-group") {
65876
+ collectConditionSites(record7.conditions, sites);
65877
+ return sites;
65878
+ }
65879
+ if (recordKind === "dialogue-node") {
65880
+ collectDialogueNodeSites(record7, sites);
65881
+ return sites;
65882
+ }
65883
+ if (recordKind === "constructor") {
65884
+ sites.push({ container: record7, key: "action", authored: true });
65885
+ sites.push({
65886
+ container: record7,
65887
+ key: "compiledBaseArguments",
65888
+ authored: false
65889
+ });
65890
+ sites.push({
65891
+ container: record7,
65892
+ key: "compiledBaseInitializerFields",
65893
+ authored: false
65894
+ });
65895
+ return sites;
65896
+ }
65897
+ if (recordKind === "value") {
65898
+ collectValueBodySites(record7, sites);
65899
+ return sites;
65900
+ }
65901
+ if (recordKind !== "member") return sites;
65902
+ if (record7.kind === 10 /* NSProperty */) {
65903
+ sites.push({
65904
+ container: record7,
65905
+ key: "getter",
65906
+ authored: typeof record7.code === "string"
65907
+ });
65908
+ sites.push({
65909
+ container: record7,
65910
+ key: "setter",
65911
+ authored: typeof record7.setterCode === "string"
65912
+ });
65913
+ }
65914
+ if (record7.kind === 23 /* NSFunction */) {
65915
+ sites.push({
65916
+ container: record7,
65917
+ key: "action",
65918
+ authored: typeof record7.code === "string"
65919
+ });
65920
+ }
65921
+ if (record7.kind === 25 /* NSDelegate */) {
65922
+ collectDelegateClosureSite(asRecord2(record7.defaultValue), sites, false);
65923
+ }
65924
+ collectInitializerSite(asRecord2(record7.defaultValue), sites);
65925
+ return sites;
65926
+ }
65927
+ function collectValueBodySites(record7, sites) {
65928
+ collectInitializerSite(record7, sites);
65929
+ collectDelegateClosureSite(record7, sites, true);
65930
+ collectInlineDelegateArgumentSites(record7, sites);
65931
+ for (const container of [record7.value, record7.constructorArgs]) {
65932
+ if (container === null || typeof container !== "object") continue;
65933
+ for (const candidate of Object.values(container)) {
65934
+ if (!isPackedValueEnvelope(candidate)) continue;
65935
+ const child2 = asRecord2(candidate[PACKED_VALUE_ENTRY_KEY]);
65936
+ if (child2 !== null) collectValueBodySites(child2, sites);
65937
+ }
65938
+ }
65939
+ }
65940
+ function collectDialogueNodeSites(node, sites) {
65941
+ collectConditionSites(node.conditions, sites);
65942
+ collectTextVariableSites(node.variables, sites);
65943
+ if (Array.isArray(node.actions)) {
65944
+ for (const actionValue2 of node.actions) {
65945
+ const logic = asRecord2(asRecord2(actionValue2)?.logic);
65946
+ if (logic === null) continue;
65947
+ if (logic.type !== 1 /* Code */) continue;
65948
+ if (typeof logic.code !== "string") continue;
65949
+ sites.push({ container: logic, key: "action", authored: true });
65950
+ }
65951
+ }
65952
+ if (Array.isArray(node.outcomes)) {
65953
+ for (const outcomeValue of node.outcomes) {
65954
+ collectConditionSites(asRecord2(outcomeValue)?.conditions, sites);
65955
+ }
65956
+ }
65957
+ const options = asRecord2(node.optionSettings)?.options;
65958
+ if (!Array.isArray(options)) return;
65959
+ for (const optionValue of options) {
65960
+ const option = asRecord2(optionValue);
65961
+ if (option === null) continue;
65962
+ collectTextVariableSites(option.variables, sites);
65963
+ const settings = asRecord2(option.settings);
65964
+ if (settings === null) continue;
65965
+ collectConditionSites(settings.conditions, sites);
65966
+ collectConditionSites(settings.selectableConditions, sites);
65967
+ }
65968
+ }
65969
+ function collectConditionSites(value, sites) {
65970
+ if (!Array.isArray(value)) return;
65971
+ for (const conditionValue of value) {
65972
+ const condition = asRecord2(conditionValue);
65973
+ if (condition === null) continue;
65974
+ if (condition.type !== 1 /* Code */) continue;
65975
+ if (typeof condition.code !== "string") continue;
65976
+ sites.push({ container: condition, key: "getter", authored: true });
65977
+ }
65978
+ }
65979
+ function collectTextVariableSites(value, sites) {
65980
+ const variables = asRecord2(value);
65981
+ if (variables === null) return;
65982
+ for (const variableValue of Object.values(variables)) {
65983
+ const variable2 = asRecord2(variableValue);
65984
+ if (variable2 === null) continue;
65985
+ sites.push({ container: variable2, key: "getter", authored: true });
65986
+ }
65987
+ }
65988
+ function collectDelegateClosureSite(container, sites, authored) {
65989
+ const delegate = asRecord2(container?.value);
65990
+ if (delegate === null) return;
65991
+ if (typeof delegate.code !== "string") return;
65992
+ sites.push({ container: delegate, key: "action", authored });
65993
+ }
65994
+ function collectInlineDelegateArgumentSites(record7, sites) {
65995
+ const constructorArgs = asRecord2(record7.constructorArgs);
65996
+ if (constructorArgs === null) return;
65997
+ for (const argument2 of Object.values(constructorArgs)) {
65998
+ const closure = asRecord2(argument2);
65999
+ if (closure === null) continue;
66000
+ if (typeof closure.code !== "string") continue;
66001
+ sites.push({ container: closure, key: "action", authored: true });
66002
+ }
66003
+ }
66004
+ function collectInitializerSite(container, sites) {
66005
+ const init = asRecord2(container?.init);
66006
+ if (init === null) return;
66007
+ sites.push({ container: init, key: "compiled", authored: true });
66008
+ }
66009
+ function stripDerivedBodies(member) {
66010
+ return strippedClone("member", member);
66011
+ }
66012
+ function stripConstructorDerivedBodies(constructorRecord) {
66013
+ return strippedClone("constructor", constructorRecord);
66014
+ }
66015
+ function stripMigrationAction(migration) {
66016
+ return strippedClone("migration", migration);
66017
+ }
66018
+ function stampUILogicBody(logic, bodyKey) {
66019
+ if (logic?.type !== 0 /* UI */) return false;
66020
+ const body = asRecord2(logic[bodyKey]);
66021
+ if (body === null) return false;
66022
+ if (body.compilerRevision === NEOSCRIPT_COMPILER_REVISION) return false;
66023
+ body.compilerRevision = NEOSCRIPT_COMPILER_REVISION;
66024
+ return true;
66025
+ }
66026
+ function stampUILogicBodies(recordKind, data) {
66027
+ const record7 = asRecord2(data);
66028
+ if (record7 === null) return false;
66029
+ if (recordKind === "dialogue-group") {
66030
+ return stampConditionList(record7.conditions);
66031
+ }
66032
+ if (recordKind !== "dialogue-node") return false;
66033
+ let changed = stampConditionList(record7.conditions);
66034
+ if (Array.isArray(record7.actions)) {
66035
+ for (const actionValue2 of record7.actions) {
66036
+ const logic = asRecord2(asRecord2(actionValue2)?.logic);
66037
+ changed = stampUILogicBody(logic, "action") || changed;
66038
+ }
66039
+ }
66040
+ if (Array.isArray(record7.outcomes)) {
66041
+ for (const outcomeValue of record7.outcomes) {
66042
+ changed = stampConditionList(asRecord2(outcomeValue)?.conditions) || changed;
66043
+ }
66044
+ }
66045
+ const options = asRecord2(record7.optionSettings)?.options;
66046
+ if (Array.isArray(options)) {
66047
+ for (const optionValue of options) {
66048
+ const settings = asRecord2(asRecord2(optionValue)?.settings);
66049
+ if (settings === null) continue;
66050
+ changed = stampConditionList(settings.conditions) || changed;
66051
+ changed = stampConditionList(settings.selectableConditions) || changed;
66052
+ }
66053
+ }
66054
+ return changed;
66055
+ }
66056
+ function stampConditionList(value) {
66057
+ if (!Array.isArray(value)) return false;
66058
+ let changed = false;
66059
+ for (const conditionValue of value) {
66060
+ changed = stampUILogicBody(asRecord2(conditionValue), "getter") || changed;
66061
+ }
66062
+ return changed;
66063
+ }
66064
+ function asRecord2(value) {
66065
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
66066
+ return null;
66067
+ }
66068
+ return value;
66069
+ }
66070
+ var init_neo_script_derived_bodies = __esm({
66071
+ "../src/database/neo-script-derived-bodies.ts"() {
66072
+ "use strict";
66073
+ init_members();
66074
+ init_logic_types();
66075
+ init_strict_ir();
66076
+ init_packed_value_encoding();
66077
+ }
66078
+ });
66079
+
66080
+ // src/project-source/stored-value-placements.ts
66081
+ function storedValueRowsByIdV4(records2) {
66082
+ const stored = /* @__PURE__ */ new Map();
66083
+ let packed = false;
66084
+ for (const record7 of records2) {
66085
+ if (record7.deleted === true) continue;
66086
+ if (record7.recordKind !== "value") continue;
66087
+ if (!isObjectRecord2(record7.data)) continue;
66088
+ stored.set(record7.recordId, record7.data);
66089
+ packed ||= rowCarriesPackedValueContent(record7.data);
66090
+ }
66091
+ if (!packed) return stored;
66092
+ const logical = /* @__PURE__ */ new Map();
66093
+ for (const [valueId, row] of stored) {
66094
+ if (!rowCarriesPackedValueContent(row)) {
66095
+ logical.set(valueId, row);
66096
+ continue;
66097
+ }
66098
+ const authoredRow = stripClientDerivedBodies("value", row);
66099
+ if (!isMemberValue(authoredRow)) {
66100
+ throw new PackedValueEncodingError(
66101
+ `Stored value row "${valueId}" packs a child but is not a well-formed value row, so its packed payload cannot be expanded.`
66102
+ );
66103
+ }
66104
+ const decoded = decodePackedValueRow(authoredRow);
66105
+ logical.set(valueId, { ...decoded.row });
66106
+ for (const child2 of decoded.children) {
66107
+ logical.set(child2.id, { ...child2 });
66108
+ }
66109
+ }
66110
+ return logical;
66111
+ }
66112
+ function buildStoredValuePlacementIndexV4(records2, logicalValues) {
66113
+ const live = [...records2].filter((record7) => record7.deleted !== true);
66114
+ const values = logicalValues ?? storedValueRowsByIdV4(live);
66115
+ const classes = [];
66116
+ const members = [];
66117
+ const memberDataById = /* @__PURE__ */ new Map();
66118
+ const constructors = /* @__PURE__ */ new Map();
66119
+ const variantTargetClassByRootValueId = /* @__PURE__ */ new Map();
66120
+ for (const record7 of live) {
66121
+ if (!isObjectRecord2(record7.data)) continue;
66122
+ if (record7.recordKind === "value") continue;
66123
+ if (record7.recordKind === "class") {
66124
+ classes.push({
66125
+ id: record7.recordId,
66126
+ ...isStringRecord3(record7.data.schema) ? { schema: record7.data.schema } : {},
66127
+ ...typeof record7.data.extendsClassId === "string" || record7.data.extendsClassId === null ? { extendsClassId: record7.data.extendsClassId } : {},
66128
+ ...typeof record7.data.requiredConstructorId === "string" ? { requiredConstructorId: record7.data.requiredConstructorId } : {},
66129
+ ...Array.isArray(record7.data.genericParams) ? {
66130
+ genericParamIds: record7.data.genericParams.flatMap(
66131
+ (entry) => isObjectRecord2(entry) && typeof entry.id === "string" ? [entry.id] : []
66132
+ )
66133
+ } : {}
66134
+ });
66135
+ } else if (record7.recordKind === "member") {
66136
+ memberDataById.set(record7.recordId, record7.data);
66137
+ members.push({
66138
+ id: record7.recordId,
66139
+ ...record7.data.defaultValue === void 0 ? {} : { defaultValue: record7.data.defaultValue }
66140
+ });
66141
+ } else if (record7.recordKind === "constructor") {
66142
+ constructors.set(record7.recordId, record7.data);
66143
+ } else if (record7.recordKind === "variant" && typeof record7.data.valueId === "string" && typeof record7.data.classId === "string") {
66144
+ variantTargetClassByRootValueId.set(
66145
+ record7.data.valueId,
66146
+ record7.data.classId
66147
+ );
66148
+ }
66149
+ }
66150
+ const classesById = new Map(
66151
+ classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
66152
+ );
66153
+ const resolveSettlement = createConstructorSettlementResolver({
66154
+ classes,
66155
+ constructors: [...constructors].flatMap(
66156
+ ([id2, constructor2]) => typeof constructor2.classId === "string" ? [
66157
+ {
66158
+ id: id2,
66159
+ classId: constructor2.classId,
66160
+ ...Array.isArray(constructor2.baseArguments) ? { baseArguments: constructor2.baseArguments } : {},
66161
+ ...Array.isArray(constructor2.baseInitializerFields) ? {
66162
+ baseInitializerFields: constructor2.baseInitializerFields
66163
+ } : {}
66164
+ }
66165
+ ] : []
66166
+ ),
66167
+ members
66168
+ });
66169
+ const memberIdForSchemaKey = (classId, schemaKey) => {
66170
+ const visited = /* @__PURE__ */ new Set();
66171
+ let cursor = classId;
66172
+ while (cursor !== null && !visited.has(cursor)) {
66173
+ visited.add(cursor);
66174
+ const schemaClass2 = classesById.get(cursor);
66175
+ if (schemaClass2 === void 0) return null;
66176
+ const memberId = schemaClass2.schema?.[schemaKey];
66177
+ if (typeof memberId === "string") return memberId;
66178
+ cursor = schemaClass2.extendsClassId ?? null;
66179
+ }
66180
+ return null;
66181
+ };
66182
+ const childrenByParentValueId = /* @__PURE__ */ new Map();
66183
+ const placementByChildValueId = /* @__PURE__ */ new Map();
66184
+ const add = (edge) => {
66185
+ const children = childrenByParentValueId.get(edge.parentValueId) ?? /* @__PURE__ */ new Map();
66186
+ if (children.has(edge.schemaKey)) return;
66187
+ children.set(edge.schemaKey, edge);
66188
+ childrenByParentValueId.set(edge.parentValueId, children);
66189
+ if (!placementByChildValueId.has(edge.childValueId)) {
66190
+ placementByChildValueId.set(edge.childValueId, edge);
66191
+ }
66192
+ };
66193
+ for (const [parentValueId, value] of values) {
66194
+ const classId = typeof value.classId === "string" ? value.classId : null;
66195
+ const body = value.value;
66196
+ if (isObjectRecord2(body)) {
66197
+ for (const [schemaKey, childValueId2] of Object.entries(body)) {
66198
+ if (typeof childValueId2 !== "string" || !values.has(childValueId2)) {
66199
+ continue;
66200
+ }
66201
+ add({
66202
+ childValueId: childValueId2,
66203
+ memberId: classId === null ? null : memberIdForSchemaKey(classId, schemaKey),
66204
+ parentValueId,
66205
+ schemaKey,
66206
+ source: "body"
66207
+ });
66208
+ }
66209
+ }
66210
+ const constructorId = value.instanceConstructorId;
66211
+ const constructorArgs = value.constructorArgs;
66212
+ if (classId === null || typeof constructorId !== "string" || !isObjectRecord2(constructorArgs)) {
66213
+ continue;
66214
+ }
66215
+ const constructor2 = constructors.get(constructorId);
66216
+ const parameters = constructor2?.argumentTypes;
66217
+ if (constructor2 === void 0 || constructor2.classId !== classId || !Array.isArray(parameters)) {
66218
+ continue;
66219
+ }
66220
+ for (const [index, parameter4] of parameters.entries()) {
66221
+ if (!isObjectRecord2(parameter4) || typeof parameter4.name !== "string") {
66222
+ continue;
66223
+ }
66224
+ const settled = resolveSettlement(classId, parameter4.name, constructorId);
66225
+ if (settled === null) continue;
66226
+ if (isObjectRecord2(body) && Object.hasOwn(body, settled.schemaKey)) {
66227
+ continue;
66228
+ }
66229
+ const parameterId = constructorActionParameterId(constructor2, index);
66230
+ const childValueId2 = constructorArgs[parameterId];
66231
+ if (typeof childValueId2 !== "string" || !values.has(childValueId2) || !memberStoresAggregate(
66232
+ memberDataById.get(settled.memberId),
66233
+ value,
66234
+ memberDataById,
66235
+ parentValueId,
66236
+ classesById,
66237
+ variantTargetClassByRootValueId
66238
+ )) {
66239
+ continue;
66240
+ }
66241
+ add({
66242
+ childValueId: childValueId2,
66243
+ memberId: settled.memberId,
66244
+ parentValueId,
66245
+ schemaKey: settled.schemaKey,
66246
+ source: "constructor"
66247
+ });
66248
+ }
66249
+ }
66250
+ return { childrenByParentValueId, placementByChildValueId };
66251
+ }
66252
+ function memberStoresAggregate(member, parent, membersById, parentValueId, classesById, variantTargetClassByRootValueId, visitedMemberIds = /* @__PURE__ */ new Set()) {
66253
+ const kind = member?.kind;
66254
+ if (kind === 5 /* Dictionary */ || kind === 6 /* List */ || kind === 7 /* Class */ || kind === "dictionary" || kind === "list" || kind === "class") {
66255
+ return true;
66256
+ }
66257
+ if (kind !== 21 /* Generic */ && kind !== "generic") return false;
66258
+ const memberId = typeof member?.id === "string" ? member.id : null;
66259
+ if (memberId !== null && visitedMemberIds.has(memberId)) return false;
66260
+ const genericParamId = member?.genericParamId;
66261
+ const bindings = parent.genericBindings;
66262
+ if (typeof genericParamId === "string" && isObjectRecord2(bindings)) {
66263
+ const bindingMemberId = bindings[genericParamId];
66264
+ if (typeof bindingMemberId === "string") {
66265
+ return memberStoresAggregate(
66266
+ membersById.get(bindingMemberId),
66267
+ parent,
66268
+ membersById,
66269
+ parentValueId,
66270
+ classesById,
66271
+ variantTargetClassByRootValueId,
66272
+ /* @__PURE__ */ new Set([
66273
+ ...visitedMemberIds,
66274
+ ...memberId === null ? [] : [memberId]
66275
+ ])
66276
+ );
66277
+ }
66278
+ }
66279
+ const parentClassId = parent.classId;
66280
+ const variantTargetClassId = variantTargetClassByRootValueId.get(parentValueId);
66281
+ if (typeof parentClassId === "string" && typeof variantTargetClassId === "string" && classesById.get(parentClassId)?.genericParamIds?.[0] === genericParamId && classesById.has(variantTargetClassId)) {
66282
+ return true;
66283
+ }
66284
+ return false;
66285
+ }
66286
+ function isStringRecord3(value) {
66287
+ return isObjectRecord2(value) && Object.values(value).every((entry) => typeof entry === "string");
66288
+ }
66289
+ var init_stored_value_placements = __esm({
66290
+ "src/project-source/stored-value-placements.ts"() {
66291
+ "use strict";
66292
+ init_constructors2();
66293
+ init_constructor_parameter_settlement();
66294
+ init_members();
66295
+ init_neo_script_derived_bodies();
66296
+ init_value_comparison();
66297
+ }
66298
+ });
66299
+
66300
+ // src/project-source/reference-target-types.ts
66301
+ function stringArray2(value) {
66302
+ return Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
66303
+ }
66304
+ var ReferenceTargetTypes;
66305
+ var init_reference_target_types = __esm({
66306
+ "src/project-source/reference-target-types.ts"() {
66307
+ "use strict";
66308
+ init_value_graph();
66309
+ init_project();
66310
+ init_codecs();
66311
+ init_document_adapters();
66312
+ init_members();
66313
+ init_projection();
66314
+ init_value_comparison();
66315
+ init_stored_value_placements();
66316
+ ReferenceTargetTypes = class {
66317
+ constructor(state, seeds = /* @__PURE__ */ new Map(), pendingRows = [], manifest) {
66318
+ this.state = state;
66319
+ this.manifest = manifest;
66320
+ for (const [memberId, seed] of seeds) {
66321
+ if (seed.valueId)
66322
+ this.overlay.set(seed.valueId, {
66323
+ id: seed.valueId,
66324
+ memberId,
66325
+ ...encodeStoredValueNode(seed)
66326
+ });
66327
+ for (const row of seed.values ?? [])
66328
+ this.overlay.set(row.id, {
66329
+ id: row.id,
66330
+ memberId: row.memberId,
66331
+ ...encodeStoredValueRowFields(row)
66332
+ });
66333
+ }
66334
+ for (const row of pendingRows)
66335
+ this.overlay.set(row.id, {
66336
+ id: row.id,
66337
+ memberId: row.memberId,
66338
+ ...encodeStoredValueRowFields(row)
66339
+ });
66340
+ const types = [];
66341
+ this.manifestMembers = manifest && new Map(manifest.members.map((member) => [member.id, member]));
66342
+ if (manifest) {
66343
+ for (const type of manifest.classes) {
66344
+ this.classes.set(type.id, type);
66345
+ types.push({
66346
+ id: type.id,
66347
+ name: type.name,
66348
+ kind: "class",
66349
+ members: [],
66350
+ baseTypeIds: type.extendsClassId ? [type.extendsClassId] : [],
66351
+ interfaceTypeIds: type.implementsInterfaceIds
66352
+ });
66353
+ }
66354
+ for (const type of manifest.interfaces)
66355
+ types.push({
66356
+ id: type.id,
66357
+ name: type.name,
66358
+ kind: "interface",
66359
+ members: [],
66360
+ baseTypeIds: type.extendsInterfaceIds
66361
+ });
66362
+ for (const type of manifest.enums)
66363
+ types.push({ id: type.id, name: type.name, kind: "enum", members: [] });
66364
+ } else {
66365
+ for (const record7 of Object.values(state)) {
66366
+ if (record7.recordKind !== "class" && record7.recordKind !== "interface" && record7.recordKind !== "enum")
66367
+ continue;
66368
+ const data = effectiveRecordData(record7);
66369
+ if (!isObjectRecord2(data) || typeof data.name !== "string") continue;
66370
+ if (record7.recordKind === "class")
66371
+ this.classes.set(record7.recordId, data);
66372
+ types.push({
66373
+ id: record7.recordId,
66374
+ name: data.name,
66375
+ kind: record7.recordKind,
66376
+ members: [],
66377
+ baseTypeIds: typeof data.extendsClassId === "string" ? [data.extendsClassId] : stringArray2(data.extendsInterfaceIds),
66378
+ interfaceTypeIds: stringArray2(data.implementsInterfaceIds)
66379
+ });
66380
+ }
66381
+ }
66382
+ this.project = createProjectIndex({
66383
+ version: 1,
66384
+ types,
66385
+ globals: [],
66386
+ roots: []
66387
+ });
66388
+ }
66389
+ state;
66390
+ manifest;
66391
+ classes = /* @__PURE__ */ new Map();
66392
+ schemaMembers = /* @__PURE__ */ new Map();
66393
+ members = /* @__PURE__ */ new Map();
66394
+ overlay = /* @__PURE__ */ new Map();
66395
+ manifestMembers;
66396
+ directOwners;
66397
+ orderedParents;
66398
+ values;
66399
+ placements;
66400
+ records;
66401
+ project;
66402
+ targetTypes = /* @__PURE__ */ new Map();
66403
+ ownerCache = /* @__PURE__ */ new Map();
66404
+ compatibility = /* @__PURE__ */ new Map();
66405
+ stored(kind, id2) {
66406
+ const record7 = this.state[`${kind}:${id2}`];
66407
+ const data = record7 && effectiveRecordData(record7);
66408
+ return isObjectRecord2(data) ? data : void 0;
66409
+ }
66410
+ member(id2) {
66411
+ const cached = this.members.get(id2);
66412
+ if (cached !== void 0) return cached ?? void 0;
66413
+ const base = this.stored("member", id2);
66414
+ const authored = this.manifestMembers?.get(id2);
66415
+ const data = authored ? memberToDocument(
66416
+ authored,
66417
+ base,
66418
+ this.manifestMembers?.get(authored.overrideOf ?? "")
66419
+ ) : base;
66420
+ this.members.set(id2, data ?? null);
66421
+ return data;
66422
+ }
66423
+ buildRecords() {
66424
+ const records2 = new Map(
66425
+ Object.values(this.state).map((record7) => [
66426
+ `${record7.recordKind}:${record7.recordId}`,
66427
+ {
66428
+ recordKind: record7.recordKind,
66429
+ recordId: record7.recordId,
66430
+ data: effectiveRecordData(record7)
66431
+ }
66432
+ ])
66433
+ );
66434
+ if (this.manifest)
66435
+ for (const record7 of projectSchemaManifestToDocuments(this.manifest, {
66436
+ baseRecord: (kind, id2) => {
66437
+ const data = this.stored(kind, id2);
66438
+ return data ? { recordKind: kind, recordId: id2, data } : null;
66439
+ }
66440
+ }))
66441
+ records2.set(`${record7.recordKind}:${record7.recordId}`, record7);
66442
+ for (const [id2, data] of this.overlay)
66443
+ records2.set(`value:${id2}`, { recordKind: "value", recordId: id2, data });
66444
+ return [...records2.values()];
66445
+ }
66446
+ readValues() {
66447
+ return this.values ??= storedValueRowsByIdV4(
66448
+ this.records ??= this.buildRecords()
66449
+ );
66450
+ }
66451
+ value(id2) {
66452
+ return this.overlay.get(id2) ?? this.stored("value", id2) ?? this.readValues().get(id2);
66453
+ }
66454
+ readPlacements() {
66455
+ return this.placements ??= buildStoredValuePlacementIndexV4(
66456
+ this.records ??= this.buildRecords(),
66457
+ this.readValues()
66458
+ );
66459
+ }
66460
+ readDirectOwners() {
66461
+ if (this.directOwners) return this.directOwners;
66462
+ const owners = /* @__PURE__ */ new Map();
66463
+ const ids = this.manifestMembers?.keys() ?? Object.values(this.state).filter((record7) => record7.recordKind === "member").map((record7) => record7.recordId);
66464
+ for (const id2 of ids) {
66465
+ const member = this.stored("member", id2);
66466
+ if (typeof member?.valueId === "string") owners.set(member.valueId, id2);
66467
+ }
66468
+ return this.directOwners = owners;
66469
+ }
66470
+ readOrderedParents() {
66471
+ if (this.orderedParents) return this.orderedParents;
66472
+ const parents = /* @__PURE__ */ new Map();
66473
+ const values = this.readValues();
66474
+ for (const [id2, row] of values) {
66475
+ if (!Array.isArray(row.value)) continue;
66476
+ for (const child2 of row.value) {
66477
+ if (typeof child2 !== "string" || !values.has(child2)) continue;
66478
+ const entries = parents.get(child2) ?? [];
66479
+ entries.push(id2);
66480
+ parents.set(child2, entries);
66481
+ }
66482
+ }
66483
+ return this.orderedParents = parents;
66484
+ }
66485
+ assertAssignable(valueId, expectedName, label) {
66486
+ let target = this.targetTypes.get(valueId);
66487
+ if (!target) {
66488
+ const value = this.value(valueId);
66489
+ const owner = value && typeof value.classId !== "string" ? this.owner(valueId, /* @__PURE__ */ new Set()) : void 0;
66490
+ const typeId = typeof value?.classId === "string" ? value.classId : owner?.classId ?? owner?.enumId;
66491
+ target = {
66492
+ exists: value !== void 0,
66493
+ typeId: typeof typeId === "string" ? typeId : void 0
66494
+ };
66495
+ this.targetTypes.set(valueId, target);
66496
+ }
66497
+ if (!target.exists)
66498
+ throw new Error(
66499
+ `${label} references unresolved value ${JSON.stringify(valueId)}.`
66500
+ );
66501
+ const classId = target.typeId;
66502
+ const actual = typeof classId === "string" ? this.project.typeById.get(classId) : void 0;
66503
+ const expected = this.project.typeByName.get(expectedName);
66504
+ if (!expected)
66505
+ throw new Error(`${label} has unknown target type ${expectedName}.`);
66506
+ const key = `${actual?.id}:${expected.id}`;
66507
+ let compatible = this.compatibility.get(key);
66508
+ if (compatible === void 0) {
66509
+ compatible = actual !== void 0 && isNeoScriptTypeAssignable(
66510
+ { kind: "named", typeId: actual.id },
66511
+ { kind: "named", typeId: expected.id },
66512
+ this.project
66513
+ );
66514
+ this.compatibility.set(key, compatible);
66515
+ }
66516
+ if (!compatible)
66517
+ throw new Error(
66518
+ `${label} target ${JSON.stringify(valueId)} has type ${actual?.name ?? "non-class value"}; expected ${expectedName}.`
66519
+ );
66520
+ }
66521
+ collectionEntryTypeName(collectionId) {
66522
+ const collection = this.member(collectionId);
66523
+ if (collection?.kind !== 6 /* List */ && collection?.kind !== 5 /* Dictionary */)
66524
+ return null;
66525
+ const entry = typeof collection.entryMemberId === "string" ? this.member(collection.entryMemberId) : void 0;
66526
+ return typeof entry?.classId === "string" ? this.project.typeById.get(entry.classId)?.name ?? null : null;
66527
+ }
66528
+ schemaMember(classId, key) {
66529
+ const cacheKey = `${classId}:${key}`;
66530
+ const cached = this.schemaMembers.get(cacheKey);
66531
+ if (cached !== void 0) return cached;
66532
+ const visited = /* @__PURE__ */ new Set();
66533
+ let current = classId;
66534
+ while (current && !visited.has(current)) {
66535
+ visited.add(current);
66536
+ const declaration = this.classes.get(current);
66537
+ const id2 = isObjectRecord2(declaration?.schema) ? declaration.schema[key] : void 0;
66538
+ if (typeof id2 === "string") {
66539
+ this.schemaMembers.set(cacheKey, id2);
66540
+ return id2;
66541
+ }
66542
+ current = typeof declaration?.extendsClassId === "string" ? declaration.extendsClassId : void 0;
66543
+ }
66544
+ this.schemaMembers.set(cacheKey, null);
66545
+ return null;
66546
+ }
66547
+ owner(valueId, visiting) {
66548
+ const cached = this.ownerCache.get(valueId);
66549
+ if (cached !== void 0)
66550
+ return cached === null ? void 0 : this.member(cached);
66551
+ if (visiting.has(valueId)) return void 0;
66552
+ visiting.add(valueId);
66553
+ const row = this.value(valueId);
66554
+ let memberId = typeof row?.memberId === "string" ? row.memberId : this.readDirectOwners().get(valueId);
66555
+ if (!memberId)
66556
+ memberId = this.readPlacements().placementByChildValueId.get(valueId)?.memberId;
66557
+ if (!memberId) {
66558
+ const placement = this.readPlacements().placementByChildValueId.get(valueId);
66559
+ const row2 = this.value(valueId);
66560
+ const parentId = placement?.parentValueId ?? (typeof row2?.containerId === "string" ? row2.containerId : void 0);
66561
+ const parent = parentId ? this.owner(parentId, visiting) : void 0;
66562
+ if (parent?.kind === 6 /* List */ || parent?.kind === 5 /* Dictionary */) {
66563
+ if (typeof parent.entryMemberId === "string")
66564
+ memberId = parent.entryMemberId;
66565
+ } else if (placement && parentId) {
66566
+ const parentValue = this.value(parentId);
66567
+ const classId = typeof parentValue?.classId === "string" ? parentValue.classId : parent?.classId;
66568
+ if (typeof classId === "string")
66569
+ memberId = this.schemaMember(classId, placement.schemaKey);
66570
+ }
66571
+ }
66572
+ if (!memberId) {
66573
+ for (const parentId of this.readOrderedParents().get(valueId) ?? []) {
66574
+ const parent = this.owner(parentId, visiting);
66575
+ if (parent?.kind === 6 /* List */ && typeof parent.entryMemberId === "string") {
66576
+ memberId = parent.entryMemberId;
66577
+ break;
66578
+ }
66579
+ }
66580
+ }
66581
+ visiting.delete(valueId);
66582
+ this.ownerCache.set(valueId, memberId ?? null);
66583
+ return memberId ? this.member(memberId) : void 0;
66584
+ }
66585
+ };
66586
+ }
66587
+ });
66588
+
65454
66589
  // ../packages/neoscript-language/src/document-scaffold.ts
65455
66590
  var init_document_scaffold = __esm({
65456
66591
  "../packages/neoscript-language/src/document-scaffold.ts"() {
@@ -69080,144 +70215,6 @@ var init_initializer_dependencies = __esm({
69080
70215
  }
69081
70216
  });
69082
70217
 
69083
- // ../src/models/classes/constructor-parameter-settlement.ts
69084
- function createConstructorSettlementResolver(view) {
69085
- const classesById = new Map(
69086
- view.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
69087
- );
69088
- const membersById = new Map(
69089
- view.members.map((member) => [member.id, member])
69090
- );
69091
- const constructorsById = new Map(
69092
- (view.constructors ?? []).map((constructor2) => [
69093
- constructor2.id,
69094
- constructor2
69095
- ])
69096
- );
69097
- const directResultByClassAndParameter = /* @__PURE__ */ new Map();
69098
- const recordedResultByConstructorAndParameter = /* @__PURE__ */ new Map();
69099
- const directSettlement = (classId, parameterName) => {
69100
- const cacheKey = `${classId}\0${parameterName}`;
69101
- if (directResultByClassAndParameter.has(cacheKey)) {
69102
- return directResultByClassAndParameter.get(cacheKey) ?? null;
69103
- }
69104
- const visited = /* @__PURE__ */ new Set();
69105
- let currentId = classId;
69106
- while (currentId !== null && !visited.has(currentId)) {
69107
- visited.add(currentId);
69108
- const schemaClass2 = classesById.get(currentId);
69109
- if (schemaClass2 === void 0) break;
69110
- for (const [schemaKey, memberId] of Object.entries(
69111
- schemaClass2.schema ?? {}
69112
- )) {
69113
- if (typeof memberId !== "string") continue;
69114
- const member = membersById.get(memberId);
69115
- const defaultRecord = asRecord(member?.defaultValue);
69116
- const initRecord = asRecord(defaultRecord?.init);
69117
- if (initRecord !== null && typeof initRecord.code === "string" && initRecord.code.trim() === parameterName) {
69118
- const result = { schemaKey, memberId };
69119
- directResultByClassAndParameter.set(cacheKey, result);
69120
- return result;
69121
- }
69122
- }
69123
- currentId = schemaClass2.extendsClassId ?? null;
69124
- }
69125
- directResultByClassAndParameter.set(cacheKey, null);
69126
- return null;
69127
- };
69128
- const memberIdForSchemaKey = (classId, schemaKey) => {
69129
- const visited = /* @__PURE__ */ new Set();
69130
- let currentId = classId;
69131
- while (currentId !== null && !visited.has(currentId)) {
69132
- visited.add(currentId);
69133
- const schemaClass2 = classesById.get(currentId);
69134
- if (schemaClass2 === void 0) return null;
69135
- const memberId = schemaClass2.schema?.[schemaKey];
69136
- if (typeof memberId === "string") return memberId;
69137
- currentId = schemaClass2.extendsClassId ?? null;
69138
- }
69139
- return null;
69140
- };
69141
- const recordedSettlement = (classId, parameterName, constructorId, resolving) => {
69142
- const cacheKey = `${classId}\0${constructorId}\0${parameterName}`;
69143
- if (recordedResultByConstructorAndParameter.has(cacheKey)) {
69144
- return recordedResultByConstructorAndParameter.get(cacheKey) ?? null;
69145
- }
69146
- if (resolving.has(cacheKey)) return null;
69147
- const constructor2 = constructorsById.get(constructorId);
69148
- if (constructor2?.classId !== classId) {
69149
- recordedResultByConstructorAndParameter.set(cacheKey, null);
69150
- return null;
69151
- }
69152
- const direct = directSettlement(classId, parameterName);
69153
- if (direct !== null) {
69154
- recordedResultByConstructorAndParameter.set(cacheKey, direct);
69155
- return direct;
69156
- }
69157
- const schemaClass2 = classesById.get(classId);
69158
- const baseClassId = schemaClass2?.extendsClassId;
69159
- if (typeof baseClassId !== "string") {
69160
- recordedResultByConstructorAndParameter.set(cacheKey, null);
69161
- return null;
69162
- }
69163
- for (const field of constructor2.baseInitializerFields ?? []) {
69164
- const record7 = asRecord(field);
69165
- if (typeof record7?.name !== "string" || typeof record7.code !== "string" || record7.code.trim() !== parameterName) {
69166
- continue;
69167
- }
69168
- const memberId = memberIdForSchemaKey(baseClassId, record7.name);
69169
- if (memberId !== null) {
69170
- const result = { schemaKey: record7.name, memberId };
69171
- recordedResultByConstructorAndParameter.set(cacheKey, result);
69172
- return result;
69173
- }
69174
- }
69175
- const baseConstructorId = classesById.get(baseClassId)?.requiredConstructorId;
69176
- if (typeof baseConstructorId !== "string") {
69177
- recordedResultByConstructorAndParameter.set(cacheKey, null);
69178
- return null;
69179
- }
69180
- resolving.add(cacheKey);
69181
- for (const argument2 of constructor2.baseArguments ?? []) {
69182
- const record7 = asRecord(argument2);
69183
- if (typeof record7?.name !== "string" || typeof record7.code !== "string" || record7.code.trim() !== parameterName) {
69184
- continue;
69185
- }
69186
- const result = recordedSettlement(
69187
- baseClassId,
69188
- record7.name,
69189
- baseConstructorId,
69190
- resolving
69191
- );
69192
- resolving.delete(cacheKey);
69193
- recordedResultByConstructorAndParameter.set(cacheKey, result);
69194
- return result;
69195
- }
69196
- resolving.delete(cacheKey);
69197
- recordedResultByConstructorAndParameter.set(cacheKey, null);
69198
- return null;
69199
- };
69200
- return (classId, parameterName, constructorId) => constructorId === void 0 ? directSettlement(classId, parameterName) : recordedSettlement(classId, parameterName, constructorId, /* @__PURE__ */ new Set());
69201
- }
69202
- function constructorSettledSchemaEntry(view, classId, parameterName, constructorId) {
69203
- return createConstructorSettlementResolver(view)(
69204
- classId,
69205
- parameterName,
69206
- constructorId
69207
- );
69208
- }
69209
- function asRecord(value) {
69210
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
69211
- return null;
69212
- }
69213
- return value;
69214
- }
69215
- var init_constructor_parameter_settlement = __esm({
69216
- "../src/models/classes/constructor-parameter-settlement.ts"() {
69217
- "use strict";
69218
- }
69219
- });
69220
-
69221
70218
  // ../src/models/members/lookup-declared-type.ts
69222
70219
  function lookupDeclaredTypeInfo(member, collectionTypeInfo) {
69223
70220
  if (collectionTypeInfo === null) return null;
@@ -70117,7 +71114,7 @@ function collectSoftOwnedConstructorArgumentValueIds(index, ownerValueId, preser
70117
71114
  collectTypedRow(childId, typeInfo.entryTypeInfo);
70118
71115
  }
70119
71116
  }
70120
- } else if (typeInfo.type === 5 /* Dictionary */ && isStringRecord3(row.value)) {
71117
+ } else if (typeInfo.type === 5 /* Dictionary */ && isStringRecord4(row.value)) {
70121
71118
  for (const childId of Object.values(row.value)) {
70122
71119
  collectTypedRow(childId, typeInfo.entryTypeInfo);
70123
71120
  }
@@ -70139,7 +71136,7 @@ function collectSoftOwnedConstructorArgumentValueIds(index, ownerValueId, preser
70139
71136
  collectNestedConstructorArguments(valueId);
70140
71137
  };
70141
71138
  const collectClassChildren = (row, typeInfo) => {
70142
- if (!isStringRecord3(row.value)) return;
71139
+ if (!isStringRecord4(row.value)) return;
70143
71140
  const effectiveClassId = row.classId ?? (typeInfo.type === 7 /* Class */ ? typeInfo.classId : void 0);
70144
71141
  if (effectiveClassId === void 0) return;
70145
71142
  const env = rowGenericEnvironment(index.document, row);
@@ -70214,7 +71211,7 @@ function tryMemberTypeInfo(document, rawMember, env) {
70214
71211
  function isAggregateTypeInfo(typeInfo) {
70215
71212
  return typeInfo.type === 7 /* Class */ || typeInfo.type === 22 /* Interface */ || typeInfo.type === 6 /* List */ || typeInfo.type === 5 /* Dictionary */;
70216
71213
  }
70217
- function isStringRecord3(value) {
71214
+ function isStringRecord4(value) {
70218
71215
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
70219
71216
  return false;
70220
71217
  }
@@ -70636,7 +71633,7 @@ function createStoredValuePlacementTraversal(args, trackReferences = false) {
70636
71633
  if (isMemberClassBase(member)) {
70637
71634
  const classId = value.classId ?? member.classId;
70638
71635
  appendPlacement(mutablePlacementsByClassId, classId, placement);
70639
- if (!isLiteralValueContent(value) || !isStringRecord4(value.value)) {
71636
+ if (!isLiteralValueContent(value) || !isStringRecord5(value.value)) {
70640
71637
  continue;
70641
71638
  }
70642
71639
  const settledChildrenBySchemaKey = /* @__PURE__ */ new Map();
@@ -70682,7 +71679,7 @@ function createStoredValuePlacementTraversal(args, trackReferences = false) {
70682
71679
  const entryMember = membersById.get(member.entryMemberId);
70683
71680
  if (entryMember === void 0) continue;
70684
71681
  if (isMemberDictionaryBase(member)) {
70685
- if (!isStringRecord4(value.value)) continue;
71682
+ if (!isStringRecord5(value.value)) continue;
70686
71683
  for (const [key, childValueId2] of Object.entries(value.value)) {
70687
71684
  queue.push({
70688
71685
  memberId: entryMember.id,
@@ -70891,7 +71888,7 @@ function appendPlacement(index, key, placement) {
70891
71888
  placements.push(placement);
70892
71889
  }
70893
71890
  }
70894
- function isStringRecord4(value) {
71891
+ function isStringRecord5(value) {
70895
71892
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
70896
71893
  return false;
70897
71894
  }
@@ -89415,6 +90412,20 @@ function compileNSGetter(code, ctx) {
89415
90412
  ctx.source
89416
90413
  );
89417
90414
  }
90415
+ function compileNSInferredExpressionGetter(code, ctx) {
90416
+ const compiled = compileStrict(
90417
+ code,
90418
+ createContext(ctx, {
90419
+ scriptKind: "getter",
90420
+ dialogueContext: ctx.dialogueContext
90421
+ }),
90422
+ ctx.source,
90423
+ true
90424
+ );
90425
+ if (!isNSGetter(compiled))
90426
+ throw new Error("Expression compiler did not produce a getter.");
90427
+ return compiled;
90428
+ }
89418
90429
  function compileNSVoidBody(code, ctx) {
89419
90430
  const context = createContext(ctx, {
89420
90431
  scriptKind: "action",
@@ -89513,9 +90524,10 @@ function withInitializerSourcePosition(error) {
89513
90524
  error.unit
89514
90525
  );
89515
90526
  }
89516
- function compileStrict(code, context, sourceInfo) {
90527
+ function compileStrict(code, context, sourceInfo, inferExpressionReturnType = false) {
89517
90528
  const source = sourceInfo?.code === code ? sourceInfo.source : void 0;
89518
90529
  const cacheKey = JSON.stringify({
90530
+ inferExpressionReturnType,
89519
90531
  code,
89520
90532
  source,
89521
90533
  projectIdentity: compilationProjectIdentity(context.project),
@@ -89548,7 +90560,11 @@ function compileStrict(code, context, sourceInfo) {
89548
90560
  text: code
89549
90561
  },
89550
90562
  context,
89551
- { projectIndex: compilationProjectIndex(context.project), source }
90563
+ {
90564
+ projectIndex: compilationProjectIndex(context.project),
90565
+ source,
90566
+ inferExpressionReturnType
90567
+ }
89552
90568
  );
89553
90569
  if (result.diagnostics.length) {
89554
90570
  const error = result.diagnostics[0];
@@ -89619,6 +90635,7 @@ var init_compile = __esm({
89619
90635
  "../src/database/neoscript/compile.ts"() {
89620
90636
  "use strict";
89621
90637
  init_runtime_source();
90638
+ init_neoscript_guards();
89622
90639
  init_compiler();
89623
90640
  init_strict_compile_error();
89624
90641
  init_project();
@@ -90047,7 +91064,7 @@ function createTypedValueNormalizer(reader, document, childrenByContainerId, par
90047
91064
  } else {
90048
91065
  value = normalizeLiteral(row.value);
90049
91066
  }
90050
- } else if (typeInfo.type === 5 /* Dictionary */ && isStringRecord5(row.value)) {
91067
+ } else if (typeInfo.type === 5 /* Dictionary */ && isStringRecord6(row.value)) {
90051
91068
  const entries = /* @__PURE__ */ Object.create(null);
90052
91069
  for (const [key, childId] of Object.entries(row.value)) {
90053
91070
  entries[key] = normalizeTypedRow(
@@ -90128,7 +91145,7 @@ function createTypedValueNormalizer(reader, document, childrenByContainerId, par
90128
91145
  return typeof row.instanceConstructorId === "string" || Object.keys(constructorArgs).length > 0;
90129
91146
  }
90130
91147
  const normalizeClassValue = (row, typeInfo, env) => {
90131
- if (!isStringRecord5(row.value)) return normalizeLiteral(row.value);
91148
+ if (!isStringRecord6(row.value)) return normalizeLiteral(row.value);
90132
91149
  const effectiveClassId = row.classId ?? (typeInfo.type === 7 /* Class */ ? typeInfo.classId : void 0);
90133
91150
  if (effectiveClassId === void 0) return normalizeLiteral(row.value);
90134
91151
  const merged = mergeInstanceSurfaceSchema(
@@ -90198,7 +91215,7 @@ function createTypedValueNormalizer(reader, document, childrenByContainerId, par
90198
91215
  }
90199
91216
  return { normalizeConstructorArgs, normalizeTypedRow };
90200
91217
  }
90201
- function isStringRecord5(value) {
91218
+ function isStringRecord6(value) {
90202
91219
  return typeof value === "object" && value !== null && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string");
90203
91220
  }
90204
91221
  function isAggregateTypeInfo2(type) {
@@ -90448,7 +91465,7 @@ var init_effective_value_reader = __esm({
90448
91465
  const row = this.rawRow(valueId);
90449
91466
  if (row === void 0) return void 0;
90450
91467
  const classId = row.classId ?? (typeInfo?.type === 7 /* Class */ ? typeInfo.classId : void 0) ?? (isMemberClassBase(placement) ? placement.classId : void 0);
90451
- if (classId === void 0 || row.value === null || !isStringRecord5(row.value))
91468
+ if (classId === void 0 || row.value === null || !isStringRecord6(row.value))
90452
91469
  return row;
90453
91470
  if (this.resolvedRoots.has(valueId)) return row;
90454
91471
  if (this.mode(valueId) === "partial") return row;
@@ -90647,6 +91664,11 @@ var init_virtual_instance_values = __esm({
90647
91664
  });
90648
91665
 
90649
91666
  // ../src/models/neoscript/neoscript-source-catalog.ts
91667
+ function neoScriptSourceLocationsChanged(previous, next) {
91668
+ return ["getter", "setter", "action"].some(
91669
+ (key) => previous[key] !== void 0 && !canonicallyEqual2(previous[key], next[key])
91670
+ );
91671
+ }
90650
91672
  function record5(value) {
90651
91673
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
90652
91674
  }
@@ -90679,6 +91701,7 @@ function remapNeoScriptRecord(current, sources2) {
90679
91701
  var init_neoscript_source_catalog = __esm({
90680
91702
  "../src/models/neoscript/neoscript-source-catalog.ts"() {
90681
91703
  "use strict";
91704
+ init_canonical_json();
90682
91705
  init_compiler();
90683
91706
  }
90684
91707
  });
@@ -90812,6 +91835,7 @@ __export(compiler_adapter_exports, {
90812
91835
  compileNSConstructor: () => compileNSConstructor,
90813
91836
  compileNSFunction: () => compileNSFunction,
90814
91837
  compileNSGetter: () => compileNSGetter,
91838
+ compileNSInferredExpressionGetter: () => compileNSInferredExpressionGetter,
90815
91839
  compileNSInitializer: () => compileNSInitializer,
90816
91840
  compileNSSetter: () => compileNSSetter,
90817
91841
  compileNSVoidBody: () => compileNSVoidBody,
@@ -93961,251 +94985,6 @@ var init_localized_text_create_envelope = __esm({
93961
94985
  }
93962
94986
  });
93963
94987
 
93964
- // ../src/database/neo-script-derived-bodies.ts
93965
- function cloneAndStripClientDerivedBodies(change) {
93966
- if (change.operation === "delete" || change.nextData === void 0) {
93967
- return { ...change };
93968
- }
93969
- return {
93970
- ...change,
93971
- nextData: stripClientDerivedBodies(change.recordKind, change.nextData)
93972
- };
93973
- }
93974
- function stripClientDerivedBodies(recordKind, nextData) {
93975
- const record7 = asRecord2(nextData);
93976
- return record7 === null ? nextData : strippedClone(recordKind, record7);
93977
- }
93978
- function hasPendingNeoScriptDerivation(recordKind, data) {
93979
- const record7 = asRecord2(data);
93980
- if (record7 === null) return false;
93981
- return collectDerivedBodySites(recordKind, record7).some(
93982
- (site) => site.authored && !(site.key in site.container)
93983
- );
93984
- }
93985
- function strippedClone(recordKind, record7) {
93986
- const next = structuredClone(record7);
93987
- const container = asRecord2(next);
93988
- if (container === null) return next;
93989
- for (const site of collectDerivedBodySites(recordKind, container)) {
93990
- delete site.container[site.key];
93991
- }
93992
- return next;
93993
- }
93994
- function collectDerivedBodySites(recordKind, record7) {
93995
- const sites = [];
93996
- if (recordKind === "migration") {
93997
- sites.push({
93998
- container: record7,
93999
- key: "action",
94000
- authored: typeof record7.code === "string"
94001
- });
94002
- return sites;
94003
- }
94004
- if (recordKind === "dialogue-group") {
94005
- collectConditionSites(record7.conditions, sites);
94006
- return sites;
94007
- }
94008
- if (recordKind === "dialogue-node") {
94009
- collectDialogueNodeSites(record7, sites);
94010
- return sites;
94011
- }
94012
- if (recordKind === "constructor") {
94013
- sites.push({ container: record7, key: "action", authored: true });
94014
- sites.push({
94015
- container: record7,
94016
- key: "compiledBaseArguments",
94017
- authored: false
94018
- });
94019
- sites.push({
94020
- container: record7,
94021
- key: "compiledBaseInitializerFields",
94022
- authored: false
94023
- });
94024
- return sites;
94025
- }
94026
- if (recordKind === "value") {
94027
- collectValueBodySites(record7, sites);
94028
- return sites;
94029
- }
94030
- if (recordKind !== "member") return sites;
94031
- if (record7.kind === 10 /* NSProperty */) {
94032
- sites.push({
94033
- container: record7,
94034
- key: "getter",
94035
- authored: typeof record7.code === "string"
94036
- });
94037
- sites.push({
94038
- container: record7,
94039
- key: "setter",
94040
- authored: typeof record7.setterCode === "string"
94041
- });
94042
- }
94043
- if (record7.kind === 23 /* NSFunction */) {
94044
- sites.push({
94045
- container: record7,
94046
- key: "action",
94047
- authored: typeof record7.code === "string"
94048
- });
94049
- }
94050
- if (record7.kind === 25 /* NSDelegate */) {
94051
- collectDelegateClosureSite(asRecord2(record7.defaultValue), sites, false);
94052
- }
94053
- collectInitializerSite(asRecord2(record7.defaultValue), sites);
94054
- return sites;
94055
- }
94056
- function collectValueBodySites(record7, sites) {
94057
- collectInitializerSite(record7, sites);
94058
- collectDelegateClosureSite(record7, sites, true);
94059
- collectInlineDelegateArgumentSites(record7, sites);
94060
- for (const container of [record7.value, record7.constructorArgs]) {
94061
- if (container === null || typeof container !== "object") continue;
94062
- for (const candidate of Object.values(container)) {
94063
- if (!isPackedValueEnvelope(candidate)) continue;
94064
- const child2 = asRecord2(candidate[PACKED_VALUE_ENTRY_KEY]);
94065
- if (child2 !== null) collectValueBodySites(child2, sites);
94066
- }
94067
- }
94068
- }
94069
- function collectDialogueNodeSites(node, sites) {
94070
- collectConditionSites(node.conditions, sites);
94071
- collectTextVariableSites(node.variables, sites);
94072
- if (Array.isArray(node.actions)) {
94073
- for (const actionValue2 of node.actions) {
94074
- const logic = asRecord2(asRecord2(actionValue2)?.logic);
94075
- if (logic === null) continue;
94076
- if (logic.type !== 1 /* Code */) continue;
94077
- if (typeof logic.code !== "string") continue;
94078
- sites.push({ container: logic, key: "action", authored: true });
94079
- }
94080
- }
94081
- if (Array.isArray(node.outcomes)) {
94082
- for (const outcomeValue of node.outcomes) {
94083
- collectConditionSites(asRecord2(outcomeValue)?.conditions, sites);
94084
- }
94085
- }
94086
- const options = asRecord2(node.optionSettings)?.options;
94087
- if (!Array.isArray(options)) return;
94088
- for (const optionValue of options) {
94089
- const option = asRecord2(optionValue);
94090
- if (option === null) continue;
94091
- collectTextVariableSites(option.variables, sites);
94092
- const settings = asRecord2(option.settings);
94093
- if (settings === null) continue;
94094
- collectConditionSites(settings.conditions, sites);
94095
- collectConditionSites(settings.selectableConditions, sites);
94096
- }
94097
- }
94098
- function collectConditionSites(value, sites) {
94099
- if (!Array.isArray(value)) return;
94100
- for (const conditionValue of value) {
94101
- const condition = asRecord2(conditionValue);
94102
- if (condition === null) continue;
94103
- if (condition.type !== 1 /* Code */) continue;
94104
- if (typeof condition.code !== "string") continue;
94105
- sites.push({ container: condition, key: "getter", authored: true });
94106
- }
94107
- }
94108
- function collectTextVariableSites(value, sites) {
94109
- const variables = asRecord2(value);
94110
- if (variables === null) return;
94111
- for (const variableValue of Object.values(variables)) {
94112
- const variable2 = asRecord2(variableValue);
94113
- if (variable2 === null) continue;
94114
- sites.push({ container: variable2, key: "getter", authored: true });
94115
- }
94116
- }
94117
- function collectDelegateClosureSite(container, sites, authored) {
94118
- const delegate = asRecord2(container?.value);
94119
- if (delegate === null) return;
94120
- if (typeof delegate.code !== "string") return;
94121
- sites.push({ container: delegate, key: "action", authored });
94122
- }
94123
- function collectInlineDelegateArgumentSites(record7, sites) {
94124
- const constructorArgs = asRecord2(record7.constructorArgs);
94125
- if (constructorArgs === null) return;
94126
- for (const argument2 of Object.values(constructorArgs)) {
94127
- const closure = asRecord2(argument2);
94128
- if (closure === null) continue;
94129
- if (typeof closure.code !== "string") continue;
94130
- sites.push({ container: closure, key: "action", authored: true });
94131
- }
94132
- }
94133
- function collectInitializerSite(container, sites) {
94134
- const init = asRecord2(container?.init);
94135
- if (init === null) return;
94136
- sites.push({ container: init, key: "compiled", authored: true });
94137
- }
94138
- function stripDerivedBodies(member) {
94139
- return strippedClone("member", member);
94140
- }
94141
- function stripConstructorDerivedBodies(constructorRecord) {
94142
- return strippedClone("constructor", constructorRecord);
94143
- }
94144
- function stripMigrationAction(migration) {
94145
- return strippedClone("migration", migration);
94146
- }
94147
- function stampUILogicBody(logic, bodyKey) {
94148
- if (logic?.type !== 0 /* UI */) return false;
94149
- const body = asRecord2(logic[bodyKey]);
94150
- if (body === null) return false;
94151
- if (body.compilerRevision === NEOSCRIPT_COMPILER_REVISION) return false;
94152
- body.compilerRevision = NEOSCRIPT_COMPILER_REVISION;
94153
- return true;
94154
- }
94155
- function stampUILogicBodies(recordKind, data) {
94156
- const record7 = asRecord2(data);
94157
- if (record7 === null) return false;
94158
- if (recordKind === "dialogue-group") {
94159
- return stampConditionList(record7.conditions);
94160
- }
94161
- if (recordKind !== "dialogue-node") return false;
94162
- let changed = stampConditionList(record7.conditions);
94163
- if (Array.isArray(record7.actions)) {
94164
- for (const actionValue2 of record7.actions) {
94165
- const logic = asRecord2(asRecord2(actionValue2)?.logic);
94166
- changed = stampUILogicBody(logic, "action") || changed;
94167
- }
94168
- }
94169
- if (Array.isArray(record7.outcomes)) {
94170
- for (const outcomeValue of record7.outcomes) {
94171
- changed = stampConditionList(asRecord2(outcomeValue)?.conditions) || changed;
94172
- }
94173
- }
94174
- const options = asRecord2(record7.optionSettings)?.options;
94175
- if (Array.isArray(options)) {
94176
- for (const optionValue of options) {
94177
- const settings = asRecord2(asRecord2(optionValue)?.settings);
94178
- if (settings === null) continue;
94179
- changed = stampConditionList(settings.conditions) || changed;
94180
- changed = stampConditionList(settings.selectableConditions) || changed;
94181
- }
94182
- }
94183
- return changed;
94184
- }
94185
- function stampConditionList(value) {
94186
- if (!Array.isArray(value)) return false;
94187
- let changed = false;
94188
- for (const conditionValue of value) {
94189
- changed = stampUILogicBody(asRecord2(conditionValue), "getter") || changed;
94190
- }
94191
- return changed;
94192
- }
94193
- function asRecord2(value) {
94194
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
94195
- return null;
94196
- }
94197
- return value;
94198
- }
94199
- var init_neo_script_derived_bodies = __esm({
94200
- "../src/database/neo-script-derived-bodies.ts"() {
94201
- "use strict";
94202
- init_members();
94203
- init_logic_types();
94204
- init_strict_ir();
94205
- init_packed_value_encoding();
94206
- }
94207
- });
94208
-
94209
94988
  // ../src/database/neo-script-recompile-scope.ts
94210
94989
  function memberNeoScriptContractChanged(current, next) {
94211
94990
  return canonicalJsonStringify(neoScriptMemberContractProjection(current)) !== canonicalJsonStringify(neoScriptMemberContractProjection(next));
@@ -101806,14 +102585,14 @@ function findParentValues(valueId, values) {
101806
102585
  }
101807
102586
  continue;
101808
102587
  }
101809
- if (!isStringRecord6(value.value)) continue;
102588
+ if (!isStringRecord7(value.value)) continue;
101810
102589
  for (const [key, childValueId2] of Object.entries(value.value)) {
101811
102590
  if (childValueId2 === valueId) parents.push({ value, key });
101812
102591
  }
101813
102592
  }
101814
102593
  return parents;
101815
102594
  }
101816
- function isStringRecord6(value) {
102595
+ function isStringRecord7(value) {
101817
102596
  if (typeof value !== "object") return false;
101818
102597
  if (value === null) return false;
101819
102598
  if (Array.isArray(value)) return false;
@@ -101990,9 +102769,16 @@ function compileDialogueLogicWithProjectData(request, projectData) {
101990
102769
  node: request.node,
101991
102770
  returnTypeInfo: sourceBacked ? request.textVariable.typeInfo : { type: 3 /* String */, required: true }
101992
102771
  });
102772
+ if (!sourceBacked)
102773
+ return {
102774
+ target: 2 /* TextVariable */,
102775
+ getter: compileTextVariableGetter(ctx2, request.textVariable)
102776
+ };
102777
+ const getter = request.textVariable.sourceInline ? compileNSInferredExpressionGetter(request.code, ctx2) : compileNSGetter(request.code, ctx2);
101993
102778
  return {
101994
102779
  target: 2 /* TextVariable */,
101995
- getter: sourceBacked ? stringifyCompiledTextGetter(compileNSGetter(request.code, ctx2)) : compileTextVariableGetter(ctx2, request.textVariable)
102780
+ getter: stringifyCompiledTextGetter(getter),
102781
+ sourceTypeInfo: getter.typeInfo
101996
102782
  };
101997
102783
  }
101998
102784
  if (request.dialogueGroup) {
@@ -102765,7 +103551,8 @@ function recompileDialogueNode(args) {
102765
103551
  (message) => ({
102766
103552
  target: 1 /* Action */,
102767
103553
  action: makeThrowBody(message, VOID_ACTION_TYPE_INFO)
102768
- })
103554
+ }),
103555
+ typeof logic.sourceFunctionId === "string" ? { id: logic.sourceFunctionId, code: logic.code } : void 0
102769
103556
  );
102770
103557
  if (!compiled.ok) continue;
102771
103558
  const response = compiled.value;
@@ -102855,7 +103642,8 @@ function recompileConditionList(value, context) {
102855
103642
  (message) => ({
102856
103643
  target: 0 /* Condition */,
102857
103644
  getter: makeThrowBody(message, BOOL_TYPE_INFO)
102858
- })
103645
+ }),
103646
+ typeof condition.sourceFunctionId === "string" ? { id: condition.sourceFunctionId, code: condition.code } : void 0
102859
103647
  );
102860
103648
  if (!compiled.ok) continue;
102861
103649
  const response = compiled.value;
@@ -102884,6 +103672,7 @@ function recompileTextVariables(value, context) {
102884
103672
  dialogue: context.dialogue,
102885
103673
  node: context.node,
102886
103674
  textVariable: {
103675
+ sourceInline: variable2.sourceInline === true,
102887
103676
  nodeId: context.nodeId,
102888
103677
  optionId: context.optionId,
102889
103678
  pointer: variable2.pointer,
@@ -102901,7 +103690,14 @@ function recompileTextVariables(value, context) {
102901
103690
  (message) => ({
102902
103691
  target: 2 /* TextVariable */,
102903
103692
  getter: makeThrowBody(message, STRING_TYPE_INFO)
102904
- })
103693
+ }),
103694
+ {
103695
+ id: variable2.sourceInline === true ? variableId : requiredString2(
103696
+ variable2.sourceFunctionId ?? variableId,
103697
+ "text source function id"
103698
+ ),
103699
+ code: typeof variable2.code === "string" ? variable2.code : ""
103700
+ }
102905
103701
  );
102906
103702
  if (!compiled.ok) continue;
102907
103703
  const response = compiled.value;
@@ -102909,6 +103705,7 @@ function recompileTextVariables(value, context) {
102909
103705
  throw new Error("Dialogue text-variable compilation returned code IR.");
102910
103706
  }
102911
103707
  variable2.getter = response.getter;
103708
+ if (response.sourceTypeInfo) variable2.typeInfo = response.sourceTypeInfo;
102912
103709
  changed = true;
102913
103710
  }
102914
103711
  return changed;
@@ -102927,7 +103724,7 @@ function buildDialogueContext(dialogue, nodes) {
102927
103724
  }
102928
103725
  };
102929
103726
  }
102930
- function compileSourceUnit(label, compile, onSourceRejection, compileErrorFallback) {
103727
+ function compileSourceUnit(label, compile, onSourceRejection, compileErrorFallback, body) {
102931
103728
  try {
102932
103729
  return { ok: true, value: compile() };
102933
103730
  } catch (error) {
@@ -102939,6 +103736,8 @@ function compileSourceUnit(label, compile, onSourceRejection, compileErrorFallba
102939
103736
  }
102940
103737
  return { ok: false };
102941
103738
  }
103739
+ if (error instanceof CompileError && body)
103740
+ throw new SourceBodyCompileError(label, body.id, body.code, error);
102942
103741
  throw new Error(`Cannot recompile ${label}: ${message}`, { cause: error });
102943
103742
  }
102944
103743
  }
@@ -102980,7 +103779,7 @@ function asObject(value) {
102980
103779
  function cloneObject(value) {
102981
103780
  return structuredClone(value);
102982
103781
  }
102983
- var VOID_ACTION_TYPE_INFO, BOOL_TYPE_INFO, STRING_TYPE_INFO;
103782
+ var SourceBodyCompileError, VOID_ACTION_TYPE_INFO, BOOL_TYPE_INFO, STRING_TYPE_INFO;
102984
103783
  var init_general_function_call_ir_source_recompile = __esm({
102985
103784
  "../src/database/general-function-call-ir-source-recompile.ts"() {
102986
103785
  "use strict";
@@ -103000,6 +103799,22 @@ var init_general_function_call_ir_source_recompile = __esm({
103000
103799
  init_dialogue_node_index();
103001
103800
  init_strict_ir();
103002
103801
  init_neo_script_derived_bodies();
103802
+ SourceBodyCompileError = class extends Error {
103803
+ constructor(sourceLabel, bodyId, code, compileError) {
103804
+ super(`Cannot recompile ${sourceLabel}: ${compileError.message}`, {
103805
+ cause: compileError
103806
+ });
103807
+ this.sourceLabel = sourceLabel;
103808
+ this.bodyId = bodyId;
103809
+ this.code = code;
103810
+ this.compileError = compileError;
103811
+ this.name = "SourceBodyCompileError";
103812
+ }
103813
+ sourceLabel;
103814
+ bodyId;
103815
+ code;
103816
+ compileError;
103817
+ };
103003
103818
  VOID_ACTION_TYPE_INFO = {
103004
103819
  type: 0 /* Null */,
103005
103820
  required: true
@@ -104636,9 +105451,9 @@ function assertNumberRange(member, value, path) {
104636
105451
  }
104637
105452
  }
104638
105453
  function stringRecord3(value) {
104639
- return isStringRecord7(value) ? value : null;
105454
+ return isStringRecord8(value) ? value : null;
104640
105455
  }
104641
- function isStringRecord7(value) {
105456
+ function isStringRecord8(value) {
104642
105457
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
104643
105458
  return false;
104644
105459
  }
@@ -105501,7 +106316,7 @@ function* prepareServerOwnedSchemaCommitPasses(args) {
105501
106316
  }
105502
106317
  let hasSourceLocationChange = false;
105503
106318
  for (const [key, source] of args.scriptSources ?? []) {
105504
- if (!canonicallyEqual2(scriptSources.get(key), source))
106319
+ if (neoScriptSourceLocationsChanged(scriptSources.get(key) ?? {}, source))
105505
106320
  hasSourceLocationChange = true;
105506
106321
  scriptSources.set(key, source);
105507
106322
  }
@@ -105721,7 +106536,7 @@ function* prepareServerOwnedSchemaCommitPasses(args) {
105721
106536
  const source = scriptSources.get(key);
105722
106537
  const base = baseScriptRecords.get(key);
105723
106538
  if (targets.has(record7.id) || !source || !base) continue;
105724
- if (!sourceOnlyKeys.has(key) && canonicallyEqual2(source, neoScriptRecordSources(base)))
106539
+ if (!sourceOnlyKeys.has(key) && !neoScriptSourceLocationsChanged(neoScriptRecordSources(base), source))
105725
106540
  continue;
105726
106541
  const moved = remapNeoScriptRecord(base, source);
105727
106542
  targets.add(record7.id);
@@ -117799,7 +118614,7 @@ function toWorldReferenceClassRecord(value) {
117799
118614
  return {
117800
118615
  id: id2,
117801
118616
  extendsClassId: nullableStringField(value, "extendsClassId"),
117802
- schema: isStringRecord8(value.schema) ? value.schema : void 0,
118617
+ schema: isStringRecord9(value.schema) ? value.schema : void 0,
117803
118618
  system: isPlainRecord7(value.system) ? value.system : null
117804
118619
  };
117805
118620
  }
@@ -117817,7 +118632,7 @@ function worldReferenceValueClassId(value) {
117817
118632
  if (value === void 0) return null;
117818
118633
  return typeof value.classId === "string" && value.classId.length > 0 ? value.classId : null;
117819
118634
  }
117820
- function isStringRecord8(value) {
118635
+ function isStringRecord9(value) {
117821
118636
  if (!isPlainRecord7(value)) return false;
117822
118637
  return Object.values(value).every((entry) => typeof entry === "string");
117823
118638
  }
@@ -122833,7 +123648,8 @@ function builtinTextVariableMember(receiver, name) {
122833
123648
  }
122834
123649
  return null;
122835
123650
  }
122836
- function lowerDialogueProjectSourcesV4(state, analysis) {
123651
+ function lowerDialogueProjectSourcesV4(state, analysis, options = {}) {
123652
+ const sourceCapture = options.sourceCapture;
122837
123653
  const result = [];
122838
123654
  const mainLocale = readMainLocale(state);
122839
123655
  const dialogueGroups = analysis.dialogueGroups.globals.filter(
@@ -122849,94 +123665,133 @@ function lowerDialogueProjectSourcesV4(state, analysis) {
122849
123665
  const sourceSchema = new SourceSchemaIndex(analysis);
122850
123666
  const valueSymbols = indexValueSymbols(state, analysis);
122851
123667
  const nodesByDialogueId = dialogueNodesByDialogueId(state);
123668
+ let referenceTypeIndex;
123669
+ const referenceTypes = () => referenceTypeIndex ??= new ReferenceTargetTypes(
123670
+ state,
123671
+ options.authoredValueSeeds,
123672
+ [],
123673
+ options.manifest
123674
+ );
122852
123675
  for (const dialogue of analysis.dialogues.dialogues) {
122853
- const dialogueId = sourceId2(dialogue, "dialogue", dialogue.name);
122854
- const baseDialogue = baseData2(state, "dialogue", dialogueId);
122855
- const nodesById = nodesByDialogueId.get(dialogueId) ?? /* @__PURE__ */ new Map();
122856
- const memberIdsByName = new Map(
122857
- dialogue.members.map((member) => [
122858
- member.name,
122859
- sourceId2(member, "dialogue-node", member.name)
122860
- ])
122861
- );
122862
- const functionsByName = new Map(
122863
- dialogue.functions.map((fn) => [fn.name, fn])
122864
- );
122865
- const context = {
122866
- state,
122867
- dialogue,
122868
- dialogueId,
122869
- baseDialogue,
122870
- nodesById,
122871
- memberIdsByName,
122872
- functionsByName,
122873
- existingLogic: indexExistingLogic(nodesById.values()),
122874
- mainLocale,
122875
- dialogueGroupIds,
122876
- lookupDialogueGroupIds,
122877
- priorityGroupsById,
122878
- valueSymbols,
122879
- sourceSchema,
122880
- dialogueBindingTypes: new Map(
122881
- dialogue.bindings.map((binding) => [binding.name, binding.type])
122882
- ),
122883
- dialogueLinks: Array.isArray(baseDialogue.linkedValues) ? baseDialogue.linkedValues.filter(isObjectRecord2) : [],
122884
- dialoguePrimaryValueId: nullableString4(baseDialogue.primaryLinkedValueId),
122885
- sourcePrimaryAlias: primaryBindingName(dialogue.bindings)
122886
- };
122887
- const trigger = dialogue.members.find(
122888
- (member) => member.graphType === "Trigger"
122889
- );
122890
- if (!trigger)
122891
- throw new Error(`Dialogue ${dialogue.name} requires Trigger.`);
122892
- const settings = annotationArguments(dialogue.annotations, "settings");
122893
- const linked = lowerBindings(
122894
- context,
122895
- dialogue.bindings,
122896
- baseDialogue.linkedValues
122897
- );
122898
- const primary = primaryValueId(dialogue.bindings, linked);
122899
- const graphContext = {
122900
- ...context,
122901
- dialogueLinks: linked,
122902
- dialoguePrimaryValueId: primary
122903
- };
122904
- const description = lowerDialogueDescription(
122905
- context,
122906
- settings.get("description"),
122907
- result
122908
- );
122909
- result.push(
122910
- reconstructed2(
122911
- "dialogue",
123676
+ try {
123677
+ const dialogueId = sourceId2(dialogue, "dialogue", dialogue.name);
123678
+ const baseDialogue = baseData2(state, "dialogue", dialogueId);
123679
+ const nodesById = nodesByDialogueId.get(dialogueId) ?? /* @__PURE__ */ new Map();
123680
+ const memberIdsByName = new Map(
123681
+ dialogue.members.map((member) => [
123682
+ member.name,
123683
+ sourceId2(member, "dialogue-node", member.name)
123684
+ ])
123685
+ );
123686
+ const functionsByName = new Map(
123687
+ dialogue.functions.map((fn) => [fn.name, fn])
123688
+ );
123689
+ const context = {
123690
+ sourceCapture,
123691
+ referenceTypes,
123692
+ state,
123693
+ dialogue,
122912
123694
  dialogueId,
122913
- {
122914
- ...baseDialogue,
122915
- id: dialogueId,
122916
- sourceName: dialogue.name,
122917
- name: literalString(settings.get("name")) ?? stringOr(baseDialogue.name, dialogue.name),
122918
- description,
122919
- settings: {
122920
- ...isObjectRecord2(baseDialogue.settings) ? baseDialogue.settings : {},
122921
- defaultSaveOptionChoices: literalBoolean(settings.get("saveOptionChoices")) ?? booleanOr(
122922
- isObjectRecord2(baseDialogue.settings) ? baseDialogue.settings.defaultSaveOptionChoices : void 0,
122923
- true
122924
- )
123695
+ baseDialogue,
123696
+ nodesById,
123697
+ memberIdsByName,
123698
+ functionsByName,
123699
+ existingLogic: indexExistingLogic(nodesById.values()),
123700
+ mainLocale,
123701
+ dialogueGroupIds,
123702
+ lookupDialogueGroupIds,
123703
+ priorityGroupsById,
123704
+ valueSymbols,
123705
+ sourceSchema,
123706
+ dialogueBindingTypes: new Map(
123707
+ dialogue.bindings.map((binding) => [binding.name, binding.type])
123708
+ ),
123709
+ dialogueLinks: Array.isArray(baseDialogue.linkedValues) ? baseDialogue.linkedValues.filter(isObjectRecord2) : [],
123710
+ dialoguePrimaryValueId: nullableString4(
123711
+ baseDialogue.primaryLinkedValueId
123712
+ ),
123713
+ sourcePrimaryAlias: primaryBindingName(dialogue.bindings)
123714
+ };
123715
+ const trigger = dialogue.members.find(
123716
+ (member) => member.graphType === "Trigger"
123717
+ );
123718
+ if (!trigger)
123719
+ throw new Error(`Dialogue ${dialogue.name} requires Trigger.`);
123720
+ const settings = annotationArguments(dialogue.annotations, "settings");
123721
+ const linked = lowerBindings(
123722
+ context,
123723
+ dialogue.bindings,
123724
+ baseDialogue.linkedValues
123725
+ );
123726
+ const primary = primaryValueId(dialogue.bindings, linked);
123727
+ const graphContext = {
123728
+ ...context,
123729
+ dialogueLinks: linked,
123730
+ dialoguePrimaryValueId: primary
123731
+ };
123732
+ const description = lowerDialogueDescription(
123733
+ context,
123734
+ settings.get("description"),
123735
+ result
123736
+ );
123737
+ result.push(
123738
+ reconstructed2(
123739
+ "dialogue",
123740
+ dialogueId,
123741
+ {
123742
+ ...baseDialogue,
123743
+ id: dialogueId,
123744
+ sourceName: dialogue.name,
123745
+ name: literalString(settings.get("name")) ?? stringOr(baseDialogue.name, dialogue.name),
123746
+ description,
123747
+ settings: {
123748
+ ...isObjectRecord2(baseDialogue.settings) ? baseDialogue.settings : {},
123749
+ defaultSaveOptionChoices: literalBoolean(settings.get("saveOptionChoices")) ?? booleanOr(
123750
+ isObjectRecord2(baseDialogue.settings) ? baseDialogue.settings.defaultSaveOptionChoices : void 0,
123751
+ true
123752
+ )
123753
+ },
123754
+ linkedValues: linked,
123755
+ primaryLinkedValueId: primary,
123756
+ triggerNodeId: sourceId2(trigger, "dialogue-node", trigger.name)
122925
123757
  },
122926
- linkedValues: linked,
122927
- primaryLinkedValueId: primary,
122928
- triggerNodeId: sourceId2(trigger, "dialogue-node", trigger.name)
122929
- },
122930
- dialogue
122931
- )
122932
- );
122933
- dialogue.members.forEach((member, index) => {
122934
- const lowered = lowerGraphMember(graphContext, member, index);
122935
- result.push(...lowered);
122936
- });
123758
+ dialogue
123759
+ )
123760
+ );
123761
+ dialogue.members.forEach((member, index) => {
123762
+ try {
123763
+ result.push(
123764
+ ...lowerGraphMember(
123765
+ {
123766
+ ...graphContext,
123767
+ sourceOwnerName: `${dialogue.name}.${member.name}`
123768
+ },
123769
+ member,
123770
+ index
123771
+ )
123772
+ );
123773
+ } catch (error) {
123774
+ throw dialogueSourceError(error, member.source);
123775
+ }
123776
+ });
123777
+ } catch (error) {
123778
+ throw dialogueSourceError(error, dialogue.source);
123779
+ }
122937
123780
  }
122938
123781
  return result;
122939
123782
  }
123783
+ function dialogueSourceError(error, source) {
123784
+ if (error instanceof SchemaSourceError) return error;
123785
+ return new SchemaSourceError(
123786
+ error instanceof Error ? error.message : String(error),
123787
+ source.uri,
123788
+ source.range.start.line + 1,
123789
+ source.range.start.character + 1,
123790
+ "neoflow-lowering",
123791
+ "error",
123792
+ source.range
123793
+ );
123794
+ }
122940
123795
  function lowerGraphMember(context, member, index) {
122941
123796
  const id2 = sourceId2(member, "dialogue-node", member.name);
122942
123797
  const base = context.nodesById.get(id2) ?? {};
@@ -123055,7 +123910,8 @@ function lowerTextNode(context, member, id2, base, common, destination) {
123055
123910
  nullableString4(common.primaryLinkedValueId) ?? context.dialoguePrimaryValueId,
123056
123911
  `node:${id2}`,
123057
123912
  dialogueNodeLocalizedTextLink(id2),
123058
- member
123913
+ member,
123914
+ member.content?.proseSources?.[0]
123059
123915
  );
123060
123916
  const children = member.content?.children.filter((child2) => child2.graphType === "Option") ?? [];
123061
123917
  const baseOptionSettings = isObjectRecord2(base.optionSettings) ? base.optionSettings : {};
@@ -123081,7 +123937,8 @@ function lowerTextNode(context, member, id2, base, common, destination) {
123081
123937
  nullableString4(common.primaryLinkedValueId) ?? context.dialoguePrimaryValueId,
123082
123938
  `option:${optionId}`,
123083
123939
  dialogueChoiceLocalizedTextLink(id2, optionId),
123084
- child2
123940
+ child2,
123941
+ child2.content?.proseSources?.[0]
123085
123942
  );
123086
123943
  if (optionText.textRecord) textRecords.push(optionText.textRecord);
123087
123944
  const priorSettings = isObjectRecord2(optionBase.settings) ? optionBase.settings : {};
@@ -123279,6 +124136,14 @@ function lowerConditionUses(context, expression, owner) {
123279
124136
  `${owner} condition ${use.name} must resolve to a zero-argument bool function.`
123280
124137
  );
123281
124138
  }
124139
+ context.sourceCapture?.bodies.set(
124140
+ sourceId2(fn, "dialogue-function", fn.name),
124141
+ {
124142
+ name: `${context.dialogue.name}.${fn.name}`,
124143
+ location: fn.bodySource ?? fn.source,
124144
+ thisAlias: context.sourcePrimaryAlias ?? void 0
124145
+ }
124146
+ );
123282
124147
  const prior = context.existingLogic.conditionsByUseId.get(id2);
123283
124148
  const body = functionCode(fn);
123284
124149
  if (body === null) {
@@ -123353,6 +124218,14 @@ function conditionProjectionMatches(context, prior, body) {
123353
124218
  return false;
123354
124219
  }
123355
124220
  function lowerActionLogic(context, prior, fn, fallbackCode, inline, useId, uiResolver) {
124221
+ context.sourceCapture?.bodies.set(
124222
+ inline ? useId : sourceId2(fn, "dialogue-function", fn.name),
124223
+ {
124224
+ name: inline ? `${context.sourceOwnerName} action` : `${context.dialogue.name}.${fn.name}`,
124225
+ location: fn.bodySource ?? fn.source,
124226
+ thisAlias: context.sourcePrimaryAlias ?? void 0
124227
+ }
124228
+ );
123356
124229
  const code = functionCode(fn) ?? fallbackCode;
123357
124230
  if (prior?.type === 0) {
123358
124231
  const projected = uiActionSource(prior.action, uiResolver);
@@ -123379,7 +124252,7 @@ function lowerActionLogic(context, prior, fn, fallbackCode, inline, useId, uiRes
123379
124252
  action: isObjectRecord2(prior?.action) ? prior.action : placeholderVoidAction()
123380
124253
  };
123381
124254
  }
123382
- function lowerProse(context, rawProse, baseTextId, baseVariables, baseLinks, bindingTypes, primaryValueId2, owner, textLink, source) {
124255
+ function lowerProse(context, rawProse, baseTextId, baseVariables, baseLinks, bindingTypes, primaryValueId2, owner, textLink, source, proseSource) {
123383
124256
  const textId = baseTextId ?? pendingId("localized-text", source.source.uri, owner, 0, "text");
123384
124257
  const baseText = baseData2(context.state, "localized-text", textId);
123385
124258
  const variablesByPath = /* @__PURE__ */ new Map();
@@ -123411,8 +124284,13 @@ function lowerProse(context, rawProse, baseTextId, baseVariables, baseLinks, bin
123411
124284
  const main2 = isObjectRecord2(mainCandidate) ? mainCandidate : {};
123412
124285
  const pulledMainText = typeof main2.value === "string" ? main2.value : "";
123413
124286
  let ordinal = 0;
124287
+ let expressionOrdinal = 0;
124288
+ const rawExpressions = context.sourceCapture ? decodeProseSegments(rawProse, false).filter(
124289
+ (segment) => segment.kind === "expression"
124290
+ ) : [];
123414
124291
  const value = decodeProseSegments(rawProse).map((segment) => {
123415
124292
  if (segment.kind === "literal") return segment.value;
124293
+ const rawExpression = rawExpressions[expressionOrdinal++];
123416
124294
  const expression = segment.value;
123417
124295
  const sourcePath = expression.trim();
123418
124296
  const missingVariableId = missingTextVariableId(sourcePath);
@@ -123445,6 +124323,30 @@ function lowerProse(context, rawProse, baseTextId, baseVariables, baseLinks, bin
123445
124323
  const functionName = callExpressionName(sourcePath) ?? `TextValue${ordinal + 1}`;
123446
124324
  const fn = callExpressionName(sourcePath) ? context.functionsByName.get(functionName) : void 0;
123447
124325
  const functionBody = fn ? functionCode(fn) : null;
124326
+ const capture = context.sourceCapture;
124327
+ if (capture) {
124328
+ let location3 = source.source;
124329
+ const text = capture.texts.get(location3.uri);
124330
+ if (text !== void 0 && proseSource && rawExpression) {
124331
+ const file = text;
124332
+ const start = file.offsetAt(proseSource.range.start) + 3;
124333
+ location3 = {
124334
+ uri: location3.uri,
124335
+ range: {
124336
+ start: file.positionAt(start + rawExpression.start),
124337
+ end: file.positionAt(start + rawExpression.end)
124338
+ }
124339
+ };
124340
+ }
124341
+ const bodyId = fn ? sourceId2(fn, "dialogue-function", fn.name) : variableId;
124342
+ const effectivePrimaryAlias = typeof primaryAlias === "string" ? primaryAlias : void 0;
124343
+ if (!capture.bodies.has(bodyId))
124344
+ capture.bodies.set(bodyId, {
124345
+ name: fn ? `${context.dialogue.name}.${fn.name}` : `${context.sourceOwnerName} interpolation`,
124346
+ location: fn?.bodySource ?? fn?.source ?? location3,
124347
+ thisAlias: fn ? context.sourcePrimaryAlias ?? void 0 : effectivePrimaryAlias
124348
+ });
124349
+ }
123448
124350
  if (prior !== void 0 && (fn === void 0 || functionBody === null)) {
123449
124351
  const declaredFunction = fn ?? sourceFunctionForPrior(context, prior);
123450
124352
  variables[variableId] = declaredFunction ? {
@@ -123484,7 +124386,7 @@ function lowerProse(context, rawProse, baseTextId, baseVariables, baseLinks, bin
123484
124386
  bindingTypes,
123485
124387
  primaryValueId2
123486
124388
  );
123487
- const sourceTypeInfo = fn ? sourceReturnTypeInfo(fn.type.name, fn.type.nullable) : directMetadata?.typeInfo ?? (isObjectRecord2(prior?.typeInfo) ? prior.typeInfo : { type: 3 /* String */, required: true });
124389
+ const sourceTypeInfo = fn ? sourceReturnTypeInfo(fn.type.name, fn.type.nullable) : directMetadata?.typeInfo ?? (isObjectRecord2(prior?.typeInfo) ? prior.typeInfo : { type: NS_TYPE_UNKNOWN, required: true });
123488
124390
  variables[variableId] = {
123489
124391
  ...prior ?? {},
123490
124392
  id: variableId,
@@ -123740,12 +124642,33 @@ function lowerBindings(context, bindings, baseLinks) {
123740
124642
  const explicit = bindings.map((binding) => {
123741
124643
  if (binding.initializer === null)
123742
124644
  throw new Error(`Binding ${binding.name} requires an initializer.`);
123743
- const valueId = resolveBindingValueId(
123744
- context,
123745
- binding.initializer,
123746
- existing,
123747
- binding.name
123748
- );
124645
+ let valueId;
124646
+ try {
124647
+ const expression = parseExpression(binding.initializer);
124648
+ valueId = resolveBindingValueId(
124649
+ context,
124650
+ binding.initializer,
124651
+ binding.name,
124652
+ expression
124653
+ );
124654
+ if (expression.kind === "call" && expression.callee.kind === "ident" && expression.callee.name === "Reference") {
124655
+ const explicit2 = expression.typeArguments?.[0];
124656
+ if (explicit2) {
124657
+ const name = astTypeNameV4(explicit2);
124658
+ context.referenceTypes().assertAssignable(valueId, name, `Reference<${name}>`);
124659
+ }
124660
+ }
124661
+ context.referenceTypes().assertAssignable(
124662
+ valueId,
124663
+ binding.type.name,
124664
+ `Binding ${binding.name}`
124665
+ );
124666
+ } catch (error) {
124667
+ throw dialogueSourceError(
124668
+ error,
124669
+ binding.initializerSource ?? binding.source
124670
+ );
124671
+ }
123749
124672
  const previous = existing.find(
123750
124673
  (link) => link.valueId === valueId || link.sourceName === binding.name
123751
124674
  );
@@ -123787,7 +124710,8 @@ function lowerNodeBindings(context, content, baseLinks) {
123787
124710
  (binding) => ({
123788
124711
  id: null,
123789
124712
  state: "pending",
123790
- source: context.dialogue.source,
124713
+ source: binding.source ?? context.dialogue.source,
124714
+ initializerSource: binding.source,
123791
124715
  kind: "field",
123792
124716
  name: binding.name,
123793
124717
  type: parseManifestTypeText(binding.type),
@@ -123864,31 +124788,33 @@ function parseManifestTypeText(source) {
123864
124788
  }
123865
124789
  return result;
123866
124790
  }
123867
- function resolveBindingValueId(context, initializer, existing, sourceName) {
123868
- const idMatch = initializer.match(
123869
- /\bReference(?:<[^>]+>)?\s*\(\s*(?:id\s*:\s*)?("(?:[^"\\]|\\.)*")\s*\)/
123870
- );
123871
- if (idMatch?.[1]) return JSON.parse(idMatch[1]);
124791
+ function resolveBindingValueId(context, initializer, sourceName, expression) {
124792
+ if (expression.kind === "call" && expression.callee.kind === "ident" && expression.callee.name === "Reference") {
124793
+ const idIndex = expression.argumentNames?.indexOf("id") ?? -1;
124794
+ if (idIndex >= 0) {
124795
+ const id2 = expression.args[idIndex];
124796
+ if (id2?.kind === "litString") return id2.value;
124797
+ }
124798
+ if (expression.argumentNames?.includes("key"))
124799
+ throw new Error(
124800
+ `Binding ${sourceName}: Reference(key:) requires a lookup field's collection context. Use Reference<T>(id: "...").`
124801
+ );
124802
+ }
123872
124803
  const direct = directValueSymbol(initializer);
123873
124804
  if (direct !== null) {
123874
124805
  const symbol = context.valueSymbols.get(direct);
123875
124806
  if (symbol !== void 0) return symbol.valueId;
123876
124807
  }
123877
- const byName = existing.find((link) => link.sourceName === sourceName);
123878
- if (typeof byName?.valueId === "string") return byName.valueId;
123879
- if (existing.length === 1 && typeof existing[0]?.valueId === "string") {
123880
- return existing[0].valueId;
123881
- }
123882
124808
  throw new Error(
123883
124809
  `Binding ${sourceName} initializer ${JSON.stringify(initializer)} cannot be resolved to a stable value. Use Reference<T>(id: "...").`
123884
124810
  );
123885
124811
  }
123886
124812
  function directValueSymbol(initializer) {
123887
124813
  const trimmed = initializer.trim();
123888
- if (/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)+$/.test(trimmed)) {
124814
+ if (/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(trimmed)) {
123889
124815
  return trimmed;
123890
124816
  }
123891
- const reference2 = /^Reference(?:<[^>]+>)?\s*\(\s*([A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)+)\s*\)$/.exec(
124817
+ const reference2 = /^Reference(?:<[^>]+>)?\s*\(\s*([A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*)\s*\)$/.exec(
123892
124818
  trimmed
123893
124819
  );
123894
124820
  return reference2?.[1] ?? null;
@@ -124035,13 +124961,18 @@ function proseExpressions(raw) {
124035
124961
  );
124036
124962
  }
124037
124963
  function lowerDialogueGroupSettings(context, member, base) {
124964
+ const groupSource = member.arguments.find((argument2) => argument2.name === "group")?.source ?? member.source;
124965
+ const prioritySource = member.arguments.find((argument2) => argument2.name === "priority")?.source ?? groupSource;
124038
124966
  const expression = constructorExpression(member.arguments, "group");
124039
124967
  if (expression === null) return null;
124040
124968
  const old = isObjectRecord2(base.dialogueGroupSettings) ? base.dialogueGroupSettings : {};
124041
124969
  const referencedGroupId = referenceId2(expression, "DialogueGroup");
124042
124970
  if (referencedGroupId !== null) {
124043
124971
  if (![...context.dialogueGroupIds.values()].includes(referencedGroupId)) {
124044
- throw new Error(`Unknown dialogue group ${referencedGroupId}.`);
124972
+ throw dialogueSourceError(
124973
+ `Unknown dialogue group ${referencedGroupId}.`,
124974
+ groupSource
124975
+ );
124045
124976
  }
124046
124977
  const group2 = baseData2(context.state, "dialogue-group", referencedGroupId);
124047
124978
  const priorityGroupId2 = nullableString4(group2.priorityGroupIdOverride) ?? defaultPriorityGroupId(context.state);
@@ -124053,14 +124984,18 @@ function lowerDialogueGroupSettings(context, member, base) {
124053
124984
  );
124054
124985
  const priorityOptionId = priorityExpression === null ? null : referenceId2(priorityExpression, "PriorityOption");
124055
124986
  if (priorityExpression !== null && priorityOptionId === null) {
124056
- throw new Error(
124057
- 'Trigger priority must be authored as Reference<PriorityOption>(id: "...").'
124987
+ throw dialogueSourceError(
124988
+ 'Trigger priority must be authored as Reference<PriorityOption>(id: "...").',
124989
+ prioritySource
124058
124990
  );
124059
124991
  }
124060
124992
  if (priorityOptionId !== null && !options2.some(
124061
124993
  (candidate) => isObjectRecord2(candidate) && candidate.id === priorityOptionId
124062
124994
  )) {
124063
- throw new Error(`Unknown priority option ${priorityOptionId}.`);
124995
+ throw dialogueSourceError(
124996
+ `Unknown priority option ${priorityOptionId}.`,
124997
+ prioritySource
124998
+ );
124064
124999
  }
124065
125000
  return {
124066
125001
  ...old,
@@ -124075,12 +125010,17 @@ function lowerDialogueGroupSettings(context, member, base) {
124075
125010
  }
124076
125011
  const [groupName, optionName] = expression.split(".");
124077
125012
  if (!groupName || !optionName) {
124078
- throw new Error(
124079
- `Trigger group must be authored as DialogueGroup.PriorityOption.`
125013
+ throw dialogueSourceError(
125014
+ `Trigger group must be authored as DialogueGroup.PriorityOption.`,
125015
+ groupSource
124080
125016
  );
124081
125017
  }
124082
125018
  const groupId = context.dialogueGroupIds.get(groupName);
124083
- if (!groupId) throw new Error(`Unknown dialogue group ${groupName}.`);
125019
+ if (!groupId)
125020
+ throw dialogueSourceError(
125021
+ `Unknown dialogue group ${groupName}.`,
125022
+ groupSource
125023
+ );
124084
125024
  const group = baseData2(context.state, "dialogue-group", groupId);
124085
125025
  const priorityGroupId = nullableString4(group.priorityGroupIdOverride) ?? defaultPriorityGroupId(context.state);
124086
125026
  const priority = priorityGroupId ? context.priorityGroupsById.get(priorityGroupId) : void 0;
@@ -124089,7 +125029,10 @@ function lowerDialogueGroupSettings(context, member, base) {
124089
125029
  (candidate) => isObjectRecord2(candidate) && candidate.name === optionName
124090
125030
  );
124091
125031
  if (!isObjectRecord2(option) || typeof option.id !== "string") {
124092
- throw new Error(`Unknown priority option ${expression}.`);
125032
+ throw dialogueSourceError(
125033
+ `Unknown priority option ${expression}.`,
125034
+ groupSource
125035
+ );
124093
125036
  }
124094
125037
  return {
124095
125038
  ...old,
@@ -124103,8 +125046,29 @@ function lowerDialogueGroupSettings(context, member, base) {
124103
125046
  };
124104
125047
  }
124105
125048
  function lookupValueSettings(context, groupId, old) {
124106
- if (context.lookupDialogueGroupIds.has(groupId))
124107
- return { lookupValueId: context.dialoguePrimaryValueId };
125049
+ if (context.lookupDialogueGroupIds.has(groupId)) {
125050
+ const valueId = context.dialoguePrimaryValueId;
125051
+ const group = baseData2(context.state, "dialogue-group", groupId);
125052
+ const typeName = typeof group.collectionMemberId === "string" ? context.referenceTypes().collectionEntryTypeName(group.collectionMemberId) : null;
125053
+ if (valueId !== null && typeName !== null) {
125054
+ const primary = context.dialogue.bindings.find(
125055
+ (binding) => hasAnnotation3(binding.annotations, "primary")
125056
+ );
125057
+ try {
125058
+ context.referenceTypes().assertAssignable(
125059
+ valueId,
125060
+ typeName,
125061
+ `Lookup group ${String(group.name ?? groupId)}`
125062
+ );
125063
+ } catch (error) {
125064
+ throw dialogueSourceError(
125065
+ error,
125066
+ primary?.initializerSource ?? primary?.source ?? context.dialogue.source
125067
+ );
125068
+ }
125069
+ }
125070
+ return { lookupValueId: valueId };
125071
+ }
124108
125072
  return old.lookupValueId == null ? {} : { lookupValueId: null };
124109
125073
  }
124110
125074
  function referenceId2(expression, typeName) {
@@ -124184,8 +125148,8 @@ function decodeProse(raw) {
124184
125148
  if (indent2.length === 0) return value;
124185
125149
  return value.split("\n").map((line) => line.startsWith(indent2) ? line.slice(indent2.length) : line).join("\n");
124186
125150
  }
124187
- function decodeProseSegments(raw) {
124188
- const value = decodeProse(raw);
125151
+ function decodeProseSegments(raw, decode2 = true) {
125152
+ const value = decode2 ? decodeProse(raw) : raw.slice(3, -3);
124189
125153
  const result = [];
124190
125154
  let literal3 = "";
124191
125155
  const flushLiteral = () => {
@@ -124225,7 +125189,12 @@ function decodeProseSegments(raw) {
124225
125189
  if (expression.length === 0) {
124226
125190
  throw new Error("NeoFlow prose interpolation cannot be empty.");
124227
125191
  }
124228
- result.push({ kind: "expression", value: expression });
125192
+ result.push({
125193
+ kind: "expression",
125194
+ value: expression,
125195
+ start: index + 1,
125196
+ end
125197
+ });
124229
125198
  index = end;
124230
125199
  }
124231
125200
  flushLiteral();
@@ -124518,6 +125487,22 @@ function indexValueSymbols(state, analysis) {
124518
125487
  });
124519
125488
  }
124520
125489
  }
125490
+ const locals = new LocalValueBindingsV4(
125491
+ analysis.values.globals,
125492
+ analysis.schema.enums.map((entry) => entry.name),
125493
+ staticMembersInitializedByName(analysis)
125494
+ );
125495
+ for (const declaration of analysis.values.globals) {
125496
+ const target = locals.declaredTarget(declaration.name);
125497
+ if (target === null) continue;
125498
+ const valueId = "id" in target ? target.id : result.get(target.ownerPath)?.valueId;
125499
+ if (valueId !== void 0)
125500
+ result.set(declaration.name, {
125501
+ valueId,
125502
+ declaredTypeName: declaration.type.name,
125503
+ declaredType: declaration.type
125504
+ });
125505
+ }
124521
125506
  return result;
124522
125507
  }
124523
125508
  function memberDeclaredTypeName(member, classes) {
@@ -124609,6 +125594,10 @@ var SourceSchemaIndex;
124609
125594
  var init_dialogue_lower = __esm({
124610
125595
  "src/project-source/dialogue-lower.ts"() {
124611
125596
  "use strict";
125597
+ init_local_values();
125598
+ init_key_reference_spelling();
125599
+ init_reference_target_types();
125600
+ init_source_diagnostics();
124612
125601
  init_executable_parser();
124613
125602
  init_strict_ir();
124614
125603
  init_localization_types();
@@ -124904,226 +125893,6 @@ var init_dialogue_lower = __esm({
124904
125893
  }
124905
125894
  });
124906
125895
 
124907
- // src/project-source/stored-value-placements.ts
124908
- function storedValueRowsByIdV4(records2) {
124909
- const stored = /* @__PURE__ */ new Map();
124910
- let packed = false;
124911
- for (const record7 of records2) {
124912
- if (record7.deleted === true) continue;
124913
- if (record7.recordKind !== "value") continue;
124914
- if (!isObjectRecord2(record7.data)) continue;
124915
- stored.set(record7.recordId, record7.data);
124916
- packed ||= rowCarriesPackedValueContent(record7.data);
124917
- }
124918
- if (!packed) return stored;
124919
- const logical = /* @__PURE__ */ new Map();
124920
- for (const [valueId, row] of stored) {
124921
- if (!rowCarriesPackedValueContent(row)) {
124922
- logical.set(valueId, row);
124923
- continue;
124924
- }
124925
- const authoredRow = stripClientDerivedBodies("value", row);
124926
- if (!isMemberValue(authoredRow)) {
124927
- throw new PackedValueEncodingError(
124928
- `Stored value row "${valueId}" packs a child but is not a well-formed value row, so its packed payload cannot be expanded.`
124929
- );
124930
- }
124931
- const decoded = decodePackedValueRow(authoredRow);
124932
- logical.set(valueId, { ...decoded.row });
124933
- for (const child2 of decoded.children) {
124934
- logical.set(child2.id, { ...child2 });
124935
- }
124936
- }
124937
- return logical;
124938
- }
124939
- function buildStoredValuePlacementIndexV4(records2) {
124940
- const live = [...records2].filter((record7) => record7.deleted !== true);
124941
- const values = storedValueRowsByIdV4(live);
124942
- const classes = [];
124943
- const members = [];
124944
- const memberDataById = /* @__PURE__ */ new Map();
124945
- const constructors = /* @__PURE__ */ new Map();
124946
- const variantTargetClassByRootValueId = /* @__PURE__ */ new Map();
124947
- for (const record7 of live) {
124948
- if (!isObjectRecord2(record7.data)) continue;
124949
- if (record7.recordKind === "value") continue;
124950
- if (record7.recordKind === "class") {
124951
- classes.push({
124952
- id: record7.recordId,
124953
- ...isStringRecord9(record7.data.schema) ? { schema: record7.data.schema } : {},
124954
- ...typeof record7.data.extendsClassId === "string" || record7.data.extendsClassId === null ? { extendsClassId: record7.data.extendsClassId } : {},
124955
- ...typeof record7.data.requiredConstructorId === "string" ? { requiredConstructorId: record7.data.requiredConstructorId } : {},
124956
- ...Array.isArray(record7.data.genericParams) ? {
124957
- genericParamIds: record7.data.genericParams.flatMap(
124958
- (entry) => isObjectRecord2(entry) && typeof entry.id === "string" ? [entry.id] : []
124959
- )
124960
- } : {}
124961
- });
124962
- } else if (record7.recordKind === "member") {
124963
- memberDataById.set(record7.recordId, record7.data);
124964
- members.push({
124965
- id: record7.recordId,
124966
- ...record7.data.defaultValue === void 0 ? {} : { defaultValue: record7.data.defaultValue }
124967
- });
124968
- } else if (record7.recordKind === "constructor") {
124969
- constructors.set(record7.recordId, record7.data);
124970
- } else if (record7.recordKind === "variant" && typeof record7.data.valueId === "string" && typeof record7.data.classId === "string") {
124971
- variantTargetClassByRootValueId.set(
124972
- record7.data.valueId,
124973
- record7.data.classId
124974
- );
124975
- }
124976
- }
124977
- const classesById = new Map(
124978
- classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
124979
- );
124980
- const resolveSettlement = createConstructorSettlementResolver({
124981
- classes,
124982
- constructors: [...constructors].flatMap(
124983
- ([id2, constructor2]) => typeof constructor2.classId === "string" ? [
124984
- {
124985
- id: id2,
124986
- classId: constructor2.classId,
124987
- ...Array.isArray(constructor2.baseArguments) ? { baseArguments: constructor2.baseArguments } : {},
124988
- ...Array.isArray(constructor2.baseInitializerFields) ? {
124989
- baseInitializerFields: constructor2.baseInitializerFields
124990
- } : {}
124991
- }
124992
- ] : []
124993
- ),
124994
- members
124995
- });
124996
- const memberIdForSchemaKey = (classId, schemaKey) => {
124997
- const visited = /* @__PURE__ */ new Set();
124998
- let cursor = classId;
124999
- while (cursor !== null && !visited.has(cursor)) {
125000
- visited.add(cursor);
125001
- const schemaClass2 = classesById.get(cursor);
125002
- if (schemaClass2 === void 0) return null;
125003
- const memberId = schemaClass2.schema?.[schemaKey];
125004
- if (typeof memberId === "string") return memberId;
125005
- cursor = schemaClass2.extendsClassId ?? null;
125006
- }
125007
- return null;
125008
- };
125009
- const childrenByParentValueId = /* @__PURE__ */ new Map();
125010
- const placementByChildValueId = /* @__PURE__ */ new Map();
125011
- const add = (edge) => {
125012
- const children = childrenByParentValueId.get(edge.parentValueId) ?? /* @__PURE__ */ new Map();
125013
- if (children.has(edge.schemaKey)) return;
125014
- children.set(edge.schemaKey, edge);
125015
- childrenByParentValueId.set(edge.parentValueId, children);
125016
- if (!placementByChildValueId.has(edge.childValueId)) {
125017
- placementByChildValueId.set(edge.childValueId, edge);
125018
- }
125019
- };
125020
- for (const [parentValueId, value] of values) {
125021
- const classId = typeof value.classId === "string" ? value.classId : null;
125022
- const body = value.value;
125023
- if (isObjectRecord2(body)) {
125024
- for (const [schemaKey, childValueId2] of Object.entries(body)) {
125025
- if (typeof childValueId2 !== "string" || !values.has(childValueId2)) {
125026
- continue;
125027
- }
125028
- add({
125029
- childValueId: childValueId2,
125030
- memberId: classId === null ? null : memberIdForSchemaKey(classId, schemaKey),
125031
- parentValueId,
125032
- schemaKey,
125033
- source: "body"
125034
- });
125035
- }
125036
- }
125037
- const constructorId = value.instanceConstructorId;
125038
- const constructorArgs = value.constructorArgs;
125039
- if (classId === null || typeof constructorId !== "string" || !isObjectRecord2(constructorArgs)) {
125040
- continue;
125041
- }
125042
- const constructor2 = constructors.get(constructorId);
125043
- const parameters = constructor2?.argumentTypes;
125044
- if (constructor2 === void 0 || constructor2.classId !== classId || !Array.isArray(parameters)) {
125045
- continue;
125046
- }
125047
- for (const [index, parameter4] of parameters.entries()) {
125048
- if (!isObjectRecord2(parameter4) || typeof parameter4.name !== "string") {
125049
- continue;
125050
- }
125051
- const settled = resolveSettlement(classId, parameter4.name, constructorId);
125052
- if (settled === null) continue;
125053
- if (isObjectRecord2(body) && Object.hasOwn(body, settled.schemaKey)) {
125054
- continue;
125055
- }
125056
- const parameterId = constructorActionParameterId(constructor2, index);
125057
- const childValueId2 = constructorArgs[parameterId];
125058
- if (typeof childValueId2 !== "string" || !values.has(childValueId2) || !memberStoresAggregate(
125059
- memberDataById.get(settled.memberId),
125060
- value,
125061
- memberDataById,
125062
- parentValueId,
125063
- classesById,
125064
- variantTargetClassByRootValueId
125065
- )) {
125066
- continue;
125067
- }
125068
- add({
125069
- childValueId: childValueId2,
125070
- memberId: settled.memberId,
125071
- parentValueId,
125072
- schemaKey: settled.schemaKey,
125073
- source: "constructor"
125074
- });
125075
- }
125076
- }
125077
- return { childrenByParentValueId, placementByChildValueId };
125078
- }
125079
- function memberStoresAggregate(member, parent, membersById, parentValueId, classesById, variantTargetClassByRootValueId, visitedMemberIds = /* @__PURE__ */ new Set()) {
125080
- const kind = member?.kind;
125081
- if (kind === 5 /* Dictionary */ || kind === 6 /* List */ || kind === 7 /* Class */ || kind === "dictionary" || kind === "list" || kind === "class") {
125082
- return true;
125083
- }
125084
- if (kind !== 21 /* Generic */ && kind !== "generic") return false;
125085
- const memberId = typeof member?.id === "string" ? member.id : null;
125086
- if (memberId !== null && visitedMemberIds.has(memberId)) return false;
125087
- const genericParamId = member?.genericParamId;
125088
- const bindings = parent.genericBindings;
125089
- if (typeof genericParamId === "string" && isObjectRecord2(bindings)) {
125090
- const bindingMemberId = bindings[genericParamId];
125091
- if (typeof bindingMemberId === "string") {
125092
- return memberStoresAggregate(
125093
- membersById.get(bindingMemberId),
125094
- parent,
125095
- membersById,
125096
- parentValueId,
125097
- classesById,
125098
- variantTargetClassByRootValueId,
125099
- /* @__PURE__ */ new Set([
125100
- ...visitedMemberIds,
125101
- ...memberId === null ? [] : [memberId]
125102
- ])
125103
- );
125104
- }
125105
- }
125106
- const parentClassId = parent.classId;
125107
- const variantTargetClassId = variantTargetClassByRootValueId.get(parentValueId);
125108
- if (typeof parentClassId === "string" && typeof variantTargetClassId === "string" && classesById.get(parentClassId)?.genericParamIds?.[0] === genericParamId && classesById.has(variantTargetClassId)) {
125109
- return true;
125110
- }
125111
- return false;
125112
- }
125113
- function isStringRecord9(value) {
125114
- return isObjectRecord2(value) && Object.values(value).every((entry) => typeof entry === "string");
125115
- }
125116
- var init_stored_value_placements = __esm({
125117
- "src/project-source/stored-value-placements.ts"() {
125118
- "use strict";
125119
- init_constructors2();
125120
- init_constructor_parameter_settlement();
125121
- init_members();
125122
- init_neo_script_derived_bodies();
125123
- init_value_comparison();
125124
- }
125125
- });
125126
-
125127
125896
  // src/project-source/root-source.ts
125128
125897
  function emitProjectRootSourceV4(records2, manifest, materializedConstructors, localValues, options = {}) {
125129
125898
  const project = [...records2.values()].find(
@@ -127035,7 +127804,8 @@ function computeWorkspaceStatus(workspace, options) {
127035
127804
  diagnostic2.range.start.line + 1,
127036
127805
  diagnostic2.range.start.character + 1,
127037
127806
  diagnostic2.code,
127038
- diagnostic2.severity
127807
+ diagnostic2.severity,
127808
+ diagnostic2.range
127039
127809
  );
127040
127810
  if (positioned.severity === "error") parseErrors.push(positioned);
127041
127811
  else parseWarnings.push(positioned);
@@ -127542,10 +128312,28 @@ function computeWorkspaceStatus(workspace, options) {
127542
128312
  ],
127543
128313
  staticMemberValueIds
127544
128314
  );
127545
- const dialogueRecords = lowerDialogueProjectSourcesV4(
127546
- prospectiveState,
127547
- projectAnalysisV4
127548
- );
128315
+ const dialogueBodySources = /* @__PURE__ */ new Map();
128316
+ let dialogueRecords;
128317
+ try {
128318
+ dialogueRecords = lowerDialogueProjectSourcesV4(
128319
+ prospectiveState,
128320
+ projectAnalysisV4,
128321
+ {
128322
+ authoredValueSeeds,
128323
+ manifest,
128324
+ sourceCapture: {
128325
+ texts: new Map(
128326
+ compilationSources.filter((input) => input.uri.endsWith(".neoflow")).map((input) => [input.uri, new SourceText(input.text)])
128327
+ ),
128328
+ bodies: dialogueBodySources
128329
+ }
128330
+ }
128331
+ );
128332
+ } catch (error) {
128333
+ if (!(error instanceof SchemaSourceError)) throw error;
128334
+ parseErrors.push(error);
128335
+ return refusedStatus(conflictedFiles, parseErrors, parseWarnings);
128336
+ }
127549
128337
  reportPhase("supplemental-dialogue", "Comparing records\u2026");
127550
128338
  records2.push(
127551
128339
  ...staticValues.records,
@@ -128061,6 +128849,7 @@ function computeWorkspaceStatus(workspace, options) {
128061
128849
  );
128062
128850
  return {
128063
128851
  ...projectAnalysisV4 === null ? {} : {
128852
+ dialogueBodySources,
128064
128853
  sourceSnapshot: {
128065
128854
  inputs: compilationSources,
128066
128855
  analysis: projectAnalysisV4
@@ -129121,6 +129910,7 @@ var ANIMATION_DOCUMENT_RECORD_KINDS, ANIMATION_REPLAY_RECORD_KINDS, PROSPECTIVE_
129121
129910
  var init_workspace_status_core = __esm({
129122
129911
  "src/project-source/workspace-status-core.ts"() {
129123
129912
  "use strict";
129913
+ init_source_text();
129124
129914
  init_runtime_diagnostic();
129125
129915
  init_NSGetterRuntimeError();
129126
129916
  init_lower_support();
@@ -131430,7 +132220,15 @@ function buildValueLowerContext(state, manifest, options = {}) {
131430
132220
  let storedValuePlacements;
131431
132221
  const readStoredValuePlacements = () => storedValuePlacements ??= buildStoredValuePlacementIndexV4(stateRecords);
131432
132222
  let rootValueTargets;
132223
+ let referenceTypes;
132224
+ const readReferenceTypes = () => referenceTypes ??= new ReferenceTargetTypes(
132225
+ state,
132226
+ void 0,
132227
+ registry.pendingValues.values(),
132228
+ manifest
132229
+ );
131433
132230
  return {
132231
+ referenceTypes: readReferenceTypes,
131434
132232
  listenerBindings: registry.listenerBindings,
131435
132233
  misplacedLocalListeners: registry.misplacedLocalListeners,
131436
132234
  localValues: registry.localValues ??= new LocalValueBindingsV4(
@@ -132099,6 +132897,21 @@ function lowerMemberDefaultSourcesV4(state, analysis, manifest, options = {}) {
132099
132897
  continue;
132100
132898
  }
132101
132899
  if (!defaultRequiresOwnedRows(context, member, expression, binding)) {
132900
+ if (member.kind === "lookup" || member.kind === "dialogueLookup") {
132901
+ const entries = expression.kind === "litList" ? expression.elements : [expression];
132902
+ for (const entry of entries) {
132903
+ const target = referenceTargetSpelling(context, entry);
132904
+ if (target?.spelling !== "id" && target?.spelling !== "symbol")
132905
+ continue;
132906
+ context.referenceObligations.push({
132907
+ kind: "reference",
132908
+ site: referenceSite(binding, entry),
132909
+ memberId,
132910
+ ownerValueId: null,
132911
+ target
132912
+ });
132913
+ }
132914
+ }
132102
132915
  continue;
132103
132916
  }
132104
132917
  const rootValueId = pendingValueId(binding, `${label}.default`);
@@ -135963,6 +136776,12 @@ function validateReferenceContract(context, member, target, ownerValueId) {
135963
136776
  `Lookup member ${member.name} target ${target.id} is ${classDisplayName2(context, actualClassId)}, but the member declares ${classDisplayName2(context, declaredClassId)} \u2014 ${narrowedFrom} and this member narrows it. Point it at a ${classDisplayName2(context, declaredClassId)} row.`
135964
136777
  );
135965
136778
  }
136779
+ if (target.genericTypeName)
136780
+ context.referenceTypes().assertAssignable(
136781
+ target.id,
136782
+ target.genericTypeName,
136783
+ `Reference<${target.genericTypeName}>`
136784
+ );
135966
136785
  if (target.genericTypeName && expectedTypeName && !referenceTypeNameAssignable(
135967
136786
  context,
135968
136787
  target.genericTypeName,
@@ -138913,6 +139732,7 @@ var INFERRED_GENERIC_CLASS_PREFIX, MEMBER_KIND_DICTIONARY2, MEMBER_KIND_LIST2, M
138913
139732
  var init_value_sources = __esm({
138914
139733
  "src/project-source/value-sources.ts"() {
138915
139734
  "use strict";
139735
+ init_reference_target_types();
138916
139736
  init_listener_template_graph();
138917
139737
  init_listener_template_type();
138918
139738
  init_project_root_members();
@@ -140943,6 +141763,75 @@ var init_project_file_source_preservation = __esm({
140943
141763
  }
140944
141764
  });
140945
141765
 
141766
+ // src/project-source/dialogue-source-diagnostic.ts
141767
+ function locateDialogueSourceError(error, sources2, texts, assigned) {
141768
+ if (!(error instanceof SourceBodyCompileError) || !sources2) return error;
141769
+ let bodyId = error.bodyId;
141770
+ for (const [pending, final] of assigned)
141771
+ if (final === bodyId) {
141772
+ bodyId = pending;
141773
+ break;
141774
+ }
141775
+ const body = sources2.get(bodyId);
141776
+ if (!body) return error;
141777
+ const { location: location3 } = body;
141778
+ const text = texts.get(location3.uri);
141779
+ let range2 = location3.range;
141780
+ let line = range2.start.line + 1;
141781
+ let column = range2.start.character + 1;
141782
+ if (text !== void 0) {
141783
+ const source = new SourceText(text);
141784
+ const start = source.offsetAt(range2.start);
141785
+ const authored = lex(
141786
+ text.slice(start, source.offsetAt(range2.end))
141787
+ ).tokens.filter(
141788
+ (token) => token.kind !== "comment" && token.kind !== "eof"
141789
+ );
141790
+ if (authored[0]?.text === "{" && authored.at(-1)?.text === "}") {
141791
+ range2 = {
141792
+ start: source.positionAt(start + authored[0].end),
141793
+ end: source.positionAt(start + authored.at(-1).start)
141794
+ };
141795
+ }
141796
+ const map = createNeoScriptSourceMap(
141797
+ error.code,
141798
+ source,
141799
+ range2,
141800
+ {
141801
+ name: body.name,
141802
+ uri: location3.uri,
141803
+ coordinateSpace: "file"
141804
+ },
141805
+ body.thisAlias
141806
+ );
141807
+ const position = map && sourcePositionMapper(map)({
141808
+ line: error.compileError.line,
141809
+ column: error.compileError.column
141810
+ });
141811
+ if (position) ({ line, column } = position);
141812
+ }
141813
+ const message = error.compileError.message.replace(/^\d+:\d+: /u, "");
141814
+ return new SchemaSourceError(
141815
+ `${body.name}: ${message}`,
141816
+ location3.uri,
141817
+ line,
141818
+ column,
141819
+ "neoflow-compile",
141820
+ "error",
141821
+ range2
141822
+ );
141823
+ }
141824
+ var init_dialogue_source_diagnostic = __esm({
141825
+ "src/project-source/dialogue-source-diagnostic.ts"() {
141826
+ "use strict";
141827
+ init_lexer();
141828
+ init_source_text();
141829
+ init_compiler();
141830
+ init_general_function_call_ir_source_recompile();
141831
+ init_source_diagnostics();
141832
+ }
141833
+ });
141834
+
140946
141835
  // ../packages/neoscript-language/src/local-scope-index.ts
140947
141836
  var LocalScopeIndex;
140948
141837
  var init_local_scope_index = __esm({
@@ -146226,6 +147115,7 @@ function projectSemanticTokens(document, analysis) {
146226
147115
  const index = buildProjectSymbolIndex(analysis.symbols);
146227
147116
  const tokens = projectTokens(document);
146228
147117
  const bodyContexts = projectBodies(analysis, document.uri);
147118
+ const source = analysis.documents.get(document.uri);
146229
147119
  const result = tokens.flatMap((token, tokenIndex) => {
146230
147120
  if (token.kind === "eof" || token.kind === "error") return [];
146231
147121
  if (rangeItemAt(bodyContexts, token.range.start)) {
@@ -146236,6 +147126,14 @@ function projectSemanticTokens(document, analysis) {
146236
147126
  let type;
146237
147127
  if (declaration) {
146238
147128
  type = projectSemanticTokenType(declaration);
147129
+ } else if (NEOFLOW_GRAPH_TYPES.has(token.text) && (source && sourceTypeAt(source, token.range.start) || tokens[tokenIndex + 1] && symbolsDeclaredAt(
147130
+ index,
147131
+ document.uri,
147132
+ tokens[tokenIndex + 1].range
147133
+ ).some(
147134
+ (symbol) => symbol.kind === "graphChild" && symbol.detail === token.text
147135
+ ))) {
147136
+ type = "type";
146239
147137
  } else if (resolved) {
146240
147138
  type = projectSemanticTokenType(resolved);
146241
147139
  } else if (token.kind === "keyword") type = "keyword";
@@ -146320,6 +147218,7 @@ function indexedProjectSymbolAt(analysis, document, position, index) {
146320
147218
  (symbol) => symbol.kind === "class" || symbol.kind === "interface" || symbol.kind === "enum" || symbol.kind === "genericParameter"
146321
147219
  );
146322
147220
  if (types.length === 1) return { token, symbol: types[0] };
147221
+ if (typePosition) return null;
146323
147222
  }
146324
147223
  const scoped = candidates.filter(
146325
147224
  (symbol) => symbol.scopeRange && symbol.location.uri === document.uri && rangeContains(symbol.scopeRange, token.range.start)
@@ -147149,6 +148048,7 @@ var init_project_source_language_features = __esm({
147149
148048
  init_analyzer();
147150
148049
  init_lexer();
147151
148050
  init_language_spec();
148051
+ init_neoflow_graph_parser();
147152
148052
  init_project_source_semantics();
147153
148053
  init_project_source_variants();
147154
148054
  init_project_source_lifecycle_editor();
@@ -168463,7 +169363,7 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
168463
169363
  binaryChanges: status.binaryChanges ?? []
168464
169364
  });
168465
169365
  const hasSourceBodies = (status.sourceSnapshot?.analysis.compiledBodies.length ?? 0) > 0;
168466
- if (status.changes.length === 0 && status.authoredValueSeeds.size === 0 && !hasSourceBodies) {
169366
+ if (status.changes.length === 0 && status.authoredValueSeeds.size === 0 && (!hasSourceBodies || purpose === "export" /* Export */)) {
168467
169367
  return status;
168468
169368
  }
168469
169369
  const initConversions = status.initConversions ?? [];
@@ -169067,6 +169967,15 @@ function candidateTimestamp(purpose) {
169067
169967
  return purpose === "export" /* Export */ ? 1 : Date.now();
169068
169968
  }
169069
169969
  function locateStoredClosureCaptureError(error, status, assigned) {
169970
+ const located = locateDialogueSourceError(
169971
+ error,
169972
+ status.dialogueBodySources,
169973
+ new Map(
169974
+ status.sourceSnapshot?.inputs.map((input) => [input.uri, input.text])
169975
+ ),
169976
+ assigned
169977
+ );
169978
+ if (located !== error) return located;
169070
169979
  if (!(error instanceof StoredClosureCaptureError)) return error;
169071
169980
  let valueId = error.valueId;
169072
169981
  for (const [pendingId2, assignedId] of assigned) {
@@ -170701,7 +171610,10 @@ function prepareCompleteNeoScriptBodyChanges(workspace, status, schema, options
170701
171610
  const movedMemberIds = new Set(
170702
171611
  schema.members.filter((member) => {
170703
171612
  const source = context.scriptSources.get(`member:${member.id}`);
170704
- return source && !canonicallyEqual(neoScriptRecordSources(member), source);
171613
+ return source && neoScriptSourceLocationsChanged(
171614
+ neoScriptRecordSources(member),
171615
+ source
171616
+ );
170705
171617
  }).map((member) => String(member.id))
170706
171618
  );
170707
171619
  const compiledMembers = schema.members.map((member) => {
@@ -171049,6 +171961,7 @@ var compileNSVoidBody2, compileNSFunction2, compileNSGetter2, compileNSSetter2,
171049
171961
  var init_push = __esm({
171050
171962
  "src/commands/push.ts"() {
171051
171963
  "use strict";
171964
+ init_dialogue_source_diagnostic();
171052
171965
  init_lower_constructors();
171053
171966
  init_neoscript_source_catalog();
171054
171967
  init_src2();
@@ -184920,7 +185833,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
184920
185833
  async function main() {
184921
185834
  const args = parseArgs(process.argv.slice(2));
184922
185835
  if (args.command === "--version") {
184923
- console.log("0.71.0");
185836
+ console.log("0.71.2");
184924
185837
  return;
184925
185838
  }
184926
185839
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {