@neocompose/cli 0.32.4 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.33.0] - 2026-08-19
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Add lazy, right-associative conditional expressions with the familiar
|
|
8
|
+
`condition ? whenTrue : whenFalse` spelling. Both result arms are
|
|
9
|
+
target-typed and only the selected arm runs in CLI tests, web previews, and
|
|
10
|
+
the Unity runtime. Project exports now use schema version 24 and compiled
|
|
11
|
+
NeoScript bodies use compiler revision 12 so older runtimes fail at their
|
|
12
|
+
normal compatibility gate.
|
|
13
|
+
- Add `NeoAction.Clear()` as the statement-form way to replace an action's
|
|
14
|
+
stored listener set with the empty set.
|
|
15
|
+
- Allow returned inline `NeoDelegate` lambdas to capture surrounding locals
|
|
16
|
+
and parameters by value. Captures are explicit in revision-12 IR and remain
|
|
17
|
+
available after the delegate is stored or serialized.
|
|
18
|
+
- Accept every NeoScript type grammar in explicit lambda parameters, including
|
|
19
|
+
`decimal`, generic parameters, collections, arrays, and nullable types.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Resolve local type annotations such as `T modifiedValue` against the
|
|
24
|
+
declaring Class's generic parameters instead of synthesizing an unrelated
|
|
25
|
+
type named `T`.
|
|
26
|
+
- Support `Equals(...)` on a non-null generic type parameter. Runtime Class
|
|
27
|
+
values dispatch a compatible one-argument, bool-returning `Equals` Function
|
|
28
|
+
or NSFunction (including overrides); other values use ordinary NeoScript
|
|
29
|
+
equality.
|
|
30
|
+
- Parse `value is Type ? whenTrue : whenFalse` as a conditional expression
|
|
31
|
+
instead of consuming its question mark as a forbidden nullable `is Type?`
|
|
32
|
+
suffix.
|
|
33
|
+
- Use the strict compiler's numeric/nullability join rules when validating
|
|
34
|
+
project-source conditional branches, and make nested-lambda shadowing
|
|
35
|
+
diagnostics independent of whether an outer value was captured earlier.
|
|
36
|
+
|
|
3
37
|
## [0.32.4] - 2026-08-18
|
|
4
38
|
|
|
5
39
|
### Fixed
|
package/dist/neo.mjs
CHANGED
|
@@ -6467,12 +6467,26 @@ function makeBinary(op, left, right, pos) {
|
|
|
6467
6467
|
return { kind: "binary", op, left, right, pos };
|
|
6468
6468
|
}
|
|
6469
6469
|
function asASTBinaryOp(text) {
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6470
|
+
switch (text) {
|
|
6471
|
+
case "+":
|
|
6472
|
+
case "-":
|
|
6473
|
+
case "*":
|
|
6474
|
+
case "/":
|
|
6475
|
+
case "%":
|
|
6476
|
+
case "==":
|
|
6477
|
+
case "!=":
|
|
6478
|
+
case "<":
|
|
6479
|
+
case ">":
|
|
6480
|
+
case "<=":
|
|
6481
|
+
case ">=":
|
|
6482
|
+
case "&&":
|
|
6483
|
+
case "||":
|
|
6484
|
+
return text;
|
|
6485
|
+
default:
|
|
6486
|
+
throw new Error(
|
|
6487
|
+
`Internal compiler error: '${text}' is not a valid ASTBinaryOp`
|
|
6488
|
+
);
|
|
6474
6489
|
}
|
|
6475
|
-
return text;
|
|
6476
6490
|
}
|
|
6477
6491
|
function isAssignmentOp(token) {
|
|
6478
6492
|
return token.kind === "op" && (token.text === "=" || token.text === "+=" || token.text === "-=" || token.text === "*=" || token.text === "/=" || token.text === "%=");
|
|
@@ -6488,7 +6502,7 @@ function describeToken(t) {
|
|
|
6488
6502
|
if (t.kind === "eof") return "end of input";
|
|
6489
6503
|
return `'${t.text}'`;
|
|
6490
6504
|
}
|
|
6491
|
-
var Parser
|
|
6505
|
+
var Parser;
|
|
6492
6506
|
var init_strict_parser = __esm({
|
|
6493
6507
|
"../packages/neoscript-language/src/strict-parser.ts"() {
|
|
6494
6508
|
"use strict";
|
|
@@ -6979,7 +6993,7 @@ var init_strict_parser = __esm({
|
|
|
6979
6993
|
// Types
|
|
6980
6994
|
// ------------------------------------------------------------------
|
|
6981
6995
|
/** Parses a type annotation (used in varDecls and Dictionary generics). */
|
|
6982
|
-
parseType() {
|
|
6996
|
+
parseType(options = {}) {
|
|
6983
6997
|
const startPos = this.peek().pos;
|
|
6984
6998
|
let inner;
|
|
6985
6999
|
const t = this.peek();
|
|
@@ -7045,17 +7059,73 @@ var init_strict_parser = __esm({
|
|
|
7045
7059
|
pos: arrPos
|
|
7046
7060
|
};
|
|
7047
7061
|
}
|
|
7048
|
-
if (this.peek().kind === "op" && this.peek().text === "?") {
|
|
7062
|
+
if (this.peek().kind === "op" && this.peek().text === "?" && !(options.conditionalQuestion === true && this.hasMatchingConditionalColon(this.i))) {
|
|
7049
7063
|
this.next();
|
|
7050
7064
|
inner = { ...inner, required: false };
|
|
7051
7065
|
}
|
|
7052
7066
|
return inner;
|
|
7053
7067
|
}
|
|
7068
|
+
/**
|
|
7069
|
+
* `is T ? a : b` is ambiguous at the token level because `?` is also the
|
|
7070
|
+
* nullable type suffix. A colon at the same delimiter depth makes it the
|
|
7071
|
+
* conditional operator; nested ternaries are paired before the outer colon.
|
|
7072
|
+
*/
|
|
7073
|
+
hasMatchingConditionalColon(questionIndex) {
|
|
7074
|
+
let delimiterDepth2 = 0;
|
|
7075
|
+
let nestedQuestions = 0;
|
|
7076
|
+
for (let index = questionIndex + 1; index < this.tokens.length; index += 1) {
|
|
7077
|
+
const token = this.tokens[index];
|
|
7078
|
+
if (token === void 0) return false;
|
|
7079
|
+
if (token.kind === "punct") {
|
|
7080
|
+
if (token.text === "(" || token.text === "[" || token.text === "{") {
|
|
7081
|
+
delimiterDepth2 += 1;
|
|
7082
|
+
continue;
|
|
7083
|
+
}
|
|
7084
|
+
if (token.text === ")" || token.text === "]" || token.text === "}") {
|
|
7085
|
+
if (delimiterDepth2 === 0) return false;
|
|
7086
|
+
delimiterDepth2 -= 1;
|
|
7087
|
+
continue;
|
|
7088
|
+
}
|
|
7089
|
+
if (delimiterDepth2 !== 0) continue;
|
|
7090
|
+
if (token.text === ";" || token.text === ",") return false;
|
|
7091
|
+
if (token.text !== ":") continue;
|
|
7092
|
+
if (nestedQuestions === 0) return true;
|
|
7093
|
+
nestedQuestions -= 1;
|
|
7094
|
+
continue;
|
|
7095
|
+
}
|
|
7096
|
+
if (delimiterDepth2 === 0 && token.kind === "op" && token.text === "?") {
|
|
7097
|
+
nestedQuestions += 1;
|
|
7098
|
+
}
|
|
7099
|
+
}
|
|
7100
|
+
return false;
|
|
7101
|
+
}
|
|
7054
7102
|
// ------------------------------------------------------------------
|
|
7055
7103
|
// Expressions — climbing precedence (lowest first)
|
|
7056
7104
|
// ------------------------------------------------------------------
|
|
7057
7105
|
parseExpr() {
|
|
7058
|
-
return this.
|
|
7106
|
+
return this.parseConditional();
|
|
7107
|
+
}
|
|
7108
|
+
/**
|
|
7109
|
+
* Conditional `condition ? whenTrue : whenFalse`. This is the lowest
|
|
7110
|
+
* precedence expression operator and is right-associative, matching the
|
|
7111
|
+
* familiar C#/TypeScript reading of nested ternaries.
|
|
7112
|
+
*/
|
|
7113
|
+
parseConditional() {
|
|
7114
|
+
const condition = this.parseCoalesce();
|
|
7115
|
+
if (!(this.peek().kind === "op" && this.peek().text === "?")) {
|
|
7116
|
+
return condition;
|
|
7117
|
+
}
|
|
7118
|
+
const question = this.next();
|
|
7119
|
+
const whenTrue = this.parseExpr();
|
|
7120
|
+
this.expect("punct", ":");
|
|
7121
|
+
const whenFalse = this.parseConditional();
|
|
7122
|
+
return {
|
|
7123
|
+
kind: "conditional",
|
|
7124
|
+
condition,
|
|
7125
|
+
whenTrue,
|
|
7126
|
+
whenFalse,
|
|
7127
|
+
pos: question.pos
|
|
7128
|
+
};
|
|
7059
7129
|
}
|
|
7060
7130
|
/**
|
|
7061
7131
|
* Null-coalesce `lhs ?? rhs`. Lower precedence than `||` / `&&` so
|
|
@@ -7103,7 +7173,7 @@ var init_strict_parser = __esm({
|
|
|
7103
7173
|
}
|
|
7104
7174
|
if (t.kind === "keyword" && t.text === "is") {
|
|
7105
7175
|
this.next();
|
|
7106
|
-
const type = this.parseType();
|
|
7176
|
+
const type = this.parseType({ conditionalQuestion: true });
|
|
7107
7177
|
const bindingName = this.peek().kind === "ident" ? this.next().text : null;
|
|
7108
7178
|
left = { kind: "is", operand: left, type, bindingName, pos: t.pos };
|
|
7109
7179
|
continue;
|
|
@@ -7538,13 +7608,8 @@ var init_strict_parser = __esm({
|
|
|
7538
7608
|
*/
|
|
7539
7609
|
parseLambdaParam() {
|
|
7540
7610
|
const startPos = this.peek().pos;
|
|
7541
|
-
const
|
|
7542
|
-
if (
|
|
7543
|
-
const type = this.parseType();
|
|
7544
|
-
const name2 = this.expect("ident");
|
|
7545
|
-
return { type, name: name2.text, pos: startPos };
|
|
7546
|
-
}
|
|
7547
|
-
if (t.kind === "ident" && this.tokens[this.i + 1]?.kind === "ident") {
|
|
7611
|
+
const afterType = this.scanType(this.i);
|
|
7612
|
+
if (afterType !== null && this.tokens[afterType]?.kind === "ident") {
|
|
7548
7613
|
const type = this.parseType();
|
|
7549
7614
|
const name2 = this.expect("ident");
|
|
7550
7615
|
return { type, name: name2.text, pos: startPos };
|
|
@@ -7607,21 +7672,6 @@ var init_strict_parser = __esm({
|
|
|
7607
7672
|
return { kind: "litInterp", parts, pos };
|
|
7608
7673
|
}
|
|
7609
7674
|
};
|
|
7610
|
-
AST_BINARY_OPS = /* @__PURE__ */ new Set([
|
|
7611
|
-
"+",
|
|
7612
|
-
"-",
|
|
7613
|
-
"*",
|
|
7614
|
-
"/",
|
|
7615
|
-
"%",
|
|
7616
|
-
"==",
|
|
7617
|
-
"!=",
|
|
7618
|
-
"<",
|
|
7619
|
-
">",
|
|
7620
|
-
"<=",
|
|
7621
|
-
">=",
|
|
7622
|
-
"&&",
|
|
7623
|
-
"||"
|
|
7624
|
-
]);
|
|
7625
7675
|
}
|
|
7626
7676
|
});
|
|
7627
7677
|
|
|
@@ -8225,7 +8275,7 @@ var NEOSCRIPT_COMPILER_REVISION;
|
|
|
8225
8275
|
var init_strict_ir = __esm({
|
|
8226
8276
|
"../packages/neoscript-language/src/strict-ir.ts"() {
|
|
8227
8277
|
"use strict";
|
|
8228
|
-
NEOSCRIPT_COMPILER_REVISION =
|
|
8278
|
+
NEOSCRIPT_COMPILER_REVISION = 12;
|
|
8229
8279
|
}
|
|
8230
8280
|
});
|
|
8231
8281
|
|
|
@@ -8628,6 +8678,11 @@ function collectAssignedPathRootsInExpression(expression, roots) {
|
|
|
8628
8678
|
collectAssignedPathRootsInExpression(expression.left, roots);
|
|
8629
8679
|
collectAssignedPathRootsInExpression(expression.right, roots);
|
|
8630
8680
|
return;
|
|
8681
|
+
case "conditional":
|
|
8682
|
+
collectAssignedPathRootsInExpression(expression.condition, roots);
|
|
8683
|
+
collectAssignedPathRootsInExpression(expression.whenTrue, roots);
|
|
8684
|
+
collectAssignedPathRootsInExpression(expression.whenFalse, roots);
|
|
8685
|
+
return;
|
|
8631
8686
|
case "unary":
|
|
8632
8687
|
case "force":
|
|
8633
8688
|
collectAssignedPathRootsInExpression(expression.operand, roots);
|
|
@@ -9515,6 +9570,7 @@ var init_strict_resolver = __esm({
|
|
|
9515
9570
|
this.context = context;
|
|
9516
9571
|
this.source = source;
|
|
9517
9572
|
this.project = projectIndex ?? createProjectIndex(context.project);
|
|
9573
|
+
this.sourceTokens = source === void 0 ? void 0 : lex2(source);
|
|
9518
9574
|
const unknown = { kind: "primitive", name: "unknown" };
|
|
9519
9575
|
this.thisVariable = variable(
|
|
9520
9576
|
"__this__",
|
|
@@ -9560,6 +9616,9 @@ var init_strict_resolver = __esm({
|
|
|
9560
9616
|
argumentVariables;
|
|
9561
9617
|
callSiteCounter = 0;
|
|
9562
9618
|
lambdaDepth = 0;
|
|
9619
|
+
delegateClosureCounter = 0;
|
|
9620
|
+
delegateCaptureContexts = [];
|
|
9621
|
+
sourceTokens;
|
|
9563
9622
|
unreachableControlEffectDepth = 0;
|
|
9564
9623
|
catchBindingCounter = 0;
|
|
9565
9624
|
catchContexts = [];
|
|
@@ -10276,6 +10335,12 @@ var init_strict_resolver = __esm({
|
|
|
10276
10335
|
case "assign":
|
|
10277
10336
|
return this.resolveAssignment(statement, scope);
|
|
10278
10337
|
case "exprStmt": {
|
|
10338
|
+
const actionClear = this.resolveActionClear(
|
|
10339
|
+
statement.expr,
|
|
10340
|
+
scope,
|
|
10341
|
+
statement.pos
|
|
10342
|
+
);
|
|
10343
|
+
if (actionClear) return actionClear;
|
|
10279
10344
|
const collectionCall = this.resolveCollectionMutation(
|
|
10280
10345
|
statement.expr,
|
|
10281
10346
|
scope,
|
|
@@ -10420,7 +10485,10 @@ var init_strict_resolver = __esm({
|
|
|
10420
10485
|
pos
|
|
10421
10486
|
);
|
|
10422
10487
|
}
|
|
10423
|
-
|
|
10488
|
+
const usedInLexicalOuter = this.delegateCaptureContexts.some(
|
|
10489
|
+
(context) => context.outerScope.lookup(name) !== null
|
|
10490
|
+
);
|
|
10491
|
+
if (!scope.lookup(name) && !usedInLexicalOuter) return;
|
|
10424
10492
|
throw new CompileError(
|
|
10425
10493
|
`Cannot declare local '${name}' because that name is already used in an enclosing or current scope.`,
|
|
10426
10494
|
pos
|
|
@@ -10579,7 +10647,9 @@ var init_strict_resolver = __esm({
|
|
|
10579
10647
|
}
|
|
10580
10648
|
const local = statement.target.kind === "ident" ? scope.lookup(statement.target.name) : null;
|
|
10581
10649
|
if (local?.readonlyBinding) {
|
|
10582
|
-
|
|
10650
|
+
let label = "foreach iterator";
|
|
10651
|
+
if (local.readonlyBinding === "catch") label = "catch parameter";
|
|
10652
|
+
if (local.readonlyBinding === "capture") label = "captured value";
|
|
10583
10653
|
throw new CompileError(
|
|
10584
10654
|
`Cannot assign to ${label} '${local.name}' because it is read-only.`,
|
|
10585
10655
|
statement.pos
|
|
@@ -11179,6 +11249,8 @@ var init_strict_resolver = __esm({
|
|
|
11179
11249
|
type: resultType
|
|
11180
11250
|
};
|
|
11181
11251
|
}
|
|
11252
|
+
case "conditional":
|
|
11253
|
+
return this.resolveConditionalExpression(expression, scope, expected);
|
|
11182
11254
|
case "is": {
|
|
11183
11255
|
const operand = this.resolveExpression(expression.operand, scope);
|
|
11184
11256
|
const check = this.resolveType(expression.type);
|
|
@@ -11223,19 +11295,40 @@ var init_strict_resolver = __esm({
|
|
|
11223
11295
|
ast.pos
|
|
11224
11296
|
);
|
|
11225
11297
|
}
|
|
11226
|
-
const
|
|
11298
|
+
const serial = this.delegateClosureCounter++;
|
|
11299
|
+
const scope = new Scope(null);
|
|
11300
|
+
scope.define(
|
|
11301
|
+
scopeVariable(
|
|
11302
|
+
"this",
|
|
11303
|
+
this.thisVariable,
|
|
11304
|
+
this.context.thisClass,
|
|
11305
|
+
void 0,
|
|
11306
|
+
"runtime" /* Runtime */
|
|
11307
|
+
)
|
|
11308
|
+
);
|
|
11309
|
+
const rootSymbol = this.context.project.roots.find(
|
|
11310
|
+
(candidate) => candidate.name === "root"
|
|
11311
|
+
);
|
|
11312
|
+
scope.define(scopeVariable("root", this.rootVariable, rootSymbol?.type));
|
|
11227
11313
|
const parameters = ast.params.map((parameter4, index) => {
|
|
11314
|
+
this.assertLocalNameAvailable(parameter4.name, outerScope, parameter4.pos);
|
|
11228
11315
|
this.assertLocalNameAvailable(parameter4.name, scope, parameter4.pos);
|
|
11229
11316
|
const expectedType = requiredAt(expected.parameterTypes, index);
|
|
11230
11317
|
const declared = parameter4.type ? this.resolveType(parameter4.type) : expectedType;
|
|
11231
|
-
if (!isNeoScriptTypeAssignable(declared, expectedType, this.project)
|
|
11318
|
+
if (!isNeoScriptTypeAssignable(declared, expectedType, this.project)) {
|
|
11319
|
+
throw new CompileError(
|
|
11320
|
+
`Delegate lambda parameter ${index + 1} type ${this.describe(declared)} is not assignable to ${this.describe(expectedType)}.`,
|
|
11321
|
+
parameter4.pos
|
|
11322
|
+
);
|
|
11323
|
+
}
|
|
11324
|
+
if (!isNeoScriptTypeAssignable(expectedType, declared, this.project)) {
|
|
11232
11325
|
throw new CompileError(
|
|
11233
|
-
`Delegate lambda parameter ${index + 1}
|
|
11326
|
+
`Delegate lambda parameter ${index + 1} type ${this.describe(declared)} is broader than the declared delegate parameter ${this.describe(expectedType)}.`,
|
|
11234
11327
|
parameter4.pos
|
|
11235
11328
|
);
|
|
11236
11329
|
}
|
|
11237
11330
|
const item = variable(
|
|
11238
|
-
`
|
|
11331
|
+
`__lambda_${serial}_arg_${index}__`,
|
|
11239
11332
|
declared,
|
|
11240
11333
|
void 0,
|
|
11241
11334
|
this.project
|
|
@@ -11251,6 +11344,14 @@ var init_strict_resolver = __esm({
|
|
|
11251
11344
|
);
|
|
11252
11345
|
return item;
|
|
11253
11346
|
});
|
|
11347
|
+
const captureContext = {
|
|
11348
|
+
outerScope,
|
|
11349
|
+
closureScope: scope,
|
|
11350
|
+
serial,
|
|
11351
|
+
captures: [],
|
|
11352
|
+
byOuterEntry: /* @__PURE__ */ new Map()
|
|
11353
|
+
};
|
|
11354
|
+
this.delegateCaptureContexts.push(captureContext);
|
|
11254
11355
|
this.functionControlBoundaries.push({
|
|
11255
11356
|
controlDepth: this.controlContexts.length,
|
|
11256
11357
|
loopFlowDepth: this.loopFlowContexts.length,
|
|
@@ -11269,11 +11370,34 @@ var init_strict_resolver = __esm({
|
|
|
11269
11370
|
}
|
|
11270
11371
|
const action = {
|
|
11271
11372
|
compilerRevision: NEOSCRIPT_COMPILER_REVISION,
|
|
11272
|
-
parameters: [
|
|
11373
|
+
parameters: [
|
|
11374
|
+
this.thisVariable,
|
|
11375
|
+
this.rootVariable,
|
|
11376
|
+
...parameters,
|
|
11377
|
+
...captureContext.captures.map((capture) => capture.parameter)
|
|
11378
|
+
],
|
|
11273
11379
|
instructions,
|
|
11274
11380
|
typeInfo: returnsVoid ? toWireType({ kind: "primitive", name: "null" }, this.project) : toWireType(expected.returnType, this.project)
|
|
11275
11381
|
};
|
|
11276
11382
|
const code = this.delegateLambdaSource(ast);
|
|
11383
|
+
if (captureContext.captures.length > 0) {
|
|
11384
|
+
const typeInfo = toWireType(expected, this.project);
|
|
11385
|
+
if (typeInfo.type !== 25 /* Delegate */) {
|
|
11386
|
+
throw new Error(
|
|
11387
|
+
"NeoScript delegate closure lowered with non-delegate type info."
|
|
11388
|
+
);
|
|
11389
|
+
}
|
|
11390
|
+
return {
|
|
11391
|
+
pointer: {
|
|
11392
|
+
type: "delegateClosure" /* DelegateClosure */,
|
|
11393
|
+
typeInfo,
|
|
11394
|
+
action,
|
|
11395
|
+
captures: captureContext.captures.map((capture) => capture.source),
|
|
11396
|
+
...code === void 0 ? {} : { code }
|
|
11397
|
+
},
|
|
11398
|
+
type: expected
|
|
11399
|
+
};
|
|
11400
|
+
}
|
|
11277
11401
|
return literal(
|
|
11278
11402
|
expected,
|
|
11279
11403
|
code === void 0 ? { action } : { code, action },
|
|
@@ -11283,11 +11407,14 @@ var init_strict_resolver = __esm({
|
|
|
11283
11407
|
this.expectedReturnStack.pop();
|
|
11284
11408
|
this.lambdaDepth--;
|
|
11285
11409
|
this.functionControlBoundaries.pop();
|
|
11410
|
+
this.delegateCaptureContexts.pop();
|
|
11286
11411
|
}
|
|
11287
11412
|
}
|
|
11288
11413
|
delegateLambdaSource(ast) {
|
|
11289
|
-
if (this.source === void 0
|
|
11290
|
-
|
|
11414
|
+
if (this.source === void 0 || this.sourceTokens === void 0) {
|
|
11415
|
+
return void 0;
|
|
11416
|
+
}
|
|
11417
|
+
const tokens = this.sourceTokens;
|
|
11291
11418
|
const startIndex = tokens.findIndex(
|
|
11292
11419
|
(token) => token.pos.line === ast.pos.line && token.pos.column === ast.pos.column
|
|
11293
11420
|
);
|
|
@@ -11606,7 +11733,7 @@ var init_strict_resolver = __esm({
|
|
|
11606
11733
|
};
|
|
11607
11734
|
}
|
|
11608
11735
|
resolveIdentifier(name, scope, pos) {
|
|
11609
|
-
const entry = scope.lookup(name);
|
|
11736
|
+
const entry = scope.lookup(name) ?? this.captureDelegateOuterBinding(name);
|
|
11610
11737
|
if (entry) {
|
|
11611
11738
|
const ownership = scope.ownership(entry) ?? entry.writability;
|
|
11612
11739
|
return {
|
|
@@ -11659,6 +11786,52 @@ var init_strict_resolver = __esm({
|
|
|
11659
11786
|
}
|
|
11660
11787
|
throw new CompileError(`Unknown identifier '${name}'`, pos);
|
|
11661
11788
|
}
|
|
11789
|
+
/**
|
|
11790
|
+
* Materializes one free delegate-lambda binding as an explicit trailing
|
|
11791
|
+
* action parameter. The pointer stored beside it is evaluated once at the
|
|
11792
|
+
* lambda expression site, giving NeoScript deterministic by-value capture
|
|
11793
|
+
* semantics that survive return, assignment, and persistence.
|
|
11794
|
+
*/
|
|
11795
|
+
captureDelegateOuterBinding(name) {
|
|
11796
|
+
const context = this.delegateCaptureContexts.at(-1);
|
|
11797
|
+
if (context === void 0) return null;
|
|
11798
|
+
let outerEntry = context.outerScope.lookup(name);
|
|
11799
|
+
if (outerEntry === null && this.delegateCaptureContexts.length > 1) {
|
|
11800
|
+
const current = this.delegateCaptureContexts.pop();
|
|
11801
|
+
try {
|
|
11802
|
+
this.captureDelegateOuterBinding(name);
|
|
11803
|
+
} finally {
|
|
11804
|
+
if (current !== void 0) this.delegateCaptureContexts.push(current);
|
|
11805
|
+
}
|
|
11806
|
+
outerEntry = context.outerScope.lookup(name);
|
|
11807
|
+
}
|
|
11808
|
+
if (outerEntry === null) return null;
|
|
11809
|
+
const existing = context.byOuterEntry.get(outerEntry);
|
|
11810
|
+
if (existing !== void 0) return existing;
|
|
11811
|
+
const parameter4 = variable(
|
|
11812
|
+
`__capture_${context.serial}_${context.captures.length}__`,
|
|
11813
|
+
outerEntry.type,
|
|
11814
|
+
void 0,
|
|
11815
|
+
this.project
|
|
11816
|
+
);
|
|
11817
|
+
const entry = scopeVariable(
|
|
11818
|
+
name,
|
|
11819
|
+
parameter4,
|
|
11820
|
+
outerEntry.type,
|
|
11821
|
+
"local" /* Local */,
|
|
11822
|
+
"local" /* Local */,
|
|
11823
|
+
outerEntry.writeRoot,
|
|
11824
|
+
"capture"
|
|
11825
|
+
);
|
|
11826
|
+
const source = outerEntry.pointer ?? {
|
|
11827
|
+
type: "variable" /* Variable */,
|
|
11828
|
+
variableId: outerEntry.variableId
|
|
11829
|
+
};
|
|
11830
|
+
context.byOuterEntry.set(outerEntry, entry);
|
|
11831
|
+
context.captures.push({ outerEntry, source, parameter: parameter4, entry });
|
|
11832
|
+
context.closureScope.define(entry);
|
|
11833
|
+
return entry;
|
|
11834
|
+
}
|
|
11662
11835
|
resolveContextualEnum(optionName, expected, pos) {
|
|
11663
11836
|
if (!expected || expected.kind !== "named") {
|
|
11664
11837
|
throw new CompileError(
|
|
@@ -12838,6 +13011,37 @@ var init_strict_resolver = __esm({
|
|
|
12838
13011
|
);
|
|
12839
13012
|
}
|
|
12840
13013
|
const memberReceiverType = neoScriptMemberLookupType(receiver.type);
|
|
13014
|
+
if (callee.name === "Equals" && memberReceiverType.kind === "typeParameter") {
|
|
13015
|
+
if (optional) {
|
|
13016
|
+
throw new CompileError(
|
|
13017
|
+
"Equals cannot be optional-chained on a generic receiver; narrow it with a null check first.",
|
|
13018
|
+
pos
|
|
13019
|
+
);
|
|
13020
|
+
}
|
|
13021
|
+
if (isNullable(receiver.type)) {
|
|
13022
|
+
throw new CompileError(
|
|
13023
|
+
"Equals cannot be called on an optional generic receiver; narrow it with a null check first.",
|
|
13024
|
+
pos
|
|
13025
|
+
);
|
|
13026
|
+
}
|
|
13027
|
+
requireArgCount("Equals", argumentsList2, 1, pos);
|
|
13028
|
+
const other = this.resolveExpression(
|
|
13029
|
+
requiredAt(argumentsList2, 0),
|
|
13030
|
+
scope,
|
|
13031
|
+
{ ...memberReceiverType, nullable: true }
|
|
13032
|
+
);
|
|
13033
|
+
return {
|
|
13034
|
+
pointer: {
|
|
13035
|
+
type: "callFunction" /* CallFunction */,
|
|
13036
|
+
memberKey: "Equals",
|
|
13037
|
+
receiver: { kind: "instance", pointer: receiver.pointer },
|
|
13038
|
+
args: [other.pointer],
|
|
13039
|
+
missingMemberFallback: "valueEquality",
|
|
13040
|
+
callSiteId: this.nextCallSite(pos)
|
|
13041
|
+
},
|
|
13042
|
+
type: { kind: "primitive", name: "bool" }
|
|
13043
|
+
};
|
|
13044
|
+
}
|
|
12841
13045
|
if (memberReceiverType.kind === "named") {
|
|
12842
13046
|
const type = this.project.typeById.get(memberReceiverType.typeId);
|
|
12843
13047
|
const member = type?.members.find(
|
|
@@ -14434,6 +14638,159 @@ var init_strict_resolver = __esm({
|
|
|
14434
14638
|
args
|
|
14435
14639
|
};
|
|
14436
14640
|
}
|
|
14641
|
+
/**
|
|
14642
|
+
* `NeoAction.Clear()` resets the stored listener set. It lowers to an
|
|
14643
|
+
* ordinary whole-member assignment so every existing write host observes
|
|
14644
|
+
* the same overlay and write-intent contract as `+=` / `-=`.
|
|
14645
|
+
*/
|
|
14646
|
+
resolveActionClear(expression, scope, pos) {
|
|
14647
|
+
if (expression.kind !== "call" || expression.callee.kind !== "member" || expression.callee.name !== "Clear") {
|
|
14648
|
+
return null;
|
|
14649
|
+
}
|
|
14650
|
+
const receiver = this.resolveExpression(expression.callee.receiver, scope);
|
|
14651
|
+
if (receiver.type.kind !== "action") return null;
|
|
14652
|
+
if (expression.callee.optional) {
|
|
14653
|
+
throw new CompileError(
|
|
14654
|
+
`${this.describe(receiver.type)} is never null, so optional-chained Clear is not supported.`,
|
|
14655
|
+
pos
|
|
14656
|
+
);
|
|
14657
|
+
}
|
|
14658
|
+
requireArgCount("Clear", expression.args, 0, pos);
|
|
14659
|
+
if (!isActionMemberPointer(receiver.pointer)) {
|
|
14660
|
+
throw new CompileError(
|
|
14661
|
+
`Cannot clear ${this.describe(receiver.type)} that is not a member reference; an action is not a value. Clear it through the member reference directly.`,
|
|
14662
|
+
pos
|
|
14663
|
+
);
|
|
14664
|
+
}
|
|
14665
|
+
if (receiver.symbol?.computed === true) {
|
|
14666
|
+
throw new CompileError(
|
|
14667
|
+
`Cannot clear NeoScript property '${receiver.symbol.name}'; an action listener set must be stored data.`,
|
|
14668
|
+
pos
|
|
14669
|
+
);
|
|
14670
|
+
}
|
|
14671
|
+
const writability = receiver.writability;
|
|
14672
|
+
if (writability === "immutable" /* Immutable */) {
|
|
14673
|
+
throw new CompileError(
|
|
14674
|
+
"Cannot clear an action whose effective storage is immutable.",
|
|
14675
|
+
pos
|
|
14676
|
+
);
|
|
14677
|
+
}
|
|
14678
|
+
if (!writability) {
|
|
14679
|
+
throw new CompileError(
|
|
14680
|
+
"Cannot clear an action whose member writability could not be resolved.",
|
|
14681
|
+
pos
|
|
14682
|
+
);
|
|
14683
|
+
}
|
|
14684
|
+
if (writability === "readOnly" /* ReadOnly */) {
|
|
14685
|
+
throw new CompileError("Cannot clear a read-only action.", pos);
|
|
14686
|
+
}
|
|
14687
|
+
this.validateConstructorWriteTarget(
|
|
14688
|
+
receiver.pointer,
|
|
14689
|
+
"mutate",
|
|
14690
|
+
pos,
|
|
14691
|
+
scope,
|
|
14692
|
+
true
|
|
14693
|
+
);
|
|
14694
|
+
const path = canonicalPath(expression.callee.receiver);
|
|
14695
|
+
if (path) {
|
|
14696
|
+
const rootEntry = scope.lookup(pathRoot(path));
|
|
14697
|
+
if (rootEntry) scope.invalidate(rootEntry);
|
|
14698
|
+
}
|
|
14699
|
+
const actionTypeInfo = receiver.wireType ?? toWireType(receiver.type, this.project);
|
|
14700
|
+
return {
|
|
14701
|
+
type: "assign" /* Assign */,
|
|
14702
|
+
target: {
|
|
14703
|
+
pointer: receiver.pointer,
|
|
14704
|
+
typeInfo: actionTypeInfo,
|
|
14705
|
+
writability
|
|
14706
|
+
},
|
|
14707
|
+
operator: "=" /* Assign */,
|
|
14708
|
+
pointer: {
|
|
14709
|
+
type: "value" /* Value */,
|
|
14710
|
+
value: { typeInfo: actionTypeInfo, value: { listeners: [] } }
|
|
14711
|
+
}
|
|
14712
|
+
};
|
|
14713
|
+
}
|
|
14714
|
+
resolveConditionalExpression(expression, scope, expected) {
|
|
14715
|
+
const condition = this.toBool(
|
|
14716
|
+
this.resolveExpression(expression.condition, scope),
|
|
14717
|
+
expression.condition.pos
|
|
14718
|
+
);
|
|
14719
|
+
const trueScope = new Scope(scope);
|
|
14720
|
+
this.applyFactsToScope(
|
|
14721
|
+
scope,
|
|
14722
|
+
trueScope,
|
|
14723
|
+
factsWhenTrue(expression.condition)
|
|
14724
|
+
);
|
|
14725
|
+
const falseScope = new Scope(scope);
|
|
14726
|
+
this.applyFactsToScope(
|
|
14727
|
+
scope,
|
|
14728
|
+
falseScope,
|
|
14729
|
+
factsWhenFalse(expression.condition)
|
|
14730
|
+
);
|
|
14731
|
+
let whenTrue;
|
|
14732
|
+
let whenFalse;
|
|
14733
|
+
if (expected) {
|
|
14734
|
+
whenTrue = this.resolveExpression(
|
|
14735
|
+
expression.whenTrue,
|
|
14736
|
+
trueScope,
|
|
14737
|
+
expected
|
|
14738
|
+
);
|
|
14739
|
+
whenFalse = this.resolveExpression(
|
|
14740
|
+
expression.whenFalse,
|
|
14741
|
+
falseScope,
|
|
14742
|
+
expected
|
|
14743
|
+
);
|
|
14744
|
+
} else if (expression.whenTrue.kind === "litNull" || expression.whenTrue.kind === "contextualEnum") {
|
|
14745
|
+
whenFalse = this.resolveExpression(expression.whenFalse, falseScope);
|
|
14746
|
+
whenTrue = this.resolveExpression(expression.whenTrue, trueScope, {
|
|
14747
|
+
...whenFalse.type,
|
|
14748
|
+
nullable: true
|
|
14749
|
+
});
|
|
14750
|
+
} else {
|
|
14751
|
+
whenTrue = this.resolveExpression(expression.whenTrue, trueScope);
|
|
14752
|
+
whenFalse = this.resolveExpression(
|
|
14753
|
+
expression.whenFalse,
|
|
14754
|
+
falseScope,
|
|
14755
|
+
expression.whenFalse.kind === "litNull" ? { ...whenTrue.type, nullable: true } : whenTrue.type
|
|
14756
|
+
);
|
|
14757
|
+
}
|
|
14758
|
+
const common = commonNeoScriptAssignableType(
|
|
14759
|
+
whenTrue.type,
|
|
14760
|
+
whenFalse.type,
|
|
14761
|
+
this.project
|
|
14762
|
+
);
|
|
14763
|
+
const resultType = common ?? (expected && isNeoScriptTypeAssignable(whenTrue.type, expected, this.project) && isNeoScriptTypeAssignable(whenFalse.type, expected, this.project) ? expected : null);
|
|
14764
|
+
if (!resultType) {
|
|
14765
|
+
throw new CompileError(
|
|
14766
|
+
`Conditional branches ${this.describe(whenTrue.type)} and ${this.describe(whenFalse.type)} do not have a common assignable type.`,
|
|
14767
|
+
expression.pos
|
|
14768
|
+
);
|
|
14769
|
+
}
|
|
14770
|
+
if (expected) {
|
|
14771
|
+
this.requireAssignable(
|
|
14772
|
+
whenTrue.type,
|
|
14773
|
+
expected,
|
|
14774
|
+
expression.whenTrue.pos,
|
|
14775
|
+
"conditional true branch"
|
|
14776
|
+
);
|
|
14777
|
+
this.requireAssignable(
|
|
14778
|
+
whenFalse.type,
|
|
14779
|
+
expected,
|
|
14780
|
+
expression.whenFalse.pos,
|
|
14781
|
+
"conditional false branch"
|
|
14782
|
+
);
|
|
14783
|
+
}
|
|
14784
|
+
return {
|
|
14785
|
+
pointer: {
|
|
14786
|
+
type: "conditional" /* Conditional */,
|
|
14787
|
+
condition: condition.pointer,
|
|
14788
|
+
whenTrue: whenTrue.pointer,
|
|
14789
|
+
whenFalse: whenFalse.pointer
|
|
14790
|
+
},
|
|
14791
|
+
type: resultType
|
|
14792
|
+
};
|
|
14793
|
+
}
|
|
14437
14794
|
resolveBinary(expression, scope) {
|
|
14438
14795
|
let left;
|
|
14439
14796
|
let preResolvedRight;
|
|
@@ -14646,6 +15003,15 @@ var init_strict_resolver = __esm({
|
|
|
14646
15003
|
type.pos
|
|
14647
15004
|
);
|
|
14648
15005
|
}
|
|
15006
|
+
const declaringTypeRef = this.context.declaringType ?? this.context.thisClass;
|
|
15007
|
+
const declaringType = declaringTypeRef?.kind === "named" ? this.project.typeById.get(declaringTypeRef.typeId) : void 0;
|
|
15008
|
+
const typeParameter2 = declaringType?.typeParameters?.find(
|
|
15009
|
+
(candidate) => candidate.name === type.name
|
|
15010
|
+
);
|
|
15011
|
+
if (typeParameter2?.type.kind === "typeParameter") {
|
|
15012
|
+
resolved = typeParameter2.type;
|
|
15013
|
+
break;
|
|
15014
|
+
}
|
|
14649
15015
|
const builtin = namedPrimitive(type.name);
|
|
14650
15016
|
if (builtin) {
|
|
14651
15017
|
resolved = { kind: "primitive", name: builtin };
|
|
@@ -22148,6 +22514,11 @@ function collectIdentifierReads(expression, names) {
|
|
|
22148
22514
|
walk(node.left, visible);
|
|
22149
22515
|
walk(node.right, visible);
|
|
22150
22516
|
return;
|
|
22517
|
+
case "conditional":
|
|
22518
|
+
walk(node.condition, visible);
|
|
22519
|
+
walk(node.whenTrue, visible);
|
|
22520
|
+
walk(node.whenFalse, visible);
|
|
22521
|
+
return;
|
|
22151
22522
|
case "unary":
|
|
22152
22523
|
case "force":
|
|
22153
22524
|
case "is":
|
|
@@ -23185,6 +23556,50 @@ function validateExpression(expression, expected, scope, environment, uri, range
|
|
|
23185
23556
|
);
|
|
23186
23557
|
return;
|
|
23187
23558
|
}
|
|
23559
|
+
if (expression.kind === "conditional") {
|
|
23560
|
+
validateExpression(
|
|
23561
|
+
expression.condition,
|
|
23562
|
+
primitiveType("bool"),
|
|
23563
|
+
scope,
|
|
23564
|
+
environment,
|
|
23565
|
+
uri,
|
|
23566
|
+
range2,
|
|
23567
|
+
diagnostics,
|
|
23568
|
+
anchor
|
|
23569
|
+
);
|
|
23570
|
+
const trueType = inferExpressionType2(
|
|
23571
|
+
expression.whenTrue,
|
|
23572
|
+
scope,
|
|
23573
|
+
environment
|
|
23574
|
+
);
|
|
23575
|
+
const falseType = inferExpressionType2(
|
|
23576
|
+
expression.whenFalse,
|
|
23577
|
+
scope,
|
|
23578
|
+
environment
|
|
23579
|
+
);
|
|
23580
|
+
const branchType = expected ?? commonSemanticAssignableType(trueType, falseType);
|
|
23581
|
+
validateExpression(
|
|
23582
|
+
expression.whenTrue,
|
|
23583
|
+
branchType,
|
|
23584
|
+
scope,
|
|
23585
|
+
environment,
|
|
23586
|
+
uri,
|
|
23587
|
+
range2,
|
|
23588
|
+
diagnostics,
|
|
23589
|
+
anchor
|
|
23590
|
+
);
|
|
23591
|
+
validateExpression(
|
|
23592
|
+
expression.whenFalse,
|
|
23593
|
+
branchType,
|
|
23594
|
+
scope,
|
|
23595
|
+
environment,
|
|
23596
|
+
uri,
|
|
23597
|
+
range2,
|
|
23598
|
+
diagnostics,
|
|
23599
|
+
anchor
|
|
23600
|
+
);
|
|
23601
|
+
return;
|
|
23602
|
+
}
|
|
23188
23603
|
if (expression.kind === "new") {
|
|
23189
23604
|
const typeName = expression.className ?? expected?.name;
|
|
23190
23605
|
const declaration = typeName ? environment.types.get(typeName) : void 0;
|
|
@@ -23493,13 +23908,19 @@ function substituteSemanticType(type, bindings) {
|
|
|
23493
23908
|
return { ...type, arguments: argumentsList2 };
|
|
23494
23909
|
}
|
|
23495
23910
|
function semanticTypesAssignable(actual, expected) {
|
|
23496
|
-
if (actual.name ===
|
|
23911
|
+
if (actual.name === "null") {
|
|
23912
|
+
return expected.name === "null" || expected.nullable === true;
|
|
23913
|
+
}
|
|
23914
|
+
if (expected.name === "null") return false;
|
|
23915
|
+
if (actual.name === expected.name) {
|
|
23916
|
+
return actual.nullable !== true || expected.nullable === true;
|
|
23917
|
+
}
|
|
23497
23918
|
if (actual.name === "void") return false;
|
|
23498
23919
|
if (actual.name === "int" && (expected.name === "float" || expected.name === "decimal")) {
|
|
23499
|
-
return true;
|
|
23920
|
+
return actual.nullable !== true || expected.nullable === true;
|
|
23500
23921
|
}
|
|
23501
23922
|
if (actual.name === "float" && expected.name === "decimal") {
|
|
23502
|
-
return true;
|
|
23923
|
+
return actual.nullable !== true || expected.nullable === true;
|
|
23503
23924
|
}
|
|
23504
23925
|
if (Object.prototype.hasOwnProperty.call(
|
|
23505
23926
|
NEO_PROJECT_SOURCE_RECORD_CONTRACT.enums,
|
|
@@ -23507,12 +23928,42 @@ function semanticTypesAssignable(actual, expected) {
|
|
|
23507
23928
|
)) {
|
|
23508
23929
|
return false;
|
|
23509
23930
|
}
|
|
23510
|
-
|
|
23511
|
-
if (primitiveNames.has(expected.name) && primitiveNames.has(actual.name)) {
|
|
23931
|
+
if (SEMANTIC_PRIMITIVE_TYPE_NAMES.has(expected.name) && SEMANTIC_PRIMITIVE_TYPE_NAMES.has(actual.name)) {
|
|
23512
23932
|
return false;
|
|
23513
23933
|
}
|
|
23514
23934
|
return true;
|
|
23515
23935
|
}
|
|
23936
|
+
function commonSemanticAssignableType(left, right) {
|
|
23937
|
+
if (left === void 0) return right;
|
|
23938
|
+
if (right === void 0) return left;
|
|
23939
|
+
if (left.name === "null" && right.name === "null") return left;
|
|
23940
|
+
if (left.name === "null") return { ...right, nullable: true };
|
|
23941
|
+
if (right.name === "null") return { ...left, nullable: true };
|
|
23942
|
+
if (left.name === right.name) {
|
|
23943
|
+
return {
|
|
23944
|
+
...left,
|
|
23945
|
+
nullable: left.nullable === true || right.nullable === true
|
|
23946
|
+
};
|
|
23947
|
+
}
|
|
23948
|
+
const leftRank = semanticNumericRank(left.name);
|
|
23949
|
+
const rightRank = semanticNumericRank(right.name);
|
|
23950
|
+
if (leftRank !== void 0 && rightRank !== void 0) {
|
|
23951
|
+
const name = leftRank >= rightRank ? left.name : right.name;
|
|
23952
|
+
return {
|
|
23953
|
+
name,
|
|
23954
|
+
nullable: left.nullable === true || right.nullable === true
|
|
23955
|
+
};
|
|
23956
|
+
}
|
|
23957
|
+
if (semanticTypesAssignable(left, right)) return right;
|
|
23958
|
+
if (semanticTypesAssignable(right, left)) return left;
|
|
23959
|
+
return void 0;
|
|
23960
|
+
}
|
|
23961
|
+
function semanticNumericRank(name) {
|
|
23962
|
+
if (name === "int") return 0;
|
|
23963
|
+
if (name === "float") return 1;
|
|
23964
|
+
if (name === "decimal") return 2;
|
|
23965
|
+
return void 0;
|
|
23966
|
+
}
|
|
23516
23967
|
function describeType(type) {
|
|
23517
23968
|
const argumentsList2 = type.arguments?.length ? `<${type.arguments.map(describeType).join(", ")}>` : "";
|
|
23518
23969
|
return `${type.name}${argumentsList2}${type.nullable ? "?" : ""}`;
|
|
@@ -23556,10 +24007,24 @@ function inferExpressionType2(expression, scope, environment) {
|
|
|
23556
24007
|
if (expression.kind === "litBool") return primitiveType("bool");
|
|
23557
24008
|
if (expression.kind === "litInt") return primitiveType("int");
|
|
23558
24009
|
if (expression.kind === "litFloat") return primitiveType("float");
|
|
24010
|
+
if (expression.kind === "litNull") return { name: "null", nullable: true };
|
|
23559
24011
|
if (expression.kind === "litString" || expression.kind === "litInterp" || expression.kind === "litTripleString")
|
|
23560
24012
|
return primitiveType("string");
|
|
23561
24013
|
if (expression.kind === "new")
|
|
23562
24014
|
return expression.className ? { name: expression.className } : void 0;
|
|
24015
|
+
if (expression.kind === "conditional") {
|
|
24016
|
+
const whenTrue = inferExpressionType2(
|
|
24017
|
+
expression.whenTrue,
|
|
24018
|
+
scope,
|
|
24019
|
+
environment
|
|
24020
|
+
);
|
|
24021
|
+
const whenFalse = inferExpressionType2(
|
|
24022
|
+
expression.whenFalse,
|
|
24023
|
+
scope,
|
|
24024
|
+
environment
|
|
24025
|
+
);
|
|
24026
|
+
return commonSemanticAssignableType(whenTrue, whenFalse);
|
|
24027
|
+
}
|
|
23563
24028
|
if (expression.kind === "member") {
|
|
23564
24029
|
if (expression.receiver.kind === "ident" && environment.enums.has(expression.receiver.name)) {
|
|
23565
24030
|
return { name: expression.receiver.name };
|
|
@@ -24073,7 +24538,7 @@ function classDerivesFromName(name, ancestorName, environment, seen = /* @__PURE
|
|
|
24073
24538
|
return classDerivesFromName(base.name, ancestorName, environment, seen);
|
|
24074
24539
|
});
|
|
24075
24540
|
}
|
|
24076
|
-
var NEO_VARIANT_FOLDER_SETTING, primitiveType, IDENTIFIER_PATTERN, LIST_COLUMN_INHERITANCE_KEY;
|
|
24541
|
+
var NEO_VARIANT_FOLDER_SETTING, primitiveType, IDENTIFIER_PATTERN, LIST_COLUMN_INHERITANCE_KEY, SEMANTIC_PRIMITIVE_TYPE_NAMES;
|
|
24077
24542
|
var init_project_source_semantics = __esm({
|
|
24078
24543
|
"../packages/neoscript-language/src/project-source-semantics.ts"() {
|
|
24079
24544
|
"use strict";
|
|
@@ -24090,6 +24555,13 @@ var init_project_source_semantics = __esm({
|
|
|
24090
24555
|
primitiveType = (name) => ({ name });
|
|
24091
24556
|
IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
24092
24557
|
LIST_COLUMN_INHERITANCE_KEY = "__other__";
|
|
24558
|
+
SEMANTIC_PRIMITIVE_TYPE_NAMES = /* @__PURE__ */ new Set([
|
|
24559
|
+
"bool",
|
|
24560
|
+
"int",
|
|
24561
|
+
"float",
|
|
24562
|
+
"decimal",
|
|
24563
|
+
"string"
|
|
24564
|
+
]);
|
|
24093
24565
|
}
|
|
24094
24566
|
});
|
|
24095
24567
|
|
|
@@ -41658,6 +42130,32 @@ function isNSPointerCoalesce(value) {
|
|
|
41658
42130
|
if (!isNSPointer(v.left)) return false;
|
|
41659
42131
|
return isNSPointer(v.right);
|
|
41660
42132
|
}
|
|
42133
|
+
function isNSPointerConditional(value) {
|
|
42134
|
+
if (typeof value !== "object" || value === null) return false;
|
|
42135
|
+
if (!("type" in value) || value.type !== "conditional" /* conditional */) {
|
|
42136
|
+
return false;
|
|
42137
|
+
}
|
|
42138
|
+
if (!("condition" in value) || !isNSPointer(value.condition)) return false;
|
|
42139
|
+
if (!("whenTrue" in value) || !isNSPointer(value.whenTrue)) return false;
|
|
42140
|
+
return "whenFalse" in value && isNSPointer(value.whenFalse);
|
|
42141
|
+
}
|
|
42142
|
+
function isNSPointerDelegateClosure(value) {
|
|
42143
|
+
if (typeof value !== "object" || value === null) return false;
|
|
42144
|
+
if (!("type" in value) || value.type !== "delegateClosure" /* delegateClosure */) {
|
|
42145
|
+
return false;
|
|
42146
|
+
}
|
|
42147
|
+
if (!("typeInfo" in value) || !isNSTypeInfo(value.typeInfo) || value.typeInfo.type !== 25 /* NSDelegate */) {
|
|
42148
|
+
return false;
|
|
42149
|
+
}
|
|
42150
|
+
if (!("action" in value) || !isNSFunctionWithReturnType(value.action)) {
|
|
42151
|
+
return false;
|
|
42152
|
+
}
|
|
42153
|
+
if (!("captures" in value) || !Array.isArray(value.captures) || !value.captures.every(isNSPointer)) {
|
|
42154
|
+
return false;
|
|
42155
|
+
}
|
|
42156
|
+
if (!("code" in value) || value.code === void 0) return true;
|
|
42157
|
+
return typeof value.code === "string" && value.code.length > 0;
|
|
42158
|
+
}
|
|
41661
42159
|
function isNSPointerToBool(value) {
|
|
41662
42160
|
const v = value;
|
|
41663
42161
|
if (v?.type !== "toBool" /* toBool */) return false;
|
|
@@ -41685,6 +42183,12 @@ function isNSPointerCallFunction(value) {
|
|
|
41685
42183
|
if (v.optional !== void 0 && typeof v.optional !== "boolean") {
|
|
41686
42184
|
return false;
|
|
41687
42185
|
}
|
|
42186
|
+
if (v.missingMemberFallback !== void 0 && v.missingMemberFallback !== "valueEquality") {
|
|
42187
|
+
return false;
|
|
42188
|
+
}
|
|
42189
|
+
if (v.missingMemberFallback === "valueEquality" && (!hasMemberKey || v.receiver?.kind !== "instance" || v.args.length !== 1)) {
|
|
42190
|
+
return false;
|
|
42191
|
+
}
|
|
41688
42192
|
return true;
|
|
41689
42193
|
}
|
|
41690
42194
|
function isNSPointerCallDelegate(value) {
|
|
@@ -41725,7 +42229,7 @@ function isNSPointerFunctionErrorCheck(value) {
|
|
|
41725
42229
|
return isNSFunctionErrorCheckMode(v.mode);
|
|
41726
42230
|
}
|
|
41727
42231
|
function isNSPointer(value) {
|
|
41728
|
-
return isNSPointerReference(value) || isNSPointerVariable(value) || isNSPointerStaticMember(value) || isNSPointerValue(value) || isNSPointerOperation(value) || isNSPointerFunction(value) || isNSPointerKeyOf(value) || isNSPointerListLiteral(value) || isNSPointerDictLiteral(value) || isNSPointerForceUnwrap(value) || isNSPointerIsCheck(value) || isNSPointerCallGetter(value) || isNSPointerCoalesce(value) || isNSPointerToBool(value) || isNSPointerStringify(value) || isNSPointerCallFunction(value) || isNSPointerCallDelegate(value) || isNSPointerCallAction(value) || isNSPointerVariant(value) || isNSPointerFunctionErrorCheck(value);
|
|
42232
|
+
return isNSPointerReference(value) || isNSPointerVariable(value) || isNSPointerStaticMember(value) || isNSPointerValue(value) || isNSPointerOperation(value) || isNSPointerFunction(value) || isNSPointerKeyOf(value) || isNSPointerListLiteral(value) || isNSPointerDictLiteral(value) || isNSPointerForceUnwrap(value) || isNSPointerIsCheck(value) || isNSPointerCallGetter(value) || isNSPointerCoalesce(value) || isNSPointerConditional(value) || isNSPointerDelegateClosure(value) || isNSPointerToBool(value) || isNSPointerStringify(value) || isNSPointerCallFunction(value) || isNSPointerCallDelegate(value) || isNSPointerCallAction(value) || isNSPointerVariant(value) || isNSPointerFunctionErrorCheck(value);
|
|
41729
42233
|
}
|
|
41730
42234
|
function isNSPointers(value) {
|
|
41731
42235
|
return Array.isArray(value) && value.every(isNSPointer);
|
|
@@ -41794,24 +42298,7 @@ function isNSFunctionWithReturnType(value) {
|
|
|
41794
42298
|
if (!Array.isArray(v.parameters)) return false;
|
|
41795
42299
|
if (!v.parameters.every(isNSVariable)) return false;
|
|
41796
42300
|
if (!isNSInstructions(v.instructions)) return false;
|
|
41797
|
-
if (
|
|
41798
|
-
"for" /* for */,
|
|
41799
|
-
"forEach" /* forEach */,
|
|
41800
|
-
"break" /* break */,
|
|
41801
|
-
"continue" /* continue */
|
|
41802
|
-
].some((type) => nsInstructionsContainType(v.instructions ?? [], type)) && (v.compilerRevision ?? 1) < 4) {
|
|
41803
|
-
return false;
|
|
41804
|
-
}
|
|
41805
|
-
if (nsInstructionsContainType(v.instructions, "switch" /* switch */) && (v.compilerRevision ?? 1) < 5) {
|
|
41806
|
-
return false;
|
|
41807
|
-
}
|
|
41808
|
-
if (nsInstructionsContainType(v.instructions, "try" /* try */) && (v.compilerRevision ?? 1) < 6) {
|
|
41809
|
-
return false;
|
|
41810
|
-
}
|
|
41811
|
-
if ((v.compilerRevision ?? 1) < 8 && ([
|
|
41812
|
-
"addActionListener" /* addActionListener */,
|
|
41813
|
-
"removeActionListener" /* removeActionListener */
|
|
41814
|
-
].some((type) => nsInstructionsContainType(v.instructions ?? [], type)) || nsIRContainsPointerType(v.instructions, "callAction" /* callAction */))) {
|
|
42301
|
+
if ((v.compilerRevision ?? 1) < NEOSCRIPT_COMPILER_REVISION && (v.compilerRevision ?? 1) < minimumNeoScriptCompilerRevisionForIR(v.instructions)) {
|
|
41815
42302
|
return false;
|
|
41816
42303
|
}
|
|
41817
42304
|
if (!isNSTypeInfo(v.typeInfo)) return false;
|
|
@@ -42252,44 +42739,32 @@ function isNSInstructionTry(value) {
|
|
|
42252
42739
|
function isNSInstruction(value) {
|
|
42253
42740
|
return isNSInstructionVariable(value) || isNSInstructionIfBranch(value) || isNSInstructionReturn(value) || isNSInstructionThrow(value) || isNSInstructionAssign(value) || isNSInstructionCollectionCall(value) || isNSInstructionFunctionCall(value) || isNSInstructionFor(value) || isNSInstructionForEach(value) || isNSInstructionBreak(value) || isNSInstructionContinue(value) || isNSInstructionSwitch(value) || isNSInstructionTry(value) || isNSInstructionAddActionListener(value) || isNSInstructionRemoveActionListener(value);
|
|
42254
42741
|
}
|
|
42255
|
-
function
|
|
42256
|
-
|
|
42257
|
-
|
|
42258
|
-
|
|
42259
|
-
|
|
42260
|
-
|
|
42261
|
-
|
|
42262
|
-
}
|
|
42263
|
-
if (instruction.type === "for" /* for */ || instruction.type === "forEach" /* forEach */) {
|
|
42264
|
-
return nsInstructionsContainType(instruction.instructions, type);
|
|
42265
|
-
}
|
|
42266
|
-
if (instruction.type === "switch" /* switch */) {
|
|
42267
|
-
return instruction.sections.some(
|
|
42268
|
-
(section) => nsInstructionsContainType(section.instructions, type)
|
|
42269
|
-
) || instruction.defaultInstructions !== null && instruction.defaultInstructions !== void 0 && nsInstructionsContainType(instruction.defaultInstructions, type);
|
|
42270
|
-
}
|
|
42271
|
-
if (instruction.type === "try" /* try */) {
|
|
42272
|
-
return nsInstructionsContainType(instruction.instructions, type) || instruction.catches.some(
|
|
42273
|
-
(clause) => nsInstructionsContainType(clause.instructions, type)
|
|
42742
|
+
function minimumNeoScriptCompilerRevisionForIR(node, visited = /* @__PURE__ */ new Set()) {
|
|
42743
|
+
if (Array.isArray(node)) {
|
|
42744
|
+
let minimum2 = 1;
|
|
42745
|
+
for (const entry of node) {
|
|
42746
|
+
minimum2 = Math.max(
|
|
42747
|
+
minimum2,
|
|
42748
|
+
minimumNeoScriptCompilerRevisionForIR(entry, visited)
|
|
42274
42749
|
);
|
|
42275
42750
|
}
|
|
42276
|
-
return
|
|
42277
|
-
});
|
|
42278
|
-
}
|
|
42279
|
-
function nsIRContainsPointerType(node, type, visited = /* @__PURE__ */ new Set()) {
|
|
42280
|
-
if (Array.isArray(node)) {
|
|
42281
|
-
return node.some((entry) => nsIRContainsPointerType(entry, type, visited));
|
|
42751
|
+
return minimum2;
|
|
42282
42752
|
}
|
|
42283
|
-
if (typeof node !== "object" || node === null) return
|
|
42284
|
-
if (visited.has(node)) return
|
|
42753
|
+
if (typeof node !== "object" || node === null) return 1;
|
|
42754
|
+
if (visited.has(node)) return 1;
|
|
42285
42755
|
visited.add(node);
|
|
42286
|
-
const
|
|
42287
|
-
|
|
42288
|
-
|
|
42289
|
-
|
|
42290
|
-
|
|
42291
|
-
|
|
42292
|
-
|
|
42756
|
+
const discriminatorRevision = "type" in node && typeof node.type === "string" ? MINIMUM_REVISION_BY_IR_DISCRIMINATOR.get(node.type) ?? 1 : 1;
|
|
42757
|
+
const fallbackRevision = "missingMemberFallback" in node && node.missingMemberFallback === "valueEquality" ? 12 : 1;
|
|
42758
|
+
let minimum = Math.max(discriminatorRevision, fallbackRevision);
|
|
42759
|
+
const isLiteralValue = "typeInfo" in node && "value" in node && !("type" in node);
|
|
42760
|
+
for (const [key, child] of Object.entries(node)) {
|
|
42761
|
+
if (isLiteralValue && key === "value") continue;
|
|
42762
|
+
minimum = Math.max(
|
|
42763
|
+
minimum,
|
|
42764
|
+
minimumNeoScriptCompilerRevisionForIR(child, visited)
|
|
42765
|
+
);
|
|
42766
|
+
}
|
|
42767
|
+
return minimum;
|
|
42293
42768
|
}
|
|
42294
42769
|
function isNSInstructions(value) {
|
|
42295
42770
|
return Array.isArray(value) && value.every(isNSInstruction);
|
|
@@ -42337,7 +42812,7 @@ function isNSVoidBody(value) {
|
|
|
42337
42812
|
if (value.typeInfo.type !== 0 /* Null */) return false;
|
|
42338
42813
|
return value.typeInfo.required === true;
|
|
42339
42814
|
}
|
|
42340
|
-
var NS_STRING_OPS, NS_DECIMAL_OPS, NS_MATH_OPS;
|
|
42815
|
+
var NS_STRING_OPS, NS_DECIMAL_OPS, NS_MATH_OPS, MINIMUM_REVISION_BY_IR_DISCRIMINATOR;
|
|
42341
42816
|
var init_neoscript_guards = __esm({
|
|
42342
42817
|
"../src/models/neoscript/neoscript-guards.ts"() {
|
|
42343
42818
|
"use strict";
|
|
@@ -42370,6 +42845,20 @@ var init_neoscript_guards = __esm({
|
|
|
42370
42845
|
"sign",
|
|
42371
42846
|
"sqrt"
|
|
42372
42847
|
];
|
|
42848
|
+
MINIMUM_REVISION_BY_IR_DISCRIMINATOR = /* @__PURE__ */ new Map([
|
|
42849
|
+
["for" /* for */, 4],
|
|
42850
|
+
["forEach" /* forEach */, 4],
|
|
42851
|
+
["break" /* break */, 4],
|
|
42852
|
+
["continue" /* continue */, 4],
|
|
42853
|
+
["switch" /* switch */, 5],
|
|
42854
|
+
["try" /* try */, 6],
|
|
42855
|
+
["callDelegate" /* callDelegate */, 7],
|
|
42856
|
+
["addActionListener" /* addActionListener */, 8],
|
|
42857
|
+
["removeActionListener" /* removeActionListener */, 8],
|
|
42858
|
+
["callAction" /* callAction */, 8],
|
|
42859
|
+
["conditional" /* conditional */, 12],
|
|
42860
|
+
["delegateClosure" /* delegateClosure */, 12]
|
|
42861
|
+
]);
|
|
42373
42862
|
}
|
|
42374
42863
|
});
|
|
42375
42864
|
|
|
@@ -43340,11 +43829,18 @@ function isNSDelegateClosureValueDraft(value) {
|
|
|
43340
43829
|
function isNSDelegateClosureValue(value) {
|
|
43341
43830
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
43342
43831
|
const record3 = value;
|
|
43343
|
-
const keys =
|
|
43832
|
+
const keys = [
|
|
43833
|
+
...record3.code === void 0 ? [] : ["code"],
|
|
43834
|
+
"action",
|
|
43835
|
+
...record3.captures === void 0 ? [] : ["captures"]
|
|
43836
|
+
];
|
|
43344
43837
|
if (!hasExactKeys(record3, keys)) return false;
|
|
43345
43838
|
if (record3.code !== void 0 && (typeof record3.code !== "string" || record3.code.length === 0)) {
|
|
43346
43839
|
return false;
|
|
43347
43840
|
}
|
|
43841
|
+
if (record3.captures !== void 0 && !Array.isArray(record3.captures)) {
|
|
43842
|
+
return false;
|
|
43843
|
+
}
|
|
43348
43844
|
return isNSFunctionWithReturnType(record3.action);
|
|
43349
43845
|
}
|
|
43350
43846
|
function isNSDelegateValue(value) {
|
|
@@ -56100,6 +56596,17 @@ function expressionReadsRuntimeIdentifier(expression, runtimeIdentifiers) {
|
|
|
56100
56596
|
case "binary":
|
|
56101
56597
|
case "coalesce":
|
|
56102
56598
|
return expressionReadsRuntimeIdentifier(expression.left, runtimeIdentifiers) || expressionReadsRuntimeIdentifier(expression.right, runtimeIdentifiers);
|
|
56599
|
+
case "conditional":
|
|
56600
|
+
return expressionReadsRuntimeIdentifier(
|
|
56601
|
+
expression.condition,
|
|
56602
|
+
runtimeIdentifiers
|
|
56603
|
+
) || expressionReadsRuntimeIdentifier(
|
|
56604
|
+
expression.whenTrue,
|
|
56605
|
+
runtimeIdentifiers
|
|
56606
|
+
) || expressionReadsRuntimeIdentifier(
|
|
56607
|
+
expression.whenFalse,
|
|
56608
|
+
runtimeIdentifiers
|
|
56609
|
+
);
|
|
56103
56610
|
case "unary":
|
|
56104
56611
|
case "force":
|
|
56105
56612
|
case "is":
|
|
@@ -56131,6 +56638,7 @@ function isEvaluatedOnlyExpression(expression) {
|
|
|
56131
56638
|
return isEvaluatedOnlyExpression(expression.expression);
|
|
56132
56639
|
case "binary":
|
|
56133
56640
|
case "coalesce":
|
|
56641
|
+
case "conditional":
|
|
56134
56642
|
case "index":
|
|
56135
56643
|
case "is":
|
|
56136
56644
|
case "force":
|
|
@@ -67071,6 +67579,9 @@ function evalPointer(pointer, scope, ctx) {
|
|
|
67071
67579
|
(arg) => evalPointer(arg, scope, ctx)
|
|
67072
67580
|
);
|
|
67073
67581
|
const member = pointer.receiver.kind === "static" ? evalMemberById(ctx.vm, pointer.receiver.memberId) : resolveEffectiveCallableMember(pointer, innerThis, ctx);
|
|
67582
|
+
if (member !== null && pointer.missingMemberFallback === "valueEquality") {
|
|
67583
|
+
assertValueEqualitySignature(member, innerThis, ctx);
|
|
67584
|
+
}
|
|
67074
67585
|
const args = fillCallableCallSiteArguments(suppliedArgs, member, ctx);
|
|
67075
67586
|
const interceptedMemberId = member?.id ?? pointer.memberId ?? pointer.memberKey ?? pointer.callSiteId;
|
|
67076
67587
|
consumeBudget(ctx, "workUnits", 1, "work unit");
|
|
@@ -67084,6 +67595,9 @@ function evalPointer(pointer, scope, ctx) {
|
|
|
67084
67595
|
});
|
|
67085
67596
|
if (intercepted?.handled === true) return intercepted.value;
|
|
67086
67597
|
if (member === null) {
|
|
67598
|
+
if (pointer.missingMemberFallback === "valueEquality") {
|
|
67599
|
+
return jsEqual(innerThis, suppliedArgs[0]);
|
|
67600
|
+
}
|
|
67087
67601
|
throw new NSGetterRuntimeError(
|
|
67088
67602
|
`Function call '${pointer.memberKey ?? pointer.memberId ?? pointer.callSiteId}' could not be resolved on the receiver's runtime class.`
|
|
67089
67603
|
);
|
|
@@ -67197,6 +67711,24 @@ function evalPointer(pointer, scope, ctx) {
|
|
|
67197
67711
|
if (left !== null && left !== void 0) return left;
|
|
67198
67712
|
return evalPointer(pointer.right, scope, ctx);
|
|
67199
67713
|
}
|
|
67714
|
+
case "conditional" /* conditional */: {
|
|
67715
|
+
const condition = evalPointer(pointer.condition, scope, ctx);
|
|
67716
|
+
return evalPointer(
|
|
67717
|
+
jsTruthy(condition) ? pointer.whenTrue : pointer.whenFalse,
|
|
67718
|
+
scope,
|
|
67719
|
+
ctx
|
|
67720
|
+
);
|
|
67721
|
+
}
|
|
67722
|
+
case "delegateClosure" /* delegateClosure */:
|
|
67723
|
+
return {
|
|
67724
|
+
...pointer.code === void 0 ? {} : { code: pointer.code },
|
|
67725
|
+
action: pointer.action,
|
|
67726
|
+
captures: pointer.captures.map(
|
|
67727
|
+
(capture) => evalPointer(capture, scope, ctx)
|
|
67728
|
+
),
|
|
67729
|
+
...ctx.thisValue === null || ctx.thisValue === void 0 ? {} : { [DELEGATE_LEXICAL_THIS]: ctx.thisValue },
|
|
67730
|
+
[DELEGATE_LEXICAL_ROOT]: ctx.rootValue
|
|
67731
|
+
};
|
|
67200
67732
|
case "toBool" /* toBool */: {
|
|
67201
67733
|
const v = evalPointer(pointer.pointer, scope, ctx);
|
|
67202
67734
|
return jsTruthy(v);
|
|
@@ -67225,6 +67757,34 @@ function resolveEffectiveCallableMember(pointer, receiver, ctx) {
|
|
|
67225
67757
|
const runtimeMember = resolveRuntimeSchemaMember(receiver, schemaKey, ctx);
|
|
67226
67758
|
return runtimeMember ?? staticMember;
|
|
67227
67759
|
}
|
|
67760
|
+
function assertValueEqualitySignature(member, receiver, ctx) {
|
|
67761
|
+
if (member.kind !== 13 /* Function */ && member.kind !== 23 /* NSFunction */) {
|
|
67762
|
+
throw new NSGetterRuntimeError(
|
|
67763
|
+
`Generic Equals resolved to non-callable member '${member.name}'.`
|
|
67764
|
+
);
|
|
67765
|
+
}
|
|
67766
|
+
const signature = resolveCallableSignature(member.id, member.kind, ctx);
|
|
67767
|
+
if (signature === null) {
|
|
67768
|
+
throw new NSGetterRuntimeError(
|
|
67769
|
+
`Generic Equals member '${member.name}' has no resolvable signature.`
|
|
67770
|
+
);
|
|
67771
|
+
}
|
|
67772
|
+
const runtimeSignature = substituteCallableSignatureForReceiver(
|
|
67773
|
+
signature,
|
|
67774
|
+
receiver,
|
|
67775
|
+
ctx
|
|
67776
|
+
);
|
|
67777
|
+
if (runtimeSignature.argumentTypes.length !== 1) {
|
|
67778
|
+
throw new NSGetterRuntimeError(
|
|
67779
|
+
`Generic Equals member '${member.name}' must take exactly one argument; found ${runtimeSignature.argumentTypes.length}.`
|
|
67780
|
+
);
|
|
67781
|
+
}
|
|
67782
|
+
if (runtimeSignature.returnTypeInfo.type !== 1 /* Bool */) {
|
|
67783
|
+
throw new NSGetterRuntimeError(
|
|
67784
|
+
`Generic Equals member '${member.name}' must return bool.`
|
|
67785
|
+
);
|
|
67786
|
+
}
|
|
67787
|
+
}
|
|
67228
67788
|
function invokeDelegateValue(value, args, ctx, callSiteId, ownerReceiver) {
|
|
67229
67789
|
if (isNSDelegateClosureValueDraft(value)) {
|
|
67230
67790
|
throw new NSGetterRuntimeError(
|
|
@@ -67234,6 +67794,7 @@ function invokeDelegateValue(value, args, ctx, callSiteId, ownerReceiver) {
|
|
|
67234
67794
|
if (isNSDelegateClosureValue(value)) {
|
|
67235
67795
|
const closure = value;
|
|
67236
67796
|
const thisValue = delegateClosureLexicalThis(closure, ctx);
|
|
67797
|
+
const captures = closure.captures ?? [];
|
|
67237
67798
|
return executeCompiledFunction(
|
|
67238
67799
|
value.action,
|
|
67239
67800
|
{
|
|
@@ -67241,7 +67802,7 @@ function invokeDelegateValue(value, args, ctx, callSiteId, ownerReceiver) {
|
|
|
67241
67802
|
thisValue,
|
|
67242
67803
|
rootValue: closure[DELEGATE_LEXICAL_ROOT] ?? ctx.rootValue
|
|
67243
67804
|
},
|
|
67244
|
-
args,
|
|
67805
|
+
[...args, ...captures],
|
|
67245
67806
|
value.action.typeInfo.type === 0 /* Null */
|
|
67246
67807
|
);
|
|
67247
67808
|
}
|
|
@@ -112350,7 +112911,7 @@ var init_registry2 = __esm({
|
|
|
112350
112911
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
112351
112912
|
formatVersion: 3,
|
|
112352
112913
|
contractVersion: "3.13",
|
|
112353
|
-
cliVersion: "0.
|
|
112914
|
+
cliVersion: "0.33.0",
|
|
112354
112915
|
projectFileUploadBatchSize: 32,
|
|
112355
112916
|
documentRecords: {
|
|
112356
112917
|
member: {
|
|
@@ -118945,7 +119506,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
118945
119506
|
async function main() {
|
|
118946
119507
|
const args = parseArgs(process.argv.slice(2));
|
|
118947
119508
|
if (args.command === "--version") {
|
|
118948
|
-
console.log("0.
|
|
119509
|
+
console.log("0.33.0");
|
|
118949
119510
|
return;
|
|
118950
119511
|
}
|
|
118951
119512
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/package.json
CHANGED
|
@@ -83,7 +83,7 @@ wrappers.
|
|
|
83
83
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
84
84
|
|
|
85
85
|
```html
|
|
86
|
-
<!-- reviewed-through-cli: 0.
|
|
86
|
+
<!-- reviewed-through-cli: 0.33.0 -->
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -8,7 +8,7 @@ runtime ownership, evaluation, and migrations.
|
|
|
8
8
|
- Inline bodies and snippets
|
|
9
9
|
- Nullability and ownership
|
|
10
10
|
- Numeric builtins
|
|
11
|
-
-
|
|
11
|
+
- Conditional and logical operators
|
|
12
12
|
- Loops and transfer
|
|
13
13
|
- Switch
|
|
14
14
|
- Try/catch
|
|
@@ -44,6 +44,20 @@ Prefer `--json` for automation.
|
|
|
44
44
|
|
|
45
45
|
Inside an inline Class body, unqualified names resolve against that Class;
|
|
46
46
|
invoke delegate and action members directly with `Selector()` or `OnChanged()`.
|
|
47
|
+
Clear every subscribed listener from a stored action with
|
|
48
|
+
`this.OnChanged.Clear()`. `Clear()` is a mutating statement and follows the
|
|
49
|
+
action member's effective storage and writability.
|
|
50
|
+
|
|
51
|
+
Inline `NeoDelegate` lambdas may be returned or stored and may read surrounding
|
|
52
|
+
locals and parameters. Those values are captured when the lambda is created,
|
|
53
|
+
so later changes to the outer binding do not alter the closure. Explicit lambda
|
|
54
|
+
parameter annotations accept the same type grammar as declarations, including
|
|
55
|
+
`decimal`, generic parameters, collections, arrays, and nullable types.
|
|
56
|
+
|
|
57
|
+
Calling `Equals(other)` on a non-null generic value dynamically uses the
|
|
58
|
+
runtime Class's one-argument `Equals` Function or NSFunction when it returns
|
|
59
|
+
`bool`, including the effective override. Values without that member fall back
|
|
60
|
+
to ordinary NeoScript equality.
|
|
47
61
|
|
|
48
62
|
## Nullability and ownership
|
|
49
63
|
|
|
@@ -113,7 +127,17 @@ enum, parameter, or local may shadow it. Qualified members use their owner's
|
|
|
113
127
|
namespace and may be named `Math`; access one as `this.Math` or
|
|
114
128
|
`SomeValue.Math` without colliding with the builtin qualifier.
|
|
115
129
|
|
|
116
|
-
##
|
|
130
|
+
## Conditional and logical operators
|
|
131
|
+
|
|
132
|
+
Use `condition ? whenTrue : whenFalse` for a value chosen by a condition:
|
|
133
|
+
|
|
134
|
+
```neo
|
|
135
|
+
T modified = this.Modifier != null ? this.Modifier(value) : value;
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The operator has lower precedence than `??`, `||`, and `&&`, associates from
|
|
139
|
+
the right, and evaluates only the selected result arm. Both arms must share a
|
|
140
|
+
common assignable type or fit the surrounding expected type.
|
|
117
141
|
|
|
118
142
|
Use `&&` and `||` with C# precedence: `&&` binds tighter than `||`, and
|
|
119
143
|
parentheses preserve explicit grouping. Both operators short-circuit, so the
|