@neocompose/cli 0.89.0 → 0.89.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/neo-runtime.mjs +1610 -520
- package/dist/test-worker.mjs +164 -54
- package/package.json +1 -1
- package/skills/neocompose-cli/SKILL.md +1 -1
- package/skills/neocompose-cli/references/cli-development.md +1 -1
- package/skills/neocompose-cli/references/values/references.md +39 -16
- package/skills/neocompose-cli/references/world/variants.md +4 -3
package/dist/test-worker.mjs
CHANGED
|
@@ -22918,8 +22918,12 @@ var FunctionTypeInference = class {
|
|
|
22918
22918
|
const value = actual.parameterTypes[index];
|
|
22919
22919
|
if (value !== void 0) this.add(value, expected, "exact");
|
|
22920
22920
|
});
|
|
22921
|
-
} else if (pattern.kind === "reference"
|
|
22922
|
-
this.add(
|
|
22921
|
+
} else if (pattern.kind === "reference") {
|
|
22922
|
+
this.add(
|
|
22923
|
+
actual.kind === "reference" ? actual.target : actual,
|
|
22924
|
+
pattern.target,
|
|
22925
|
+
"exact"
|
|
22926
|
+
);
|
|
22923
22927
|
}
|
|
22924
22928
|
}
|
|
22925
22929
|
fix(index) {
|
|
@@ -33327,11 +33331,14 @@ function resolveMemberForValueRow(row, ctx, visited) {
|
|
|
33327
33331
|
ctx.__valueOverlay
|
|
33328
33332
|
);
|
|
33329
33333
|
if (parent === null) continue;
|
|
33330
|
-
|
|
33331
|
-
|
|
33332
|
-
|
|
33333
|
-
|
|
33334
|
-
|
|
33334
|
+
let parentMember = resolveMemberForValueRow(parent, ctx, new Set(visited));
|
|
33335
|
+
if (parentMember?.kind === 21 /* Generic */) {
|
|
33336
|
+
parentMember = substituteMember(
|
|
33337
|
+
parentMember,
|
|
33338
|
+
runtimeParentGenericEnv(parent, ctx, /* @__PURE__ */ new Set()),
|
|
33339
|
+
ctx.vm.members
|
|
33340
|
+
);
|
|
33341
|
+
}
|
|
33335
33342
|
if (parentMember !== null && isMemberTupleBase(parentMember)) {
|
|
33336
33343
|
const memberId = parentMember.elementMemberIds[Number(link.key)];
|
|
33337
33344
|
return memberId === void 0 ? null : evalMemberById(ctx.vm, memberId);
|
|
@@ -50834,7 +50841,9 @@ function indexCalls(tokens, pairs, lexed) {
|
|
|
50834
50841
|
const name = tokens[index];
|
|
50835
50842
|
const openIndex = callOpenParenIndex(tokens, index);
|
|
50836
50843
|
const open = tokens[openIndex];
|
|
50837
|
-
if (!name
|
|
50844
|
+
if (!name) continue;
|
|
50845
|
+
const expression = [")", "]", "!"].includes(name.text) && openIndex === index + 1;
|
|
50846
|
+
if (name.kind !== "identifier" && !expression) continue;
|
|
50838
50847
|
if (!open || open.kind !== "punctuation" || open.text !== "(") continue;
|
|
50839
50848
|
const previous = tokens[index - 1];
|
|
50840
50849
|
const targetTyped = isContextualNew(name, previous, open);
|
|
@@ -50863,14 +50872,19 @@ function indexCalls(tokens, pairs, lexed) {
|
|
|
50863
50872
|
segmentStart = token.end;
|
|
50864
50873
|
segmentStartIndex = cursor + 1;
|
|
50865
50874
|
}
|
|
50875
|
+
if (tokens[cursor + 1]?.text === "<") {
|
|
50876
|
+
const genericOpen = callOpenParenIndex(tokens, cursor);
|
|
50877
|
+
if (genericOpen >= 0) cursor = genericOpen - 1;
|
|
50878
|
+
}
|
|
50866
50879
|
}
|
|
50867
50880
|
if (segmentStart < (close?.start ?? lexed.end)) {
|
|
50868
50881
|
ranges.push(lexed.source.range(segmentStart, close?.start ?? lexed.end));
|
|
50869
50882
|
names2.push(callArgumentLabel(tokens, segmentStartIndex, limit));
|
|
50870
50883
|
}
|
|
50884
|
+
const namedKind = contextualKeyword ? "constructor" : "function";
|
|
50871
50885
|
calls.push({
|
|
50872
|
-
kind:
|
|
50873
|
-
name: name.text,
|
|
50886
|
+
kind: expression ? "expression" : namedKind,
|
|
50887
|
+
name: expression ? "delegate" : name.text,
|
|
50874
50888
|
nameRange: name.range,
|
|
50875
50889
|
...contextualKeyword ? { contextualKeywordRange: contextualKeyword.range } : {},
|
|
50876
50890
|
...targetTyped ? { targetTyped: true } : {},
|
|
@@ -52690,6 +52704,10 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
52690
52704
|
if (expected === void 0) return;
|
|
52691
52705
|
this.requireAssignable(resolved.type, expected, expression.pos, "value");
|
|
52692
52706
|
}
|
|
52707
|
+
/** Type a source expression with the same call binding rules as executable code. */
|
|
52708
|
+
resolveExpressionType(expression) {
|
|
52709
|
+
return this.resolveExpression(expression, this.initialScope()).type;
|
|
52710
|
+
}
|
|
52693
52711
|
persistedListenerCompletions(receiver, expected) {
|
|
52694
52712
|
const scope = this.initialScope();
|
|
52695
52713
|
let receiverType = this.context.thisClass;
|
|
@@ -54956,8 +54974,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
54956
54974
|
);
|
|
54957
54975
|
}
|
|
54958
54976
|
}
|
|
54959
|
-
resolveMemberRowOf(place, scope) {
|
|
54960
|
-
const optional2 = place.optional === true;
|
|
54977
|
+
resolveMemberRowOf(place, scope, resolved) {
|
|
54961
54978
|
if ((this.context.kind === "initializer" || this.context.kind === "initializerExpression") && this.delegateCaptureContexts.length === 0 && referencePlaceRoot(place) === "this") {
|
|
54962
54979
|
const text = referencePlaceText(place) ?? "this";
|
|
54963
54980
|
throw new CompileError(
|
|
@@ -54965,12 +54982,12 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
54965
54982
|
place.pos
|
|
54966
54983
|
);
|
|
54967
54984
|
}
|
|
54968
|
-
const slot = this.resolveMemberNatural(
|
|
54985
|
+
const slot = resolved ?? this.resolveMemberNatural(
|
|
54969
54986
|
place.receiver,
|
|
54970
54987
|
place.name,
|
|
54971
54988
|
scope,
|
|
54972
54989
|
place.pos,
|
|
54973
|
-
|
|
54990
|
+
place.optional === true
|
|
54974
54991
|
);
|
|
54975
54992
|
const member = slot.symbol;
|
|
54976
54993
|
if (member === void 0) {
|
|
@@ -54988,19 +55005,55 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
54988
55005
|
place.pos
|
|
54989
55006
|
);
|
|
54990
55007
|
}
|
|
54991
|
-
const
|
|
54992
|
-
const stored = member.lookup !== void 0 && member.lookup.multiselect !== true && read.kind !== "reference" ? {
|
|
54993
|
-
kind: "reference",
|
|
54994
|
-
target: { ...read, nullable: false },
|
|
54995
|
-
...isNullable(read) ? { nullable: true } : {}
|
|
54996
|
-
} : read;
|
|
54997
|
-
const type2 = this.referenceType(stored, optional2);
|
|
55008
|
+
const type2 = this.memberReferenceType(slot, place.optional === true);
|
|
54998
55009
|
if (type2.kind !== "reference") return slot;
|
|
54999
55010
|
return {
|
|
55000
55011
|
pointer: { type: "rowOf" /* RowOf */, place: slot.pointer },
|
|
55001
55012
|
type: type2
|
|
55002
55013
|
};
|
|
55003
55014
|
}
|
|
55015
|
+
memberReferenceType(slot, optional2) {
|
|
55016
|
+
const read = slot.storedType ?? slot.optionalChainType ?? slot.type;
|
|
55017
|
+
const stored = slot.symbol?.lookup !== void 0 && slot.symbol.lookup.multiselect !== true && read.kind !== "reference" ? {
|
|
55018
|
+
kind: "reference",
|
|
55019
|
+
target: { ...read, nullable: false },
|
|
55020
|
+
...isNullable(read) ? { nullable: true } : {}
|
|
55021
|
+
} : read;
|
|
55022
|
+
return this.referenceType(
|
|
55023
|
+
stored,
|
|
55024
|
+
optional2 || slot.optionalChainType !== void 0
|
|
55025
|
+
);
|
|
55026
|
+
}
|
|
55027
|
+
/** Only stored member slots can acquire a reference from an expected type. */
|
|
55028
|
+
implicitReferenceType(expression, value) {
|
|
55029
|
+
if (expression.kind !== "member") return void 0;
|
|
55030
|
+
if (value.symbol === void 0 || value.symbol.computed === true)
|
|
55031
|
+
return void 0;
|
|
55032
|
+
return this.memberReferenceType(value, expression.optional === true);
|
|
55033
|
+
}
|
|
55034
|
+
referenceInferenceType(expression, value, pattern) {
|
|
55035
|
+
const read = this.readReferences(value, pattern).type;
|
|
55036
|
+
if (pattern.kind !== "reference" || read.kind === "reference") return read;
|
|
55037
|
+
return this.implicitReferenceType(expression, value) ?? read;
|
|
55038
|
+
}
|
|
55039
|
+
contextualReferenceType(expression, value, expected) {
|
|
55040
|
+
const read = this.readReferences(value, expected).type;
|
|
55041
|
+
if (expected.kind !== "reference" || isNeoScriptTypeAssignable(read, expected, this.project))
|
|
55042
|
+
return read;
|
|
55043
|
+
const reference = this.implicitReferenceType(expression, value);
|
|
55044
|
+
return reference !== void 0 && isNeoScriptTypeAssignable(reference, expected, this.project) ? reference : read;
|
|
55045
|
+
}
|
|
55046
|
+
/** Use the same slot identity for explicit and expected-type references. */
|
|
55047
|
+
contextualReference(expression, value, scope, expected) {
|
|
55048
|
+
const read = this.readReferences(value, expected);
|
|
55049
|
+
if (expected?.kind !== "reference" || isNeoScriptTypeAssignable(read.type, expected, this.project))
|
|
55050
|
+
return read;
|
|
55051
|
+
const reference = this.implicitReferenceType(expression, value);
|
|
55052
|
+
if (expression.kind === "member" && reference !== void 0 && isNeoScriptTypeAssignable(reference, expected, this.project)) {
|
|
55053
|
+
return this.resolveMemberRowOf(expression, scope, value);
|
|
55054
|
+
}
|
|
55055
|
+
return read;
|
|
55056
|
+
}
|
|
55004
55057
|
/** Whether assigning `target` rebinds a reference to a handle. */
|
|
55005
55058
|
holdsHandleReference(target) {
|
|
55006
55059
|
if (target.type.kind === "reference") {
|
|
@@ -55609,13 +55662,15 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
55609
55662
|
});
|
|
55610
55663
|
}
|
|
55611
55664
|
resolveExpression(expression, scope, expected, convertSequence = true) {
|
|
55612
|
-
const value = this.
|
|
55665
|
+
const value = this.contextualReference(
|
|
55666
|
+
expression,
|
|
55613
55667
|
this.resolveReferenceExpression(
|
|
55614
55668
|
expression,
|
|
55615
55669
|
scope,
|
|
55616
55670
|
expected,
|
|
55617
55671
|
convertSequence
|
|
55618
55672
|
),
|
|
55673
|
+
scope,
|
|
55619
55674
|
expected
|
|
55620
55675
|
);
|
|
55621
55676
|
return convertSequence ? this.convertSequence(value, expected) : value;
|
|
@@ -57137,7 +57192,8 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
57137
57192
|
}
|
|
57138
57193
|
entryType = common;
|
|
57139
57194
|
}
|
|
57140
|
-
|
|
57195
|
+
const referenceSelection = expected?.kind === "set" && this.context.kind === "initializer" && (expected.elementType.kind === "reference" || hasReferenceEquality(expected.elementType, this.project));
|
|
57196
|
+
if (expected?.kind === "set" && this.context.kind === "initializer" && !referenceSelection) {
|
|
57141
57197
|
const element = expected.elementType;
|
|
57142
57198
|
const spelling = element.kind === "named" && this.project.typeById.get(element.typeId)?.kind === "enum" ? `.Option or ${this.describe({ ...element, nullable: false })}.Option values` : "literal values";
|
|
57143
57199
|
throw new CompileError(
|
|
@@ -57155,7 +57211,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
57155
57211
|
"NeoScript strict compiler produced a non-list wire type for a list literal."
|
|
57156
57212
|
);
|
|
57157
57213
|
}
|
|
57158
|
-
|
|
57214
|
+
const list = {
|
|
57159
57215
|
pointer: {
|
|
57160
57216
|
type: "listLiteral" /* ListLiteral */,
|
|
57161
57217
|
typeInfo: wire,
|
|
@@ -57164,6 +57220,18 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
57164
57220
|
type: type2,
|
|
57165
57221
|
entries: resolved
|
|
57166
57222
|
};
|
|
57223
|
+
return referenceSelection ? this.resolveCollectionQuery(
|
|
57224
|
+
list,
|
|
57225
|
+
{
|
|
57226
|
+
kind: "list",
|
|
57227
|
+
keyType: { kind: "primitive", name: "int" },
|
|
57228
|
+
valueType: entryType
|
|
57229
|
+
},
|
|
57230
|
+
"ToSet",
|
|
57231
|
+
[],
|
|
57232
|
+
scope,
|
|
57233
|
+
pos
|
|
57234
|
+
) : list;
|
|
57167
57235
|
}
|
|
57168
57236
|
resolveDictionaryLiteral(entries, scope, expected, pos) {
|
|
57169
57237
|
const expectedDictionary = expected?.kind === "dictionary" ? expected : void 0;
|
|
@@ -57874,7 +57942,12 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
57874
57942
|
const rootEntry = scope.lookupFlowRoot(pathRoot(path));
|
|
57875
57943
|
if (rootEntry) {
|
|
57876
57944
|
const narrowed = scope.lookupNarrowedType(path, rootEntry);
|
|
57877
|
-
if (narrowed)
|
|
57945
|
+
if (narrowed)
|
|
57946
|
+
resolved = {
|
|
57947
|
+
...resolved,
|
|
57948
|
+
storedType: resolved.type,
|
|
57949
|
+
type: narrowed
|
|
57950
|
+
};
|
|
57878
57951
|
}
|
|
57879
57952
|
}
|
|
57880
57953
|
}
|
|
@@ -60593,17 +60666,28 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
60593
60666
|
args,
|
|
60594
60667
|
scope
|
|
60595
60668
|
);
|
|
60596
|
-
|
|
60669
|
+
const resolve = (implicit) => resolveNeoScriptDeclaredConstructorOverload(
|
|
60597
60670
|
declared,
|
|
60598
60671
|
named.map((name, index) => {
|
|
60599
60672
|
const inferred = inferredTypes?.[index];
|
|
60600
|
-
|
|
60673
|
+
const argument2 = args[index];
|
|
60674
|
+
if (!inferred || !argument2) return { name };
|
|
60601
60675
|
return {
|
|
60602
60676
|
name,
|
|
60603
|
-
matchesParameter: (parameter3) =>
|
|
60677
|
+
matchesParameter: (parameter3) => implicit && parameter3.type.kind === "reference" && isContextualReferenceExpression(argument2) ? this.targetTypedArgumentFits(argument2, parameter3.type, scope) : isNeoScriptTypeAssignable(
|
|
60678
|
+
implicit ? this.contextualReferenceType(
|
|
60679
|
+
argument2,
|
|
60680
|
+
inferred,
|
|
60681
|
+
parameter3.type
|
|
60682
|
+
) : inferred.type,
|
|
60683
|
+
parameter3.type,
|
|
60684
|
+
this.project
|
|
60685
|
+
)
|
|
60604
60686
|
};
|
|
60605
60687
|
})
|
|
60606
60688
|
);
|
|
60689
|
+
const direct = resolve(false);
|
|
60690
|
+
return direct.kind === "ambiguous" ? resolve(true) : direct;
|
|
60607
60691
|
}
|
|
60608
60692
|
/**
|
|
60609
60693
|
* Types for the §6.1.1 step-2 tie-break, computed only when several
|
|
@@ -60624,7 +60708,9 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
60624
60708
|
const argument2 = args[index];
|
|
60625
60709
|
if (!argument2) return null;
|
|
60626
60710
|
try {
|
|
60627
|
-
|
|
60711
|
+
if (isContextualReferenceExpression(argument2))
|
|
60712
|
+
this.typeOverloadEntries(argument2, scope);
|
|
60713
|
+
return this.resolveReferenceExpression(argument2, scope);
|
|
60628
60714
|
} catch (error) {
|
|
60629
60715
|
if (error instanceof CompileError) return null;
|
|
60630
60716
|
throw error;
|
|
@@ -60994,7 +61080,8 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
60994
61080
|
(argument2) => this.overloadArgumentKind(argument2, scope)
|
|
60995
61081
|
);
|
|
60996
61082
|
argumentsList2.forEach((argument2, index) => {
|
|
60997
|
-
if (kinds[index] !== "typed"
|
|
61083
|
+
if (kinds[index] !== "typed" || isContextualReferenceExpression(argument2))
|
|
61084
|
+
this.typeOverloadEntries(argument2, scope);
|
|
60998
61085
|
});
|
|
60999
61086
|
const typed = argumentsList2.map(
|
|
61000
61087
|
(argument2, index) => kinds[index] === "targetTyped" ? void 0 : this.resolveReferenceExpression(argument2, scope)
|
|
@@ -61042,11 +61129,11 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
61042
61129
|
const fits = argumentsList2.every((argument2, index) => {
|
|
61043
61130
|
const parameter3 = requiredAt(parameters, index).type;
|
|
61044
61131
|
const resolved = typed[index];
|
|
61045
|
-
if (resolved === void 0 || argument2.kind === "tuple" || kinds[index] === "numeric" && parameter3.kind === "tuple") {
|
|
61132
|
+
if (resolved === void 0 || parameter3.kind === "reference" && isContextualReferenceExpression(argument2) || argument2.kind === "tuple" || kinds[index] === "numeric" && parameter3.kind === "tuple") {
|
|
61046
61133
|
return this.targetTypedArgumentFits(argument2, parameter3, scope);
|
|
61047
61134
|
}
|
|
61048
61135
|
return this.typedArgumentFits(
|
|
61049
|
-
this.
|
|
61136
|
+
this.contextualReferenceType(argument2, resolved, parameter3),
|
|
61050
61137
|
requiredAt(kinds, index),
|
|
61051
61138
|
parameter3
|
|
61052
61139
|
);
|
|
@@ -61218,6 +61305,12 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
61218
61305
|
}
|
|
61219
61306
|
case "annotated":
|
|
61220
61307
|
return this.entryFits(argument2.expression, parameter3, scope);
|
|
61308
|
+
case "coalesce":
|
|
61309
|
+
return this.entryFits(
|
|
61310
|
+
argument2.left,
|
|
61311
|
+
{ ...parameter3, nullable: true },
|
|
61312
|
+
scope
|
|
61313
|
+
) && this.entryFits(argument2.right, parameter3, scope);
|
|
61221
61314
|
case "conditional": {
|
|
61222
61315
|
const { trueScope, falseScope } = this.conditionalBranchScopes(
|
|
61223
61316
|
argument2,
|
|
@@ -61297,12 +61390,12 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
61297
61390
|
*/
|
|
61298
61391
|
entryFits(argument2, parameter3, scope) {
|
|
61299
61392
|
const kind = this.overloadArgumentKind(argument2, scope);
|
|
61300
|
-
if (kind === "targetTyped" || argument2.kind === "tuple" || kind === "numeric" && parameter3.kind === "tuple") {
|
|
61393
|
+
if (kind === "targetTyped" || parameter3.kind === "reference" && isContextualReferenceExpression(argument2) || argument2.kind === "tuple" || kind === "numeric" && parameter3.kind === "tuple") {
|
|
61301
61394
|
return this.targetTypedArgumentFits(argument2, parameter3, scope);
|
|
61302
61395
|
}
|
|
61303
|
-
const resolved = isPureArgument(argument2) ? this.
|
|
61396
|
+
const resolved = isPureArgument(argument2) ? this.resolveReferenceExpression(argument2, scope) : this.overloadEntries.get(argument2) ?? this.resolveReferenceExpression(argument2, scope);
|
|
61304
61397
|
return this.typedArgumentFits(
|
|
61305
|
-
this.
|
|
61398
|
+
this.contextualReferenceType(argument2, resolved, parameter3),
|
|
61306
61399
|
kind,
|
|
61307
61400
|
parameter3
|
|
61308
61401
|
);
|
|
@@ -61345,6 +61438,10 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
61345
61438
|
case "annotated":
|
|
61346
61439
|
visit(argument2.expression, scope);
|
|
61347
61440
|
return;
|
|
61441
|
+
case "coalesce":
|
|
61442
|
+
visit(argument2.left, scope);
|
|
61443
|
+
visit(argument2.right, scope);
|
|
61444
|
+
return;
|
|
61348
61445
|
case "conditional": {
|
|
61349
61446
|
visit(argument2.condition, scope);
|
|
61350
61447
|
const { trueScope, falseScope } = this.conditionalBranchScopes(
|
|
@@ -61529,19 +61626,16 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
61529
61626
|
pos,
|
|
61530
61627
|
inferred?.typeArguments
|
|
61531
61628
|
);
|
|
61532
|
-
|
|
61533
|
-
|
|
61534
|
-
|
|
61535
|
-
|
|
61536
|
-
|
|
61537
|
-
|
|
61538
|
-
|
|
61539
|
-
|
|
61540
|
-
|
|
61541
|
-
|
|
61542
|
-
})
|
|
61543
|
-
)
|
|
61544
|
-
});
|
|
61629
|
+
this.options.onCallResolved?.(pos, {
|
|
61630
|
+
...symbol,
|
|
61631
|
+
type: signature.returnType,
|
|
61632
|
+
returnType: signature.returnType,
|
|
61633
|
+
parameters: signature.parameters,
|
|
61634
|
+
typeParameters: (symbol.typeParameters ?? []).map((parameter3, index) => ({
|
|
61635
|
+
...parameter3,
|
|
61636
|
+
type: requiredAt(signature.typeArguments, index)
|
|
61637
|
+
}))
|
|
61638
|
+
});
|
|
61545
61639
|
const wireTypeArguments = signature.typeArguments.length ? {
|
|
61546
61640
|
typeArguments: signature.typeArguments.map(
|
|
61547
61641
|
(argument2) => toWireType(argument2, this.project)
|
|
@@ -61716,7 +61810,12 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
61716
61810
|
const prior = choice?.preResolved[index];
|
|
61717
61811
|
const cached = inferred?.resolved.get(argument2);
|
|
61718
61812
|
let resolved;
|
|
61719
|
-
if (prior !== void 0
|
|
61813
|
+
if (prior !== void 0 && !(target?.kind === "reference" && isContextualReferenceExpression(argument2) && !isNeoScriptTypeAssignable(
|
|
61814
|
+
this.readReferences(prior, target).type,
|
|
61815
|
+
target,
|
|
61816
|
+
this.project
|
|
61817
|
+
)))
|
|
61818
|
+
resolved = this.readReferences(prior, target);
|
|
61720
61819
|
else if (cached && (sameCompilationType(cached.type, expected) || cached.pointer.type === "callFunction" /* CallFunction */)) {
|
|
61721
61820
|
resolved = cached;
|
|
61722
61821
|
} else {
|
|
@@ -61725,6 +61824,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
61725
61824
|
const compile = () => this.resolveExpression(argument2, scope, target);
|
|
61726
61825
|
resolved = weighed ?? (argument2.kind === "lambda" && lambdas ? this.inLambdaFrame(lambdas, argument2, compile) : compile());
|
|
61727
61826
|
}
|
|
61827
|
+
resolved = this.contextualReference(argument2, resolved, scope, target);
|
|
61728
61828
|
resolved = this.convertSequence(resolved, target);
|
|
61729
61829
|
if (!isUnknown(expected)) {
|
|
61730
61830
|
this.requireReferenceArgument(
|
|
@@ -61799,7 +61899,10 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
61799
61899
|
if (!hasIndependentTypeEvidence(argument2)) return;
|
|
61800
61900
|
const prior = weighed?.typed[index];
|
|
61801
61901
|
if (prior !== void 0) {
|
|
61802
|
-
inference.add(
|
|
61902
|
+
inference.add(
|
|
61903
|
+
this.referenceInferenceType(argument2, prior, pattern),
|
|
61904
|
+
pattern
|
|
61905
|
+
);
|
|
61803
61906
|
return;
|
|
61804
61907
|
}
|
|
61805
61908
|
const group = pattern.kind === "delegate" ? this.inferredMethodGroupTarget(argument2, probe) : null;
|
|
@@ -61810,10 +61913,13 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
61810
61913
|
pattern
|
|
61811
61914
|
);
|
|
61812
61915
|
} else {
|
|
61813
|
-
const resolved = weighed?.contextless.get(argument2) ?? this.
|
|
61916
|
+
const resolved = weighed?.contextless.get(argument2) ?? this.resolveReferenceExpression(argument2, probe);
|
|
61814
61917
|
weighed?.contextless.set(argument2, resolved);
|
|
61815
61918
|
resolvedArguments.set(argument2, resolved);
|
|
61816
|
-
inference.add(
|
|
61919
|
+
inference.add(
|
|
61920
|
+
this.referenceInferenceType(argument2, resolved, pattern),
|
|
61921
|
+
pattern
|
|
61922
|
+
);
|
|
61817
61923
|
}
|
|
61818
61924
|
});
|
|
61819
61925
|
const error = inference.solve(callbacks, (callback, inputs) => {
|
|
@@ -64883,7 +64989,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
64883
64989
|
}
|
|
64884
64990
|
return canonicalPath(target) ?? "the slot";
|
|
64885
64991
|
}
|
|
64886
|
-
/**
|
|
64992
|
+
/** A transient value has no stored slot to pass by reference. */
|
|
64887
64993
|
requireReferenceArgument(source, target, parameter3, pos) {
|
|
64888
64994
|
if (target.kind !== "reference") return;
|
|
64889
64995
|
if (source.kind === "reference") return;
|
|
@@ -64892,7 +64998,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
64892
64998
|
const value = this.describe(source);
|
|
64893
64999
|
const article = /^[aeiou]/i.test(value) ? "an" : "a";
|
|
64894
65000
|
throw new CompileError(
|
|
64895
|
-
`Argument \`${parameter3}\` needs a ${this.describe(target)}, not ${article} ${value}.
|
|
65001
|
+
`Argument \`${parameter3}\` needs a ${this.describe(target)}, not ${article} ${value}. Pass a stored ${this.describe(read)} member instead.`,
|
|
64896
65002
|
pos
|
|
64897
65003
|
);
|
|
64898
65004
|
}
|
|
@@ -67165,6 +67271,7 @@ function weighedLambda(probes, expected) {
|
|
|
67165
67271
|
if (probe === void 0 || probe.type.kind !== "delegate") return void 0;
|
|
67166
67272
|
if (probe.needsReturnContext !== true && sameCompilationType(probe.type.returnType, expected.returnType))
|
|
67167
67273
|
return probe;
|
|
67274
|
+
if (expected.returnType.kind === "reference") return void 0;
|
|
67168
67275
|
return probe.retype?.(expected.returnType);
|
|
67169
67276
|
}
|
|
67170
67277
|
function replaceReturns(instructions, replaced) {
|
|
@@ -67287,6 +67394,9 @@ function andList(texts) {
|
|
|
67287
67394
|
if (texts.length <= 2) return texts.join(" and ");
|
|
67288
67395
|
return `${texts.slice(0, -1).join(", ")}, and ${texts[texts.length - 1]}`;
|
|
67289
67396
|
}
|
|
67397
|
+
function isContextualReferenceExpression(expression) {
|
|
67398
|
+
return expression.kind === "conditional" || expression.kind === "switchExpression" || expression.kind === "coalesce" || expression.kind === "annotated";
|
|
67399
|
+
}
|
|
67290
67400
|
function isPureArgument(expression) {
|
|
67291
67401
|
switch (expression.kind) {
|
|
67292
67402
|
case "litInt":
|
package/package.json
CHANGED
|
@@ -109,7 +109,7 @@ The marker near the top of `SKILL.md` must exactly match the package version,
|
|
|
109
109
|
and this quoted copy is checked too:
|
|
110
110
|
|
|
111
111
|
```html
|
|
112
|
-
<!-- reviewed-through-cli: 0.89.
|
|
112
|
+
<!-- reviewed-through-cli: 0.89.1 -->
|
|
113
113
|
```
|
|
114
114
|
|
|
115
115
|
Keep this skill on current behavior. Upgrade steps, rollout prerequisites,
|
|
@@ -26,7 +26,8 @@ public Reference<int> TrackedStat; // another member's int
|
|
|
26
26
|
|
|
27
27
|
- `Reference<T>` also works as a parameter, collection element, dictionary
|
|
28
28
|
value, and unbound generic argument (`Box<Reference<int>>`), and keeps that
|
|
29
|
-
storage type through push and pull
|
|
29
|
+
storage type through push and pull, including nested generic collections
|
|
30
|
+
and named tuples. Use `Set<T>` parameters for several
|
|
30
31
|
selections.
|
|
31
32
|
- `@settings(collection: Owner.Member)` binds a class reference to one
|
|
32
33
|
collection. Unbound references select any stored row of `T` or a subclass,
|
|
@@ -47,20 +48,31 @@ public Reference<int> TrackedStat; // another member's int
|
|
|
47
48
|
|
|
48
49
|
```neo
|
|
49
50
|
public Reference<Item> StarterSeed = root.Assets.Items.Index.Slug["seed.carrot"]!;
|
|
50
|
-
public Reference<int> Gold =
|
|
51
|
-
public Reference<string> Greeting =
|
|
52
|
-
public Reference<NeoVariant<Tree>> Look =
|
|
51
|
+
public Reference<int> Gold = root.Player.Gold;
|
|
52
|
+
public Reference<string> Greeting = root.Npcs.Index.Slug["mira"]!.Greeting;
|
|
53
|
+
public Reference<NeoVariant<Tree>> Look = root.Garden.Felled;
|
|
53
54
|
```
|
|
54
55
|
|
|
55
56
|
- An unbound handle default may name its row by a unique index: a `root`
|
|
56
57
|
path to a List, `.Index.<Name>`, and a string literal key. Other shapes are
|
|
57
58
|
initializer code.
|
|
58
|
-
- Slot defaults
|
|
59
|
-
|
|
60
|
-
default stays the bare
|
|
59
|
+
- Slot defaults accept compatible stored member paths directly; `Reference()`
|
|
60
|
+
remains valid. Literals and computed values cannot supply a slot, and `this`
|
|
61
|
+
does not exist yet. A `NeoVariant<T>` member's own default stays the bare
|
|
62
|
+
variant path.
|
|
61
63
|
- List and dictionary defaults may hold slot references, nested too:
|
|
62
|
-
`List<Reference<int>> Counts = [
|
|
64
|
+
`List<Reference<int>> Counts = [root.Save.Bits]`. Each instance
|
|
63
65
|
owns the collection; entries target the original slots.
|
|
66
|
+
- `Set<Reference<T>>` selections can mix bare paths and explicit references.
|
|
67
|
+
Computed selections deduplicate by target identity, not by current value.
|
|
68
|
+
A literal selection of fixed targets must not repeat the same target.
|
|
69
|
+
- A bare path to an existing reference copies its current target when the
|
|
70
|
+
object is constructed. Later rebinding of that source reference does not
|
|
71
|
+
rebind the copy.
|
|
72
|
+
- A nullable target still needs a stored row. Pin an otherwise absent
|
|
73
|
+
nullable member in its owner's initializer, for example
|
|
74
|
+
`new() { Maybe = null }`, before referencing it. A declaration default alone
|
|
75
|
+
does not create that row.
|
|
64
76
|
|
|
65
77
|
## Source forms
|
|
66
78
|
|
|
@@ -89,11 +101,18 @@ Reference<NeoDialogue>(id: "capitol-dialogue-id")
|
|
|
89
101
|
|
|
90
102
|
## Runtime semantics
|
|
91
103
|
|
|
92
|
-
`Reference
|
|
93
|
-
`root.Player.Gold`, `item.Count
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
104
|
+
When executable code expects `Reference<T>`, pass a compatible stored member
|
|
105
|
+
such as `this.Gold`, `root.Player.Gold`, or `item.Count` directly. This works
|
|
106
|
+
for constructor and function arguments, returns, typed locals, object
|
|
107
|
+
initializers, and collection entries. The reference keeps following that
|
|
108
|
+
slot when its value changes. `Reference(place)` remains valid when an
|
|
109
|
+
explicit reference is needed.
|
|
110
|
+
|
|
111
|
+
Locals, parameters, list or dictionary elements, vector components, getters,
|
|
112
|
+
query results, and new scalar values have no row. A narrowed nullable member
|
|
113
|
+
still names its declared storage type. When `Selected` is `Reference<Item>`,
|
|
114
|
+
`Reference(this.Selected)` is `Reference<Reference<Item>>`. Access checks
|
|
115
|
+
apply where the reference is formed.
|
|
97
116
|
|
|
98
117
|
```neo
|
|
99
118
|
this.A = 5; // writes 5 into A's target
|
|
@@ -106,8 +125,8 @@ this.A += 1; // reads A's target, writes it back
|
|
|
106
125
|
- Assigning a same-typed reference rebinds; anything else writes through.
|
|
107
126
|
`this.A = c ? first : second` rebinds when both arms are references, writes
|
|
108
127
|
when both are scalars, and reads the chosen target when mixed.
|
|
109
|
-
- A
|
|
110
|
-
parameter is an error.
|
|
128
|
+
- A value without a stored slot never becomes a reference: passing `3` to a
|
|
129
|
+
`Reference<int>` parameter is an error.
|
|
111
130
|
- Constructors may initialize their own reference fields but can't write
|
|
112
131
|
through external targets.
|
|
113
132
|
- `==` compares handles by identity and slots by value. Collections of
|
|
@@ -138,6 +157,10 @@ Lookup assignment still needs an existing backing row.
|
|
|
138
157
|
(`root.Assets.Quests.Daily` or `Reference(root.Assets.Quests.Daily)`) and
|
|
139
158
|
follow the same rules. The path may cross construction defaults and
|
|
140
159
|
declarations from the same push; no preliminary push or manual ID is needed.
|
|
160
|
+
Pull emits bare paths in `collectionValue` settings when the target is reachable
|
|
161
|
+
from a root; otherwise it retains `Reference(id: "...")`. Lookup variant folder
|
|
162
|
+
bindings and `.Bind(root.Assets.Items.Index.Slug["seed.carrot"]!)` use the same
|
|
163
|
+
implicit reference conversion.
|
|
141
164
|
Invalid reference settings are errors, never silently dropped.
|
|
142
165
|
|
|
143
166
|
## Init-built objects
|
|
@@ -145,7 +168,7 @@ Invalid reference settings are errors, never silently dropped.
|
|
|
145
168
|
An object `Root.neo` writes is init-built when its class has an `init` block.
|
|
146
169
|
A declaration binding may name a member inside it, and push stores that
|
|
147
170
|
member's row. A reference captured by `init` or a constructor
|
|
148
|
-
(`new Rule(
|
|
171
|
+
(`new Rule(this.Weather)`) keeps its target's row. Status refuses a
|
|
149
172
|
value row's reference to a member of an init-built object (bind it from a
|
|
150
173
|
declaration instead) and a binding to a class or list that an `init` block
|
|
151
174
|
builds.
|
|
@@ -86,7 +86,7 @@ class root.
|
|
|
86
86
|
NeoLookupVariantFolder<ExampleObject, NeoSortingLayer> Root = new(
|
|
87
87
|
path: "",
|
|
88
88
|
collection: Assets.SortingLayers,
|
|
89
|
-
collectionValue:
|
|
89
|
+
collectionValue: root.Assets.SortingLayers,
|
|
90
90
|
);
|
|
91
91
|
|
|
92
92
|
@id("736dddf8-2881-47e1-a1d3-55fb65ea9f2a")
|
|
@@ -97,13 +97,14 @@ NeoLookupVariant<ExampleObject, NeoSortingLayer> Layered = new(
|
|
|
97
97
|
```
|
|
98
98
|
|
|
99
99
|
- `collection` names the eligible list member; `collectionValue` the stored
|
|
100
|
-
list whose rows it enumerates. Prefer the `
|
|
100
|
+
list whose rows it enumerates. Prefer the bare `root...` path pull
|
|
101
101
|
emits.
|
|
102
102
|
- Lookup `initialize` receives the row; lookup `apply` receives the object,
|
|
103
103
|
then the row.
|
|
104
104
|
- A `NeoLookupVariant<TObject, TValue>` member holds an unbound handle. A
|
|
105
105
|
plain `NeoVariant<TObject>` member may pick one row with
|
|
106
|
-
`.Bind(
|
|
106
|
+
`.Bind(root.Assets.Items.Index.Slug["seed.carrot"]!)`; explicit
|
|
107
|
+
`Reference(...)` remains valid. Never bind a row to the lookup-handle type.
|
|
107
108
|
|
|
108
109
|
## Type restrictions
|
|
109
110
|
|