@neocompose/cli 0.71.1 → 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.1",
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;
@@ -90818,6 +91835,7 @@ __export(compiler_adapter_exports, {
90818
91835
  compileNSConstructor: () => compileNSConstructor,
90819
91836
  compileNSFunction: () => compileNSFunction,
90820
91837
  compileNSGetter: () => compileNSGetter,
91838
+ compileNSInferredExpressionGetter: () => compileNSInferredExpressionGetter,
90821
91839
  compileNSInitializer: () => compileNSInitializer,
90822
91840
  compileNSSetter: () => compileNSSetter,
90823
91841
  compileNSVoidBody: () => compileNSVoidBody,
@@ -93967,251 +94985,6 @@ var init_localized_text_create_envelope = __esm({
93967
94985
  }
93968
94986
  });
93969
94987
 
93970
- // ../src/database/neo-script-derived-bodies.ts
93971
- function cloneAndStripClientDerivedBodies(change) {
93972
- if (change.operation === "delete" || change.nextData === void 0) {
93973
- return { ...change };
93974
- }
93975
- return {
93976
- ...change,
93977
- nextData: stripClientDerivedBodies(change.recordKind, change.nextData)
93978
- };
93979
- }
93980
- function stripClientDerivedBodies(recordKind, nextData) {
93981
- const record7 = asRecord2(nextData);
93982
- return record7 === null ? nextData : strippedClone(recordKind, record7);
93983
- }
93984
- function hasPendingNeoScriptDerivation(recordKind, data) {
93985
- const record7 = asRecord2(data);
93986
- if (record7 === null) return false;
93987
- return collectDerivedBodySites(recordKind, record7).some(
93988
- (site) => site.authored && !(site.key in site.container)
93989
- );
93990
- }
93991
- function strippedClone(recordKind, record7) {
93992
- const next = structuredClone(record7);
93993
- const container = asRecord2(next);
93994
- if (container === null) return next;
93995
- for (const site of collectDerivedBodySites(recordKind, container)) {
93996
- delete site.container[site.key];
93997
- }
93998
- return next;
93999
- }
94000
- function collectDerivedBodySites(recordKind, record7) {
94001
- const sites = [];
94002
- if (recordKind === "migration") {
94003
- sites.push({
94004
- container: record7,
94005
- key: "action",
94006
- authored: typeof record7.code === "string"
94007
- });
94008
- return sites;
94009
- }
94010
- if (recordKind === "dialogue-group") {
94011
- collectConditionSites(record7.conditions, sites);
94012
- return sites;
94013
- }
94014
- if (recordKind === "dialogue-node") {
94015
- collectDialogueNodeSites(record7, sites);
94016
- return sites;
94017
- }
94018
- if (recordKind === "constructor") {
94019
- sites.push({ container: record7, key: "action", authored: true });
94020
- sites.push({
94021
- container: record7,
94022
- key: "compiledBaseArguments",
94023
- authored: false
94024
- });
94025
- sites.push({
94026
- container: record7,
94027
- key: "compiledBaseInitializerFields",
94028
- authored: false
94029
- });
94030
- return sites;
94031
- }
94032
- if (recordKind === "value") {
94033
- collectValueBodySites(record7, sites);
94034
- return sites;
94035
- }
94036
- if (recordKind !== "member") return sites;
94037
- if (record7.kind === 10 /* NSProperty */) {
94038
- sites.push({
94039
- container: record7,
94040
- key: "getter",
94041
- authored: typeof record7.code === "string"
94042
- });
94043
- sites.push({
94044
- container: record7,
94045
- key: "setter",
94046
- authored: typeof record7.setterCode === "string"
94047
- });
94048
- }
94049
- if (record7.kind === 23 /* NSFunction */) {
94050
- sites.push({
94051
- container: record7,
94052
- key: "action",
94053
- authored: typeof record7.code === "string"
94054
- });
94055
- }
94056
- if (record7.kind === 25 /* NSDelegate */) {
94057
- collectDelegateClosureSite(asRecord2(record7.defaultValue), sites, false);
94058
- }
94059
- collectInitializerSite(asRecord2(record7.defaultValue), sites);
94060
- return sites;
94061
- }
94062
- function collectValueBodySites(record7, sites) {
94063
- collectInitializerSite(record7, sites);
94064
- collectDelegateClosureSite(record7, sites, true);
94065
- collectInlineDelegateArgumentSites(record7, sites);
94066
- for (const container of [record7.value, record7.constructorArgs]) {
94067
- if (container === null || typeof container !== "object") continue;
94068
- for (const candidate of Object.values(container)) {
94069
- if (!isPackedValueEnvelope(candidate)) continue;
94070
- const child2 = asRecord2(candidate[PACKED_VALUE_ENTRY_KEY]);
94071
- if (child2 !== null) collectValueBodySites(child2, sites);
94072
- }
94073
- }
94074
- }
94075
- function collectDialogueNodeSites(node, sites) {
94076
- collectConditionSites(node.conditions, sites);
94077
- collectTextVariableSites(node.variables, sites);
94078
- if (Array.isArray(node.actions)) {
94079
- for (const actionValue2 of node.actions) {
94080
- const logic = asRecord2(asRecord2(actionValue2)?.logic);
94081
- if (logic === null) continue;
94082
- if (logic.type !== 1 /* Code */) continue;
94083
- if (typeof logic.code !== "string") continue;
94084
- sites.push({ container: logic, key: "action", authored: true });
94085
- }
94086
- }
94087
- if (Array.isArray(node.outcomes)) {
94088
- for (const outcomeValue of node.outcomes) {
94089
- collectConditionSites(asRecord2(outcomeValue)?.conditions, sites);
94090
- }
94091
- }
94092
- const options = asRecord2(node.optionSettings)?.options;
94093
- if (!Array.isArray(options)) return;
94094
- for (const optionValue of options) {
94095
- const option = asRecord2(optionValue);
94096
- if (option === null) continue;
94097
- collectTextVariableSites(option.variables, sites);
94098
- const settings = asRecord2(option.settings);
94099
- if (settings === null) continue;
94100
- collectConditionSites(settings.conditions, sites);
94101
- collectConditionSites(settings.selectableConditions, sites);
94102
- }
94103
- }
94104
- function collectConditionSites(value, sites) {
94105
- if (!Array.isArray(value)) return;
94106
- for (const conditionValue of value) {
94107
- const condition = asRecord2(conditionValue);
94108
- if (condition === null) continue;
94109
- if (condition.type !== 1 /* Code */) continue;
94110
- if (typeof condition.code !== "string") continue;
94111
- sites.push({ container: condition, key: "getter", authored: true });
94112
- }
94113
- }
94114
- function collectTextVariableSites(value, sites) {
94115
- const variables = asRecord2(value);
94116
- if (variables === null) return;
94117
- for (const variableValue of Object.values(variables)) {
94118
- const variable2 = asRecord2(variableValue);
94119
- if (variable2 === null) continue;
94120
- sites.push({ container: variable2, key: "getter", authored: true });
94121
- }
94122
- }
94123
- function collectDelegateClosureSite(container, sites, authored) {
94124
- const delegate = asRecord2(container?.value);
94125
- if (delegate === null) return;
94126
- if (typeof delegate.code !== "string") return;
94127
- sites.push({ container: delegate, key: "action", authored });
94128
- }
94129
- function collectInlineDelegateArgumentSites(record7, sites) {
94130
- const constructorArgs = asRecord2(record7.constructorArgs);
94131
- if (constructorArgs === null) return;
94132
- for (const argument2 of Object.values(constructorArgs)) {
94133
- const closure = asRecord2(argument2);
94134
- if (closure === null) continue;
94135
- if (typeof closure.code !== "string") continue;
94136
- sites.push({ container: closure, key: "action", authored: true });
94137
- }
94138
- }
94139
- function collectInitializerSite(container, sites) {
94140
- const init = asRecord2(container?.init);
94141
- if (init === null) return;
94142
- sites.push({ container: init, key: "compiled", authored: true });
94143
- }
94144
- function stripDerivedBodies(member) {
94145
- return strippedClone("member", member);
94146
- }
94147
- function stripConstructorDerivedBodies(constructorRecord) {
94148
- return strippedClone("constructor", constructorRecord);
94149
- }
94150
- function stripMigrationAction(migration) {
94151
- return strippedClone("migration", migration);
94152
- }
94153
- function stampUILogicBody(logic, bodyKey) {
94154
- if (logic?.type !== 0 /* UI */) return false;
94155
- const body = asRecord2(logic[bodyKey]);
94156
- if (body === null) return false;
94157
- if (body.compilerRevision === NEOSCRIPT_COMPILER_REVISION) return false;
94158
- body.compilerRevision = NEOSCRIPT_COMPILER_REVISION;
94159
- return true;
94160
- }
94161
- function stampUILogicBodies(recordKind, data) {
94162
- const record7 = asRecord2(data);
94163
- if (record7 === null) return false;
94164
- if (recordKind === "dialogue-group") {
94165
- return stampConditionList(record7.conditions);
94166
- }
94167
- if (recordKind !== "dialogue-node") return false;
94168
- let changed = stampConditionList(record7.conditions);
94169
- if (Array.isArray(record7.actions)) {
94170
- for (const actionValue2 of record7.actions) {
94171
- const logic = asRecord2(asRecord2(actionValue2)?.logic);
94172
- changed = stampUILogicBody(logic, "action") || changed;
94173
- }
94174
- }
94175
- if (Array.isArray(record7.outcomes)) {
94176
- for (const outcomeValue of record7.outcomes) {
94177
- changed = stampConditionList(asRecord2(outcomeValue)?.conditions) || changed;
94178
- }
94179
- }
94180
- const options = asRecord2(record7.optionSettings)?.options;
94181
- if (Array.isArray(options)) {
94182
- for (const optionValue of options) {
94183
- const settings = asRecord2(asRecord2(optionValue)?.settings);
94184
- if (settings === null) continue;
94185
- changed = stampConditionList(settings.conditions) || changed;
94186
- changed = stampConditionList(settings.selectableConditions) || changed;
94187
- }
94188
- }
94189
- return changed;
94190
- }
94191
- function stampConditionList(value) {
94192
- if (!Array.isArray(value)) return false;
94193
- let changed = false;
94194
- for (const conditionValue of value) {
94195
- changed = stampUILogicBody(asRecord2(conditionValue), "getter") || changed;
94196
- }
94197
- return changed;
94198
- }
94199
- function asRecord2(value) {
94200
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
94201
- return null;
94202
- }
94203
- return value;
94204
- }
94205
- var init_neo_script_derived_bodies = __esm({
94206
- "../src/database/neo-script-derived-bodies.ts"() {
94207
- "use strict";
94208
- init_members();
94209
- init_logic_types();
94210
- init_strict_ir();
94211
- init_packed_value_encoding();
94212
- }
94213
- });
94214
-
94215
94988
  // ../src/database/neo-script-recompile-scope.ts
94216
94989
  function memberNeoScriptContractChanged(current, next) {
94217
94990
  return canonicalJsonStringify(neoScriptMemberContractProjection(current)) !== canonicalJsonStringify(neoScriptMemberContractProjection(next));
@@ -101812,14 +102585,14 @@ function findParentValues(valueId, values) {
101812
102585
  }
101813
102586
  continue;
101814
102587
  }
101815
- if (!isStringRecord6(value.value)) continue;
102588
+ if (!isStringRecord7(value.value)) continue;
101816
102589
  for (const [key, childValueId2] of Object.entries(value.value)) {
101817
102590
  if (childValueId2 === valueId) parents.push({ value, key });
101818
102591
  }
101819
102592
  }
101820
102593
  return parents;
101821
102594
  }
101822
- function isStringRecord6(value) {
102595
+ function isStringRecord7(value) {
101823
102596
  if (typeof value !== "object") return false;
101824
102597
  if (value === null) return false;
101825
102598
  if (Array.isArray(value)) return false;
@@ -101996,9 +102769,16 @@ function compileDialogueLogicWithProjectData(request, projectData) {
101996
102769
  node: request.node,
101997
102770
  returnTypeInfo: sourceBacked ? request.textVariable.typeInfo : { type: 3 /* String */, required: true }
101998
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);
101999
102778
  return {
102000
102779
  target: 2 /* TextVariable */,
102001
- getter: sourceBacked ? stringifyCompiledTextGetter(compileNSGetter(request.code, ctx2)) : compileTextVariableGetter(ctx2, request.textVariable)
102780
+ getter: stringifyCompiledTextGetter(getter),
102781
+ sourceTypeInfo: getter.typeInfo
102002
102782
  };
102003
102783
  }
102004
102784
  if (request.dialogueGroup) {
@@ -102771,7 +103551,8 @@ function recompileDialogueNode(args) {
102771
103551
  (message) => ({
102772
103552
  target: 1 /* Action */,
102773
103553
  action: makeThrowBody(message, VOID_ACTION_TYPE_INFO)
102774
- })
103554
+ }),
103555
+ typeof logic.sourceFunctionId === "string" ? { id: logic.sourceFunctionId, code: logic.code } : void 0
102775
103556
  );
102776
103557
  if (!compiled.ok) continue;
102777
103558
  const response = compiled.value;
@@ -102861,7 +103642,8 @@ function recompileConditionList(value, context) {
102861
103642
  (message) => ({
102862
103643
  target: 0 /* Condition */,
102863
103644
  getter: makeThrowBody(message, BOOL_TYPE_INFO)
102864
- })
103645
+ }),
103646
+ typeof condition.sourceFunctionId === "string" ? { id: condition.sourceFunctionId, code: condition.code } : void 0
102865
103647
  );
102866
103648
  if (!compiled.ok) continue;
102867
103649
  const response = compiled.value;
@@ -102890,6 +103672,7 @@ function recompileTextVariables(value, context) {
102890
103672
  dialogue: context.dialogue,
102891
103673
  node: context.node,
102892
103674
  textVariable: {
103675
+ sourceInline: variable2.sourceInline === true,
102893
103676
  nodeId: context.nodeId,
102894
103677
  optionId: context.optionId,
102895
103678
  pointer: variable2.pointer,
@@ -102907,7 +103690,14 @@ function recompileTextVariables(value, context) {
102907
103690
  (message) => ({
102908
103691
  target: 2 /* TextVariable */,
102909
103692
  getter: makeThrowBody(message, STRING_TYPE_INFO)
102910
- })
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
+ }
102911
103701
  );
102912
103702
  if (!compiled.ok) continue;
102913
103703
  const response = compiled.value;
@@ -102915,6 +103705,7 @@ function recompileTextVariables(value, context) {
102915
103705
  throw new Error("Dialogue text-variable compilation returned code IR.");
102916
103706
  }
102917
103707
  variable2.getter = response.getter;
103708
+ if (response.sourceTypeInfo) variable2.typeInfo = response.sourceTypeInfo;
102918
103709
  changed = true;
102919
103710
  }
102920
103711
  return changed;
@@ -102933,7 +103724,7 @@ function buildDialogueContext(dialogue, nodes) {
102933
103724
  }
102934
103725
  };
102935
103726
  }
102936
- function compileSourceUnit(label, compile, onSourceRejection, compileErrorFallback) {
103727
+ function compileSourceUnit(label, compile, onSourceRejection, compileErrorFallback, body) {
102937
103728
  try {
102938
103729
  return { ok: true, value: compile() };
102939
103730
  } catch (error) {
@@ -102945,6 +103736,8 @@ function compileSourceUnit(label, compile, onSourceRejection, compileErrorFallba
102945
103736
  }
102946
103737
  return { ok: false };
102947
103738
  }
103739
+ if (error instanceof CompileError && body)
103740
+ throw new SourceBodyCompileError(label, body.id, body.code, error);
102948
103741
  throw new Error(`Cannot recompile ${label}: ${message}`, { cause: error });
102949
103742
  }
102950
103743
  }
@@ -102986,7 +103779,7 @@ function asObject(value) {
102986
103779
  function cloneObject(value) {
102987
103780
  return structuredClone(value);
102988
103781
  }
102989
- var VOID_ACTION_TYPE_INFO, BOOL_TYPE_INFO, STRING_TYPE_INFO;
103782
+ var SourceBodyCompileError, VOID_ACTION_TYPE_INFO, BOOL_TYPE_INFO, STRING_TYPE_INFO;
102990
103783
  var init_general_function_call_ir_source_recompile = __esm({
102991
103784
  "../src/database/general-function-call-ir-source-recompile.ts"() {
102992
103785
  "use strict";
@@ -103006,6 +103799,22 @@ var init_general_function_call_ir_source_recompile = __esm({
103006
103799
  init_dialogue_node_index();
103007
103800
  init_strict_ir();
103008
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
+ };
103009
103818
  VOID_ACTION_TYPE_INFO = {
103010
103819
  type: 0 /* Null */,
103011
103820
  required: true
@@ -104642,9 +105451,9 @@ function assertNumberRange(member, value, path) {
104642
105451
  }
104643
105452
  }
104644
105453
  function stringRecord3(value) {
104645
- return isStringRecord7(value) ? value : null;
105454
+ return isStringRecord8(value) ? value : null;
104646
105455
  }
104647
- function isStringRecord7(value) {
105456
+ function isStringRecord8(value) {
104648
105457
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
104649
105458
  return false;
104650
105459
  }
@@ -117805,7 +118614,7 @@ function toWorldReferenceClassRecord(value) {
117805
118614
  return {
117806
118615
  id: id2,
117807
118616
  extendsClassId: nullableStringField(value, "extendsClassId"),
117808
- schema: isStringRecord8(value.schema) ? value.schema : void 0,
118617
+ schema: isStringRecord9(value.schema) ? value.schema : void 0,
117809
118618
  system: isPlainRecord7(value.system) ? value.system : null
117810
118619
  };
117811
118620
  }
@@ -117823,7 +118632,7 @@ function worldReferenceValueClassId(value) {
117823
118632
  if (value === void 0) return null;
117824
118633
  return typeof value.classId === "string" && value.classId.length > 0 ? value.classId : null;
117825
118634
  }
117826
- function isStringRecord8(value) {
118635
+ function isStringRecord9(value) {
117827
118636
  if (!isPlainRecord7(value)) return false;
117828
118637
  return Object.values(value).every((entry) => typeof entry === "string");
117829
118638
  }
@@ -122839,7 +123648,8 @@ function builtinTextVariableMember(receiver, name) {
122839
123648
  }
122840
123649
  return null;
122841
123650
  }
122842
- function lowerDialogueProjectSourcesV4(state, analysis) {
123651
+ function lowerDialogueProjectSourcesV4(state, analysis, options = {}) {
123652
+ const sourceCapture = options.sourceCapture;
122843
123653
  const result = [];
122844
123654
  const mainLocale = readMainLocale(state);
122845
123655
  const dialogueGroups = analysis.dialogueGroups.globals.filter(
@@ -122855,94 +123665,133 @@ function lowerDialogueProjectSourcesV4(state, analysis) {
122855
123665
  const sourceSchema = new SourceSchemaIndex(analysis);
122856
123666
  const valueSymbols = indexValueSymbols(state, analysis);
122857
123667
  const nodesByDialogueId = dialogueNodesByDialogueId(state);
123668
+ let referenceTypeIndex;
123669
+ const referenceTypes = () => referenceTypeIndex ??= new ReferenceTargetTypes(
123670
+ state,
123671
+ options.authoredValueSeeds,
123672
+ [],
123673
+ options.manifest
123674
+ );
122858
123675
  for (const dialogue of analysis.dialogues.dialogues) {
122859
- const dialogueId = sourceId2(dialogue, "dialogue", dialogue.name);
122860
- const baseDialogue = baseData2(state, "dialogue", dialogueId);
122861
- const nodesById = nodesByDialogueId.get(dialogueId) ?? /* @__PURE__ */ new Map();
122862
- const memberIdsByName = new Map(
122863
- dialogue.members.map((member) => [
122864
- member.name,
122865
- sourceId2(member, "dialogue-node", member.name)
122866
- ])
122867
- );
122868
- const functionsByName = new Map(
122869
- dialogue.functions.map((fn) => [fn.name, fn])
122870
- );
122871
- const context = {
122872
- state,
122873
- dialogue,
122874
- dialogueId,
122875
- baseDialogue,
122876
- nodesById,
122877
- memberIdsByName,
122878
- functionsByName,
122879
- existingLogic: indexExistingLogic(nodesById.values()),
122880
- mainLocale,
122881
- dialogueGroupIds,
122882
- lookupDialogueGroupIds,
122883
- priorityGroupsById,
122884
- valueSymbols,
122885
- sourceSchema,
122886
- dialogueBindingTypes: new Map(
122887
- dialogue.bindings.map((binding) => [binding.name, binding.type])
122888
- ),
122889
- dialogueLinks: Array.isArray(baseDialogue.linkedValues) ? baseDialogue.linkedValues.filter(isObjectRecord2) : [],
122890
- dialoguePrimaryValueId: nullableString4(baseDialogue.primaryLinkedValueId),
122891
- sourcePrimaryAlias: primaryBindingName(dialogue.bindings)
122892
- };
122893
- const trigger = dialogue.members.find(
122894
- (member) => member.graphType === "Trigger"
122895
- );
122896
- if (!trigger)
122897
- throw new Error(`Dialogue ${dialogue.name} requires Trigger.`);
122898
- const settings = annotationArguments(dialogue.annotations, "settings");
122899
- const linked = lowerBindings(
122900
- context,
122901
- dialogue.bindings,
122902
- baseDialogue.linkedValues
122903
- );
122904
- const primary = primaryValueId(dialogue.bindings, linked);
122905
- const graphContext = {
122906
- ...context,
122907
- dialogueLinks: linked,
122908
- dialoguePrimaryValueId: primary
122909
- };
122910
- const description = lowerDialogueDescription(
122911
- context,
122912
- settings.get("description"),
122913
- result
122914
- );
122915
- result.push(
122916
- reconstructed2(
122917
- "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,
122918
123694
  dialogueId,
122919
- {
122920
- ...baseDialogue,
122921
- id: dialogueId,
122922
- sourceName: dialogue.name,
122923
- name: literalString(settings.get("name")) ?? stringOr(baseDialogue.name, dialogue.name),
122924
- description,
122925
- settings: {
122926
- ...isObjectRecord2(baseDialogue.settings) ? baseDialogue.settings : {},
122927
- defaultSaveOptionChoices: literalBoolean(settings.get("saveOptionChoices")) ?? booleanOr(
122928
- isObjectRecord2(baseDialogue.settings) ? baseDialogue.settings.defaultSaveOptionChoices : void 0,
122929
- true
122930
- )
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)
122931
123757
  },
122932
- linkedValues: linked,
122933
- primaryLinkedValueId: primary,
122934
- triggerNodeId: sourceId2(trigger, "dialogue-node", trigger.name)
122935
- },
122936
- dialogue
122937
- )
122938
- );
122939
- dialogue.members.forEach((member, index) => {
122940
- const lowered = lowerGraphMember(graphContext, member, index);
122941
- result.push(...lowered);
122942
- });
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
+ }
122943
123780
  }
122944
123781
  return result;
122945
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
+ }
122946
123795
  function lowerGraphMember(context, member, index) {
122947
123796
  const id2 = sourceId2(member, "dialogue-node", member.name);
122948
123797
  const base = context.nodesById.get(id2) ?? {};
@@ -123061,7 +123910,8 @@ function lowerTextNode(context, member, id2, base, common, destination) {
123061
123910
  nullableString4(common.primaryLinkedValueId) ?? context.dialoguePrimaryValueId,
123062
123911
  `node:${id2}`,
123063
123912
  dialogueNodeLocalizedTextLink(id2),
123064
- member
123913
+ member,
123914
+ member.content?.proseSources?.[0]
123065
123915
  );
123066
123916
  const children = member.content?.children.filter((child2) => child2.graphType === "Option") ?? [];
123067
123917
  const baseOptionSettings = isObjectRecord2(base.optionSettings) ? base.optionSettings : {};
@@ -123087,7 +123937,8 @@ function lowerTextNode(context, member, id2, base, common, destination) {
123087
123937
  nullableString4(common.primaryLinkedValueId) ?? context.dialoguePrimaryValueId,
123088
123938
  `option:${optionId}`,
123089
123939
  dialogueChoiceLocalizedTextLink(id2, optionId),
123090
- child2
123940
+ child2,
123941
+ child2.content?.proseSources?.[0]
123091
123942
  );
123092
123943
  if (optionText.textRecord) textRecords.push(optionText.textRecord);
123093
123944
  const priorSettings = isObjectRecord2(optionBase.settings) ? optionBase.settings : {};
@@ -123285,6 +124136,14 @@ function lowerConditionUses(context, expression, owner) {
123285
124136
  `${owner} condition ${use.name} must resolve to a zero-argument bool function.`
123286
124137
  );
123287
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
+ );
123288
124147
  const prior = context.existingLogic.conditionsByUseId.get(id2);
123289
124148
  const body = functionCode(fn);
123290
124149
  if (body === null) {
@@ -123359,6 +124218,14 @@ function conditionProjectionMatches(context, prior, body) {
123359
124218
  return false;
123360
124219
  }
123361
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
+ );
123362
124229
  const code = functionCode(fn) ?? fallbackCode;
123363
124230
  if (prior?.type === 0) {
123364
124231
  const projected = uiActionSource(prior.action, uiResolver);
@@ -123385,7 +124252,7 @@ function lowerActionLogic(context, prior, fn, fallbackCode, inline, useId, uiRes
123385
124252
  action: isObjectRecord2(prior?.action) ? prior.action : placeholderVoidAction()
123386
124253
  };
123387
124254
  }
123388
- 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) {
123389
124256
  const textId = baseTextId ?? pendingId("localized-text", source.source.uri, owner, 0, "text");
123390
124257
  const baseText = baseData2(context.state, "localized-text", textId);
123391
124258
  const variablesByPath = /* @__PURE__ */ new Map();
@@ -123417,8 +124284,13 @@ function lowerProse(context, rawProse, baseTextId, baseVariables, baseLinks, bin
123417
124284
  const main2 = isObjectRecord2(mainCandidate) ? mainCandidate : {};
123418
124285
  const pulledMainText = typeof main2.value === "string" ? main2.value : "";
123419
124286
  let ordinal = 0;
124287
+ let expressionOrdinal = 0;
124288
+ const rawExpressions = context.sourceCapture ? decodeProseSegments(rawProse, false).filter(
124289
+ (segment) => segment.kind === "expression"
124290
+ ) : [];
123420
124291
  const value = decodeProseSegments(rawProse).map((segment) => {
123421
124292
  if (segment.kind === "literal") return segment.value;
124293
+ const rawExpression = rawExpressions[expressionOrdinal++];
123422
124294
  const expression = segment.value;
123423
124295
  const sourcePath = expression.trim();
123424
124296
  const missingVariableId = missingTextVariableId(sourcePath);
@@ -123451,6 +124323,30 @@ function lowerProse(context, rawProse, baseTextId, baseVariables, baseLinks, bin
123451
124323
  const functionName = callExpressionName(sourcePath) ?? `TextValue${ordinal + 1}`;
123452
124324
  const fn = callExpressionName(sourcePath) ? context.functionsByName.get(functionName) : void 0;
123453
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
+ }
123454
124350
  if (prior !== void 0 && (fn === void 0 || functionBody === null)) {
123455
124351
  const declaredFunction = fn ?? sourceFunctionForPrior(context, prior);
123456
124352
  variables[variableId] = declaredFunction ? {
@@ -123490,7 +124386,7 @@ function lowerProse(context, rawProse, baseTextId, baseVariables, baseLinks, bin
123490
124386
  bindingTypes,
123491
124387
  primaryValueId2
123492
124388
  );
123493
- 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 });
123494
124390
  variables[variableId] = {
123495
124391
  ...prior ?? {},
123496
124392
  id: variableId,
@@ -123746,12 +124642,33 @@ function lowerBindings(context, bindings, baseLinks) {
123746
124642
  const explicit = bindings.map((binding) => {
123747
124643
  if (binding.initializer === null)
123748
124644
  throw new Error(`Binding ${binding.name} requires an initializer.`);
123749
- const valueId = resolveBindingValueId(
123750
- context,
123751
- binding.initializer,
123752
- existing,
123753
- binding.name
123754
- );
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
+ }
123755
124672
  const previous = existing.find(
123756
124673
  (link) => link.valueId === valueId || link.sourceName === binding.name
123757
124674
  );
@@ -123793,7 +124710,8 @@ function lowerNodeBindings(context, content, baseLinks) {
123793
124710
  (binding) => ({
123794
124711
  id: null,
123795
124712
  state: "pending",
123796
- source: context.dialogue.source,
124713
+ source: binding.source ?? context.dialogue.source,
124714
+ initializerSource: binding.source,
123797
124715
  kind: "field",
123798
124716
  name: binding.name,
123799
124717
  type: parseManifestTypeText(binding.type),
@@ -123870,31 +124788,33 @@ function parseManifestTypeText(source) {
123870
124788
  }
123871
124789
  return result;
123872
124790
  }
123873
- function resolveBindingValueId(context, initializer, existing, sourceName) {
123874
- const idMatch = initializer.match(
123875
- /\bReference(?:<[^>]+>)?\s*\(\s*(?:id\s*:\s*)?("(?:[^"\\]|\\.)*")\s*\)/
123876
- );
123877
- 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
+ }
123878
124803
  const direct = directValueSymbol(initializer);
123879
124804
  if (direct !== null) {
123880
124805
  const symbol = context.valueSymbols.get(direct);
123881
124806
  if (symbol !== void 0) return symbol.valueId;
123882
124807
  }
123883
- const byName = existing.find((link) => link.sourceName === sourceName);
123884
- if (typeof byName?.valueId === "string") return byName.valueId;
123885
- if (existing.length === 1 && typeof existing[0]?.valueId === "string") {
123886
- return existing[0].valueId;
123887
- }
123888
124808
  throw new Error(
123889
124809
  `Binding ${sourceName} initializer ${JSON.stringify(initializer)} cannot be resolved to a stable value. Use Reference<T>(id: "...").`
123890
124810
  );
123891
124811
  }
123892
124812
  function directValueSymbol(initializer) {
123893
124813
  const trimmed = initializer.trim();
123894
- 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)) {
123895
124815
  return trimmed;
123896
124816
  }
123897
- 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(
123898
124818
  trimmed
123899
124819
  );
123900
124820
  return reference2?.[1] ?? null;
@@ -124041,13 +124961,18 @@ function proseExpressions(raw) {
124041
124961
  );
124042
124962
  }
124043
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;
124044
124966
  const expression = constructorExpression(member.arguments, "group");
124045
124967
  if (expression === null) return null;
124046
124968
  const old = isObjectRecord2(base.dialogueGroupSettings) ? base.dialogueGroupSettings : {};
124047
124969
  const referencedGroupId = referenceId2(expression, "DialogueGroup");
124048
124970
  if (referencedGroupId !== null) {
124049
124971
  if (![...context.dialogueGroupIds.values()].includes(referencedGroupId)) {
124050
- throw new Error(`Unknown dialogue group ${referencedGroupId}.`);
124972
+ throw dialogueSourceError(
124973
+ `Unknown dialogue group ${referencedGroupId}.`,
124974
+ groupSource
124975
+ );
124051
124976
  }
124052
124977
  const group2 = baseData2(context.state, "dialogue-group", referencedGroupId);
124053
124978
  const priorityGroupId2 = nullableString4(group2.priorityGroupIdOverride) ?? defaultPriorityGroupId(context.state);
@@ -124059,14 +124984,18 @@ function lowerDialogueGroupSettings(context, member, base) {
124059
124984
  );
124060
124985
  const priorityOptionId = priorityExpression === null ? null : referenceId2(priorityExpression, "PriorityOption");
124061
124986
  if (priorityExpression !== null && priorityOptionId === null) {
124062
- throw new Error(
124063
- 'Trigger priority must be authored as Reference<PriorityOption>(id: "...").'
124987
+ throw dialogueSourceError(
124988
+ 'Trigger priority must be authored as Reference<PriorityOption>(id: "...").',
124989
+ prioritySource
124064
124990
  );
124065
124991
  }
124066
124992
  if (priorityOptionId !== null && !options2.some(
124067
124993
  (candidate) => isObjectRecord2(candidate) && candidate.id === priorityOptionId
124068
124994
  )) {
124069
- throw new Error(`Unknown priority option ${priorityOptionId}.`);
124995
+ throw dialogueSourceError(
124996
+ `Unknown priority option ${priorityOptionId}.`,
124997
+ prioritySource
124998
+ );
124070
124999
  }
124071
125000
  return {
124072
125001
  ...old,
@@ -124081,12 +125010,17 @@ function lowerDialogueGroupSettings(context, member, base) {
124081
125010
  }
124082
125011
  const [groupName, optionName] = expression.split(".");
124083
125012
  if (!groupName || !optionName) {
124084
- throw new Error(
124085
- `Trigger group must be authored as DialogueGroup.PriorityOption.`
125013
+ throw dialogueSourceError(
125014
+ `Trigger group must be authored as DialogueGroup.PriorityOption.`,
125015
+ groupSource
124086
125016
  );
124087
125017
  }
124088
125018
  const groupId = context.dialogueGroupIds.get(groupName);
124089
- if (!groupId) throw new Error(`Unknown dialogue group ${groupName}.`);
125019
+ if (!groupId)
125020
+ throw dialogueSourceError(
125021
+ `Unknown dialogue group ${groupName}.`,
125022
+ groupSource
125023
+ );
124090
125024
  const group = baseData2(context.state, "dialogue-group", groupId);
124091
125025
  const priorityGroupId = nullableString4(group.priorityGroupIdOverride) ?? defaultPriorityGroupId(context.state);
124092
125026
  const priority = priorityGroupId ? context.priorityGroupsById.get(priorityGroupId) : void 0;
@@ -124095,7 +125029,10 @@ function lowerDialogueGroupSettings(context, member, base) {
124095
125029
  (candidate) => isObjectRecord2(candidate) && candidate.name === optionName
124096
125030
  );
124097
125031
  if (!isObjectRecord2(option) || typeof option.id !== "string") {
124098
- throw new Error(`Unknown priority option ${expression}.`);
125032
+ throw dialogueSourceError(
125033
+ `Unknown priority option ${expression}.`,
125034
+ groupSource
125035
+ );
124099
125036
  }
124100
125037
  return {
124101
125038
  ...old,
@@ -124109,8 +125046,29 @@ function lowerDialogueGroupSettings(context, member, base) {
124109
125046
  };
124110
125047
  }
124111
125048
  function lookupValueSettings(context, groupId, old) {
124112
- if (context.lookupDialogueGroupIds.has(groupId))
124113
- 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
+ }
124114
125072
  return old.lookupValueId == null ? {} : { lookupValueId: null };
124115
125073
  }
124116
125074
  function referenceId2(expression, typeName) {
@@ -124190,8 +125148,8 @@ function decodeProse(raw) {
124190
125148
  if (indent2.length === 0) return value;
124191
125149
  return value.split("\n").map((line) => line.startsWith(indent2) ? line.slice(indent2.length) : line).join("\n");
124192
125150
  }
124193
- function decodeProseSegments(raw) {
124194
- const value = decodeProse(raw);
125151
+ function decodeProseSegments(raw, decode2 = true) {
125152
+ const value = decode2 ? decodeProse(raw) : raw.slice(3, -3);
124195
125153
  const result = [];
124196
125154
  let literal3 = "";
124197
125155
  const flushLiteral = () => {
@@ -124231,7 +125189,12 @@ function decodeProseSegments(raw) {
124231
125189
  if (expression.length === 0) {
124232
125190
  throw new Error("NeoFlow prose interpolation cannot be empty.");
124233
125191
  }
124234
- result.push({ kind: "expression", value: expression });
125192
+ result.push({
125193
+ kind: "expression",
125194
+ value: expression,
125195
+ start: index + 1,
125196
+ end
125197
+ });
124235
125198
  index = end;
124236
125199
  }
124237
125200
  flushLiteral();
@@ -124524,6 +125487,22 @@ function indexValueSymbols(state, analysis) {
124524
125487
  });
124525
125488
  }
124526
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
+ }
124527
125506
  return result;
124528
125507
  }
124529
125508
  function memberDeclaredTypeName(member, classes) {
@@ -124615,6 +125594,10 @@ var SourceSchemaIndex;
124615
125594
  var init_dialogue_lower = __esm({
124616
125595
  "src/project-source/dialogue-lower.ts"() {
124617
125596
  "use strict";
125597
+ init_local_values();
125598
+ init_key_reference_spelling();
125599
+ init_reference_target_types();
125600
+ init_source_diagnostics();
124618
125601
  init_executable_parser();
124619
125602
  init_strict_ir();
124620
125603
  init_localization_types();
@@ -124910,226 +125893,6 @@ var init_dialogue_lower = __esm({
124910
125893
  }
124911
125894
  });
124912
125895
 
124913
- // src/project-source/stored-value-placements.ts
124914
- function storedValueRowsByIdV4(records2) {
124915
- const stored = /* @__PURE__ */ new Map();
124916
- let packed = false;
124917
- for (const record7 of records2) {
124918
- if (record7.deleted === true) continue;
124919
- if (record7.recordKind !== "value") continue;
124920
- if (!isObjectRecord2(record7.data)) continue;
124921
- stored.set(record7.recordId, record7.data);
124922
- packed ||= rowCarriesPackedValueContent(record7.data);
124923
- }
124924
- if (!packed) return stored;
124925
- const logical = /* @__PURE__ */ new Map();
124926
- for (const [valueId, row] of stored) {
124927
- if (!rowCarriesPackedValueContent(row)) {
124928
- logical.set(valueId, row);
124929
- continue;
124930
- }
124931
- const authoredRow = stripClientDerivedBodies("value", row);
124932
- if (!isMemberValue(authoredRow)) {
124933
- throw new PackedValueEncodingError(
124934
- `Stored value row "${valueId}" packs a child but is not a well-formed value row, so its packed payload cannot be expanded.`
124935
- );
124936
- }
124937
- const decoded = decodePackedValueRow(authoredRow);
124938
- logical.set(valueId, { ...decoded.row });
124939
- for (const child2 of decoded.children) {
124940
- logical.set(child2.id, { ...child2 });
124941
- }
124942
- }
124943
- return logical;
124944
- }
124945
- function buildStoredValuePlacementIndexV4(records2) {
124946
- const live = [...records2].filter((record7) => record7.deleted !== true);
124947
- const values = storedValueRowsByIdV4(live);
124948
- const classes = [];
124949
- const members = [];
124950
- const memberDataById = /* @__PURE__ */ new Map();
124951
- const constructors = /* @__PURE__ */ new Map();
124952
- const variantTargetClassByRootValueId = /* @__PURE__ */ new Map();
124953
- for (const record7 of live) {
124954
- if (!isObjectRecord2(record7.data)) continue;
124955
- if (record7.recordKind === "value") continue;
124956
- if (record7.recordKind === "class") {
124957
- classes.push({
124958
- id: record7.recordId,
124959
- ...isStringRecord9(record7.data.schema) ? { schema: record7.data.schema } : {},
124960
- ...typeof record7.data.extendsClassId === "string" || record7.data.extendsClassId === null ? { extendsClassId: record7.data.extendsClassId } : {},
124961
- ...typeof record7.data.requiredConstructorId === "string" ? { requiredConstructorId: record7.data.requiredConstructorId } : {},
124962
- ...Array.isArray(record7.data.genericParams) ? {
124963
- genericParamIds: record7.data.genericParams.flatMap(
124964
- (entry) => isObjectRecord2(entry) && typeof entry.id === "string" ? [entry.id] : []
124965
- )
124966
- } : {}
124967
- });
124968
- } else if (record7.recordKind === "member") {
124969
- memberDataById.set(record7.recordId, record7.data);
124970
- members.push({
124971
- id: record7.recordId,
124972
- ...record7.data.defaultValue === void 0 ? {} : { defaultValue: record7.data.defaultValue }
124973
- });
124974
- } else if (record7.recordKind === "constructor") {
124975
- constructors.set(record7.recordId, record7.data);
124976
- } else if (record7.recordKind === "variant" && typeof record7.data.valueId === "string" && typeof record7.data.classId === "string") {
124977
- variantTargetClassByRootValueId.set(
124978
- record7.data.valueId,
124979
- record7.data.classId
124980
- );
124981
- }
124982
- }
124983
- const classesById = new Map(
124984
- classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
124985
- );
124986
- const resolveSettlement = createConstructorSettlementResolver({
124987
- classes,
124988
- constructors: [...constructors].flatMap(
124989
- ([id2, constructor2]) => typeof constructor2.classId === "string" ? [
124990
- {
124991
- id: id2,
124992
- classId: constructor2.classId,
124993
- ...Array.isArray(constructor2.baseArguments) ? { baseArguments: constructor2.baseArguments } : {},
124994
- ...Array.isArray(constructor2.baseInitializerFields) ? {
124995
- baseInitializerFields: constructor2.baseInitializerFields
124996
- } : {}
124997
- }
124998
- ] : []
124999
- ),
125000
- members
125001
- });
125002
- const memberIdForSchemaKey = (classId, schemaKey) => {
125003
- const visited = /* @__PURE__ */ new Set();
125004
- let cursor = classId;
125005
- while (cursor !== null && !visited.has(cursor)) {
125006
- visited.add(cursor);
125007
- const schemaClass2 = classesById.get(cursor);
125008
- if (schemaClass2 === void 0) return null;
125009
- const memberId = schemaClass2.schema?.[schemaKey];
125010
- if (typeof memberId === "string") return memberId;
125011
- cursor = schemaClass2.extendsClassId ?? null;
125012
- }
125013
- return null;
125014
- };
125015
- const childrenByParentValueId = /* @__PURE__ */ new Map();
125016
- const placementByChildValueId = /* @__PURE__ */ new Map();
125017
- const add = (edge) => {
125018
- const children = childrenByParentValueId.get(edge.parentValueId) ?? /* @__PURE__ */ new Map();
125019
- if (children.has(edge.schemaKey)) return;
125020
- children.set(edge.schemaKey, edge);
125021
- childrenByParentValueId.set(edge.parentValueId, children);
125022
- if (!placementByChildValueId.has(edge.childValueId)) {
125023
- placementByChildValueId.set(edge.childValueId, edge);
125024
- }
125025
- };
125026
- for (const [parentValueId, value] of values) {
125027
- const classId = typeof value.classId === "string" ? value.classId : null;
125028
- const body = value.value;
125029
- if (isObjectRecord2(body)) {
125030
- for (const [schemaKey, childValueId2] of Object.entries(body)) {
125031
- if (typeof childValueId2 !== "string" || !values.has(childValueId2)) {
125032
- continue;
125033
- }
125034
- add({
125035
- childValueId: childValueId2,
125036
- memberId: classId === null ? null : memberIdForSchemaKey(classId, schemaKey),
125037
- parentValueId,
125038
- schemaKey,
125039
- source: "body"
125040
- });
125041
- }
125042
- }
125043
- const constructorId = value.instanceConstructorId;
125044
- const constructorArgs = value.constructorArgs;
125045
- if (classId === null || typeof constructorId !== "string" || !isObjectRecord2(constructorArgs)) {
125046
- continue;
125047
- }
125048
- const constructor2 = constructors.get(constructorId);
125049
- const parameters = constructor2?.argumentTypes;
125050
- if (constructor2 === void 0 || constructor2.classId !== classId || !Array.isArray(parameters)) {
125051
- continue;
125052
- }
125053
- for (const [index, parameter4] of parameters.entries()) {
125054
- if (!isObjectRecord2(parameter4) || typeof parameter4.name !== "string") {
125055
- continue;
125056
- }
125057
- const settled = resolveSettlement(classId, parameter4.name, constructorId);
125058
- if (settled === null) continue;
125059
- if (isObjectRecord2(body) && Object.hasOwn(body, settled.schemaKey)) {
125060
- continue;
125061
- }
125062
- const parameterId = constructorActionParameterId(constructor2, index);
125063
- const childValueId2 = constructorArgs[parameterId];
125064
- if (typeof childValueId2 !== "string" || !values.has(childValueId2) || !memberStoresAggregate(
125065
- memberDataById.get(settled.memberId),
125066
- value,
125067
- memberDataById,
125068
- parentValueId,
125069
- classesById,
125070
- variantTargetClassByRootValueId
125071
- )) {
125072
- continue;
125073
- }
125074
- add({
125075
- childValueId: childValueId2,
125076
- memberId: settled.memberId,
125077
- parentValueId,
125078
- schemaKey: settled.schemaKey,
125079
- source: "constructor"
125080
- });
125081
- }
125082
- }
125083
- return { childrenByParentValueId, placementByChildValueId };
125084
- }
125085
- function memberStoresAggregate(member, parent, membersById, parentValueId, classesById, variantTargetClassByRootValueId, visitedMemberIds = /* @__PURE__ */ new Set()) {
125086
- const kind = member?.kind;
125087
- if (kind === 5 /* Dictionary */ || kind === 6 /* List */ || kind === 7 /* Class */ || kind === "dictionary" || kind === "list" || kind === "class") {
125088
- return true;
125089
- }
125090
- if (kind !== 21 /* Generic */ && kind !== "generic") return false;
125091
- const memberId = typeof member?.id === "string" ? member.id : null;
125092
- if (memberId !== null && visitedMemberIds.has(memberId)) return false;
125093
- const genericParamId = member?.genericParamId;
125094
- const bindings = parent.genericBindings;
125095
- if (typeof genericParamId === "string" && isObjectRecord2(bindings)) {
125096
- const bindingMemberId = bindings[genericParamId];
125097
- if (typeof bindingMemberId === "string") {
125098
- return memberStoresAggregate(
125099
- membersById.get(bindingMemberId),
125100
- parent,
125101
- membersById,
125102
- parentValueId,
125103
- classesById,
125104
- variantTargetClassByRootValueId,
125105
- /* @__PURE__ */ new Set([
125106
- ...visitedMemberIds,
125107
- ...memberId === null ? [] : [memberId]
125108
- ])
125109
- );
125110
- }
125111
- }
125112
- const parentClassId = parent.classId;
125113
- const variantTargetClassId = variantTargetClassByRootValueId.get(parentValueId);
125114
- if (typeof parentClassId === "string" && typeof variantTargetClassId === "string" && classesById.get(parentClassId)?.genericParamIds?.[0] === genericParamId && classesById.has(variantTargetClassId)) {
125115
- return true;
125116
- }
125117
- return false;
125118
- }
125119
- function isStringRecord9(value) {
125120
- return isObjectRecord2(value) && Object.values(value).every((entry) => typeof entry === "string");
125121
- }
125122
- var init_stored_value_placements = __esm({
125123
- "src/project-source/stored-value-placements.ts"() {
125124
- "use strict";
125125
- init_constructors2();
125126
- init_constructor_parameter_settlement();
125127
- init_members();
125128
- init_neo_script_derived_bodies();
125129
- init_value_comparison();
125130
- }
125131
- });
125132
-
125133
125896
  // src/project-source/root-source.ts
125134
125897
  function emitProjectRootSourceV4(records2, manifest, materializedConstructors, localValues, options = {}) {
125135
125898
  const project = [...records2.values()].find(
@@ -127041,7 +127804,8 @@ function computeWorkspaceStatus(workspace, options) {
127041
127804
  diagnostic2.range.start.line + 1,
127042
127805
  diagnostic2.range.start.character + 1,
127043
127806
  diagnostic2.code,
127044
- diagnostic2.severity
127807
+ diagnostic2.severity,
127808
+ diagnostic2.range
127045
127809
  );
127046
127810
  if (positioned.severity === "error") parseErrors.push(positioned);
127047
127811
  else parseWarnings.push(positioned);
@@ -127548,10 +128312,28 @@ function computeWorkspaceStatus(workspace, options) {
127548
128312
  ],
127549
128313
  staticMemberValueIds
127550
128314
  );
127551
- const dialogueRecords = lowerDialogueProjectSourcesV4(
127552
- prospectiveState,
127553
- projectAnalysisV4
127554
- );
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
+ }
127555
128337
  reportPhase("supplemental-dialogue", "Comparing records\u2026");
127556
128338
  records2.push(
127557
128339
  ...staticValues.records,
@@ -128067,6 +128849,7 @@ function computeWorkspaceStatus(workspace, options) {
128067
128849
  );
128068
128850
  return {
128069
128851
  ...projectAnalysisV4 === null ? {} : {
128852
+ dialogueBodySources,
128070
128853
  sourceSnapshot: {
128071
128854
  inputs: compilationSources,
128072
128855
  analysis: projectAnalysisV4
@@ -129127,6 +129910,7 @@ var ANIMATION_DOCUMENT_RECORD_KINDS, ANIMATION_REPLAY_RECORD_KINDS, PROSPECTIVE_
129127
129910
  var init_workspace_status_core = __esm({
129128
129911
  "src/project-source/workspace-status-core.ts"() {
129129
129912
  "use strict";
129913
+ init_source_text();
129130
129914
  init_runtime_diagnostic();
129131
129915
  init_NSGetterRuntimeError();
129132
129916
  init_lower_support();
@@ -131436,7 +132220,15 @@ function buildValueLowerContext(state, manifest, options = {}) {
131436
132220
  let storedValuePlacements;
131437
132221
  const readStoredValuePlacements = () => storedValuePlacements ??= buildStoredValuePlacementIndexV4(stateRecords);
131438
132222
  let rootValueTargets;
132223
+ let referenceTypes;
132224
+ const readReferenceTypes = () => referenceTypes ??= new ReferenceTargetTypes(
132225
+ state,
132226
+ void 0,
132227
+ registry.pendingValues.values(),
132228
+ manifest
132229
+ );
131439
132230
  return {
132231
+ referenceTypes: readReferenceTypes,
131440
132232
  listenerBindings: registry.listenerBindings,
131441
132233
  misplacedLocalListeners: registry.misplacedLocalListeners,
131442
132234
  localValues: registry.localValues ??= new LocalValueBindingsV4(
@@ -132105,6 +132897,21 @@ function lowerMemberDefaultSourcesV4(state, analysis, manifest, options = {}) {
132105
132897
  continue;
132106
132898
  }
132107
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
+ }
132108
132915
  continue;
132109
132916
  }
132110
132917
  const rootValueId = pendingValueId(binding, `${label}.default`);
@@ -135969,6 +136776,12 @@ function validateReferenceContract(context, member, target, ownerValueId) {
135969
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.`
135970
136777
  );
135971
136778
  }
136779
+ if (target.genericTypeName)
136780
+ context.referenceTypes().assertAssignable(
136781
+ target.id,
136782
+ target.genericTypeName,
136783
+ `Reference<${target.genericTypeName}>`
136784
+ );
135972
136785
  if (target.genericTypeName && expectedTypeName && !referenceTypeNameAssignable(
135973
136786
  context,
135974
136787
  target.genericTypeName,
@@ -138919,6 +139732,7 @@ var INFERRED_GENERIC_CLASS_PREFIX, MEMBER_KIND_DICTIONARY2, MEMBER_KIND_LIST2, M
138919
139732
  var init_value_sources = __esm({
138920
139733
  "src/project-source/value-sources.ts"() {
138921
139734
  "use strict";
139735
+ init_reference_target_types();
138922
139736
  init_listener_template_graph();
138923
139737
  init_listener_template_type();
138924
139738
  init_project_root_members();
@@ -140949,6 +141763,75 @@ var init_project_file_source_preservation = __esm({
140949
141763
  }
140950
141764
  });
140951
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
+
140952
141835
  // ../packages/neoscript-language/src/local-scope-index.ts
140953
141836
  var LocalScopeIndex;
140954
141837
  var init_local_scope_index = __esm({
@@ -146232,6 +147115,7 @@ function projectSemanticTokens(document, analysis) {
146232
147115
  const index = buildProjectSymbolIndex(analysis.symbols);
146233
147116
  const tokens = projectTokens(document);
146234
147117
  const bodyContexts = projectBodies(analysis, document.uri);
147118
+ const source = analysis.documents.get(document.uri);
146235
147119
  const result = tokens.flatMap((token, tokenIndex) => {
146236
147120
  if (token.kind === "eof" || token.kind === "error") return [];
146237
147121
  if (rangeItemAt(bodyContexts, token.range.start)) {
@@ -146242,6 +147126,14 @@ function projectSemanticTokens(document, analysis) {
146242
147126
  let type;
146243
147127
  if (declaration) {
146244
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";
146245
147137
  } else if (resolved) {
146246
147138
  type = projectSemanticTokenType(resolved);
146247
147139
  } else if (token.kind === "keyword") type = "keyword";
@@ -146326,6 +147218,7 @@ function indexedProjectSymbolAt(analysis, document, position, index) {
146326
147218
  (symbol) => symbol.kind === "class" || symbol.kind === "interface" || symbol.kind === "enum" || symbol.kind === "genericParameter"
146327
147219
  );
146328
147220
  if (types.length === 1) return { token, symbol: types[0] };
147221
+ if (typePosition) return null;
146329
147222
  }
146330
147223
  const scoped = candidates.filter(
146331
147224
  (symbol) => symbol.scopeRange && symbol.location.uri === document.uri && rangeContains(symbol.scopeRange, token.range.start)
@@ -147155,6 +148048,7 @@ var init_project_source_language_features = __esm({
147155
148048
  init_analyzer();
147156
148049
  init_lexer();
147157
148050
  init_language_spec();
148051
+ init_neoflow_graph_parser();
147158
148052
  init_project_source_semantics();
147159
148053
  init_project_source_variants();
147160
148054
  init_project_source_lifecycle_editor();
@@ -169073,6 +169967,15 @@ function candidateTimestamp(purpose) {
169073
169967
  return purpose === "export" /* Export */ ? 1 : Date.now();
169074
169968
  }
169075
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;
169076
169979
  if (!(error instanceof StoredClosureCaptureError)) return error;
169077
169980
  let valueId = error.valueId;
169078
169981
  for (const [pendingId2, assignedId] of assigned) {
@@ -171058,6 +171961,7 @@ var compileNSVoidBody2, compileNSFunction2, compileNSGetter2, compileNSSetter2,
171058
171961
  var init_push = __esm({
171059
171962
  "src/commands/push.ts"() {
171060
171963
  "use strict";
171964
+ init_dialogue_source_diagnostic();
171061
171965
  init_lower_constructors();
171062
171966
  init_neoscript_source_catalog();
171063
171967
  init_src2();
@@ -184929,7 +185833,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
184929
185833
  async function main() {
184930
185834
  const args = parseArgs(process.argv.slice(2));
184931
185835
  if (args.command === "--version") {
184932
- console.log("0.71.1");
185836
+ console.log("0.71.2");
184933
185837
  return;
184934
185838
  }
184935
185839
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {