@neocompose/cli 0.33.1 → 0.34.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,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.34.0] - 2026-08-19
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- P71 `List.Repeat`: call `List.Repeat(value, count)` from any NeoScript body
|
|
8
|
+
to build a list of `count` copies of `value`. The entry type is inferred
|
|
9
|
+
from the value and joined with the assignment context, so
|
|
10
|
+
`List<float> w = List.Repeat(0, 4)` widens; `count` must be an `int`, a
|
|
11
|
+
negative count is a runtime error, and materialization is charged to the
|
|
12
|
+
shared collection-entries budget.
|
|
13
|
+
- Unity export schema version 25, so an SDK that predates `listRepeat` refuses
|
|
14
|
+
the export with the standard upgrade message instead of failing
|
|
15
|
+
mid-deserialize.
|
|
16
|
+
|
|
17
|
+
## [0.33.2] - 2026-08-19
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Preserve authored non-null generic fields while projecting the local schema
|
|
22
|
+
manifest used by `neo script check --all`, so a `T` field read remains `T`
|
|
23
|
+
instead of becoming `T?` from the storage placeholder's structural flags.
|
|
24
|
+
- Compile prospective functions, properties, migrations, and ad-hoc scripts
|
|
25
|
+
against the complete project context, including declared constructors,
|
|
26
|
+
project files, and variants. `neo test` now resolves required Class-header
|
|
27
|
+
constructors instead of incorrectly falling back to their stored fields.
|
|
28
|
+
|
|
3
29
|
## [0.33.1] - 2026-08-19
|
|
4
30
|
|
|
5
31
|
### Fixed
|
package/dist/neo.mjs
CHANGED
|
@@ -1336,7 +1336,7 @@ function vectorTypes() {
|
|
|
1336
1336
|
members: structuredLeafFieldProperties(name)
|
|
1337
1337
|
}));
|
|
1338
1338
|
}
|
|
1339
|
-
var NEO_PROJECT_IGNORED_DIRECTORY_NAMES, NEOSCRIPT_KEYWORDS, NEOSCRIPT_INFERRED_LOCAL_KEYWORD, NEOSCRIPT_CONSTRUCTOR_KEYWORD, NEOSCRIPT_PRIMITIVE_TYPES, NEOSCRIPT_BUILTIN_ANNOTATION_TYPES, NEOSCRIPT_BUILTIN_NAMESPACES, NEOSCRIPT_BUILTIN_TYPES, NEO_VARIANT_TYPE_NAME, NEO_VARIANT_FOLDER_TYPE_NAME, NEO_LOOKUP_VARIANT_TYPE_NAME, NEO_LOOKUP_VARIANT_FOLDER_TYPE_NAME, NEO_VARIANT_SCOPE_NAME, NEO_VARIANT_RESERVED_NAME, NEO_VARIANT_FOLDER_PATH_SEPARATOR, NEOSCRIPT_OPERATORS, NEOSCRIPT_STATEMENT_SNIPPETS, STRING_TYPE, INT_TYPE, FLOAT_TYPE, BOOL_TYPE, IMAGE_REF_TYPE, SPRITE_INFO_TYPE, FLOAT_OPTIONAL_TYPE, NEOSCRIPT_STRUCTURED_LEAF_FIELDS, NEOSCRIPT_IMAGE_REGISTRY_TYPE, NEOSCRIPT_AUDIO_CLIP_REGISTRY_TYPE, NEOSCRIPT_PENDING_SYMBOL_ID_PREFIX, REGISTRY_ENTRY_TYPES, NEOSCRIPT_GLOBALS, NEOSCRIPT_SPRITE_INFO_EMPTY_MEMBER_ID, NEOSCRIPT_SPRITE_INFO_EMPTY_VALUE, NEOSCRIPT_MATH_TYPE_ID, MATH_INFERENCE_RULE, MATH_INTEGRAL_RULE, NEOSCRIPT_BUILTIN_TYPE_SYMBOLS;
|
|
1339
|
+
var NEO_PROJECT_IGNORED_DIRECTORY_NAMES, NEOSCRIPT_KEYWORDS, NEOSCRIPT_INFERRED_LOCAL_KEYWORD, NEOSCRIPT_CONSTRUCTOR_KEYWORD, NEOSCRIPT_PRIMITIVE_TYPES, NEOSCRIPT_BUILTIN_ANNOTATION_TYPES, NEOSCRIPT_BUILTIN_NAMESPACES, NEOSCRIPT_BUILTIN_TYPES, NEO_VARIANT_TYPE_NAME, NEO_VARIANT_FOLDER_TYPE_NAME, NEO_LOOKUP_VARIANT_TYPE_NAME, NEO_LOOKUP_VARIANT_FOLDER_TYPE_NAME, NEO_VARIANT_SCOPE_NAME, NEO_VARIANT_RESERVED_NAME, NEO_VARIANT_FOLDER_PATH_SEPARATOR, NEOSCRIPT_OPERATORS, NEOSCRIPT_STATEMENT_SNIPPETS, STRING_TYPE, INT_TYPE, FLOAT_TYPE, BOOL_TYPE, IMAGE_REF_TYPE, SPRITE_INFO_TYPE, FLOAT_OPTIONAL_TYPE, NEOSCRIPT_STRUCTURED_LEAF_FIELDS, NEOSCRIPT_IMAGE_REGISTRY_TYPE, NEOSCRIPT_AUDIO_CLIP_REGISTRY_TYPE, NEOSCRIPT_PENDING_SYMBOL_ID_PREFIX, REGISTRY_ENTRY_TYPES, NEOSCRIPT_GLOBALS, NEOSCRIPT_SPRITE_INFO_EMPTY_MEMBER_ID, NEOSCRIPT_SPRITE_INFO_EMPTY_VALUE, NEOSCRIPT_MATH_TYPE_ID, MATH_INFERENCE_RULE, MATH_INTEGRAL_RULE, NEOSCRIPT_LIST_TYPE_NAME, NEOSCRIPT_LIST_TYPE_ID, NEOSCRIPT_LIST_REPEAT_NAME, LIST_ENTRY_TYPE, NEOSCRIPT_BUILTIN_TYPE_SYMBOLS;
|
|
1340
1340
|
var init_language_spec = __esm({
|
|
1341
1341
|
"../packages/neoscript-language/src/language-spec.ts"() {
|
|
1342
1342
|
"use strict";
|
|
@@ -1680,6 +1680,14 @@ var init_language_spec = __esm({
|
|
|
1680
1680
|
NEOSCRIPT_MATH_TYPE_ID = "builtin:Math";
|
|
1681
1681
|
MATH_INFERENCE_RULE = "Accepts int, float, or decimal; the result mirrors the widest argument type.";
|
|
1682
1682
|
MATH_INTEGRAL_RULE = "Accepts int, float, or decimal; int and float return int, decimal returns decimal.";
|
|
1683
|
+
NEOSCRIPT_LIST_TYPE_NAME = "List";
|
|
1684
|
+
NEOSCRIPT_LIST_TYPE_ID = "builtin:List";
|
|
1685
|
+
NEOSCRIPT_LIST_REPEAT_NAME = "Repeat";
|
|
1686
|
+
LIST_ENTRY_TYPE = {
|
|
1687
|
+
kind: "typeParameter",
|
|
1688
|
+
id: `${NEOSCRIPT_LIST_TYPE_ID}:entry`,
|
|
1689
|
+
name: "T"
|
|
1690
|
+
};
|
|
1683
1691
|
NEOSCRIPT_BUILTIN_TYPE_SYMBOLS = [
|
|
1684
1692
|
{
|
|
1685
1693
|
id: "builtin:SpriteInfo",
|
|
@@ -1833,6 +1841,27 @@ var init_language_spec = __esm({
|
|
|
1833
1841
|
static: true
|
|
1834
1842
|
}
|
|
1835
1843
|
]
|
|
1844
|
+
},
|
|
1845
|
+
{
|
|
1846
|
+
id: NEOSCRIPT_LIST_TYPE_ID,
|
|
1847
|
+
name: NEOSCRIPT_LIST_TYPE_NAME,
|
|
1848
|
+
kind: "builtin",
|
|
1849
|
+
documentation: "The ordered collection type. Write List<T> to annotate, and bare List to reach its static factories.",
|
|
1850
|
+
members: [
|
|
1851
|
+
{
|
|
1852
|
+
id: `${NEOSCRIPT_LIST_TYPE_ID}:function:${NEOSCRIPT_LIST_REPEAT_NAME}`,
|
|
1853
|
+
name: NEOSCRIPT_LIST_REPEAT_NAME,
|
|
1854
|
+
kind: "function",
|
|
1855
|
+
type: { kind: "list", elementType: LIST_ENTRY_TYPE },
|
|
1856
|
+
returnType: { kind: "list", elementType: LIST_ENTRY_TYPE },
|
|
1857
|
+
parameters: [
|
|
1858
|
+
parameter("value", LIST_ENTRY_TYPE),
|
|
1859
|
+
parameter("count", INT_TYPE)
|
|
1860
|
+
],
|
|
1861
|
+
documentation: "Returns a list of count copies of value. The entry type is inferred from value and the assignment context \u2014 never spell it. value is evaluated exactly once, then count exactly once, so a reference-typed value is the same reference in every entry; count must be a non-negative int, and 0 produces an empty list.",
|
|
1862
|
+
static: true
|
|
1863
|
+
}
|
|
1864
|
+
]
|
|
1836
1865
|
}
|
|
1837
1866
|
];
|
|
1838
1867
|
}
|
|
@@ -6975,6 +7004,9 @@ var init_strict_parser = __esm({
|
|
|
6975
7004
|
if (t.kind === "keyword" && t.text === "Dictionary") {
|
|
6976
7005
|
return true;
|
|
6977
7006
|
}
|
|
7007
|
+
if (t.kind === "keyword" && (t.text === "List" || t.text === "Set") && this.peek(1).kind === "op" && this.peek(1).text === "<") {
|
|
7008
|
+
return true;
|
|
7009
|
+
}
|
|
6978
7010
|
if (t.kind !== "ident") return false;
|
|
6979
7011
|
let j = this.i + 1;
|
|
6980
7012
|
const tk = (k) => this.tokens[k];
|
|
@@ -7233,6 +7265,15 @@ var init_strict_parser = __esm({
|
|
|
7233
7265
|
let expr = this.parsePrimary();
|
|
7234
7266
|
while (true) {
|
|
7235
7267
|
const t = this.peek();
|
|
7268
|
+
if (t.kind === "op" && t.text === "<" && expr.kind === "ident" && expr.name === NEOSCRIPT_LIST_TYPE_NAME) {
|
|
7269
|
+
const member = this.genericStaticMemberName();
|
|
7270
|
+
if (member !== null) {
|
|
7271
|
+
throw new CompileError(
|
|
7272
|
+
`Do not spell type arguments on '${NEOSCRIPT_LIST_TYPE_NAME}.${member}'; the entry type is inferred from the value.`,
|
|
7273
|
+
t.pos
|
|
7274
|
+
);
|
|
7275
|
+
}
|
|
7276
|
+
}
|
|
7236
7277
|
if (t.kind === "op" && t.text === "<" && this.looksLikeGenericCall()) {
|
|
7237
7278
|
this.next();
|
|
7238
7279
|
const typeArguments = [this.parseType()];
|
|
@@ -7322,6 +7363,28 @@ var init_strict_parser = __esm({
|
|
|
7322
7363
|
return expr;
|
|
7323
7364
|
}
|
|
7324
7365
|
}
|
|
7366
|
+
/**
|
|
7367
|
+
* The member name in a `<T, …>.Member` spelling at the cursor, or `null`
|
|
7368
|
+
* when the `<` is an ordinary comparison. Type arguments never precede a
|
|
7369
|
+
* member access in NeoScript, so this shape is always an author mistake and
|
|
7370
|
+
* the name is what a diagnostic needs to describe it.
|
|
7371
|
+
*/
|
|
7372
|
+
genericStaticMemberName() {
|
|
7373
|
+
const open = this.tokens[this.i];
|
|
7374
|
+
if (open?.kind !== "op" || open.text !== "<") return null;
|
|
7375
|
+
let index = this.scanType(this.i + 1);
|
|
7376
|
+
if (index === null) return null;
|
|
7377
|
+
while (this.tokens[index]?.kind === "punct" && this.tokens[index]?.text === ",") {
|
|
7378
|
+
index = this.scanType(index + 1);
|
|
7379
|
+
if (index === null) return null;
|
|
7380
|
+
}
|
|
7381
|
+
const close = this.tokens[index];
|
|
7382
|
+
const dot = this.tokens[index + 1];
|
|
7383
|
+
const member = this.tokens[index + 2];
|
|
7384
|
+
if (close?.kind !== "op" || close.text !== ">") return null;
|
|
7385
|
+
if (dot?.kind !== "punct" || dot.text !== ".") return null;
|
|
7386
|
+
return member?.kind === "ident" ? member.text : null;
|
|
7387
|
+
}
|
|
7325
7388
|
looksLikeGenericCall() {
|
|
7326
7389
|
const open = this.tokens[this.i];
|
|
7327
7390
|
if (open?.kind !== "op" || open.text !== "<") return false;
|
|
@@ -9431,7 +9494,7 @@ function switchValueKey(value) {
|
|
|
9431
9494
|
const enumId = value.typeInfo.type === 8 /* Enum */ ? value.typeInfo.enumId : null;
|
|
9432
9495
|
return JSON.stringify([value.typeInfo.type, enumId, value.value]);
|
|
9433
9496
|
}
|
|
9434
|
-
var CONSTRUCTING_FUNCTION_KINDS, VARIANT_INITIALIZE_NAME, VARIANT_APPLY_NAME, MATH_NAMESPACE_NAME, MATH_FUNCTIONS, MATH_CONSTANTS, WRITE_TARGET_DESCRIPTIONS, FALLTHROUGH_LABELS, Scope, StrictNeoScriptResolver, SPRITE_DERIVED_MEMBERS;
|
|
9497
|
+
var CONSTRUCTING_FUNCTION_KINDS, VARIANT_INITIALIZE_NAME, VARIANT_APPLY_NAME, MATH_NAMESPACE_NAME, MATH_FUNCTIONS, MATH_CONSTANTS, LIST_STATIC_FUNCTIONS, WRITE_TARGET_DESCRIPTIONS, FALLTHROUGH_LABELS, Scope, StrictNeoScriptResolver, SPRITE_DERIVED_MEMBERS;
|
|
9435
9498
|
var init_strict_resolver = __esm({
|
|
9436
9499
|
"../packages/neoscript-language/src/strict-resolver.ts"() {
|
|
9437
9500
|
"use strict";
|
|
@@ -9472,6 +9535,9 @@ var init_strict_resolver = __esm({
|
|
|
9472
9535
|
["PI", 3.141592653589793],
|
|
9473
9536
|
["E", 2.718281828459045]
|
|
9474
9537
|
]);
|
|
9538
|
+
LIST_STATIC_FUNCTIONS = /* @__PURE__ */ new Map([
|
|
9539
|
+
[NEOSCRIPT_LIST_REPEAT_NAME, { arity: 2 }]
|
|
9540
|
+
]);
|
|
9475
9541
|
WRITE_TARGET_DESCRIPTIONS = {
|
|
9476
9542
|
this: "`this`",
|
|
9477
9543
|
local: "a local",
|
|
@@ -11123,7 +11189,8 @@ var init_strict_resolver = __esm({
|
|
|
11123
11189
|
expression.callee,
|
|
11124
11190
|
expression.args,
|
|
11125
11191
|
scope,
|
|
11126
|
-
expression.pos
|
|
11192
|
+
expression.pos,
|
|
11193
|
+
expected
|
|
11127
11194
|
);
|
|
11128
11195
|
case "new": {
|
|
11129
11196
|
const vector = this.targetTypedVectorKind(expression, expected);
|
|
@@ -11770,6 +11837,12 @@ var init_strict_resolver = __esm({
|
|
|
11770
11837
|
pos
|
|
11771
11838
|
);
|
|
11772
11839
|
}
|
|
11840
|
+
if (name === NEOSCRIPT_LIST_TYPE_NAME) {
|
|
11841
|
+
throw new CompileError(
|
|
11842
|
+
`'${NEOSCRIPT_LIST_TYPE_NAME}' is a type and cannot be used as a value.`,
|
|
11843
|
+
pos
|
|
11844
|
+
);
|
|
11845
|
+
}
|
|
11773
11846
|
const type = this.project.typeByName.get(name);
|
|
11774
11847
|
if (type?.kind === "enum") {
|
|
11775
11848
|
return {
|
|
@@ -12222,6 +12295,15 @@ var init_strict_resolver = __esm({
|
|
|
12222
12295
|
}
|
|
12223
12296
|
return this.resolveMathMemberRead(name, pos);
|
|
12224
12297
|
}
|
|
12298
|
+
if (receiverAst.name === NEOSCRIPT_LIST_TYPE_NAME) {
|
|
12299
|
+
if (optional) {
|
|
12300
|
+
throw new CompileError(
|
|
12301
|
+
`Optional chaining is not valid on type '${NEOSCRIPT_LIST_TYPE_NAME}'.`,
|
|
12302
|
+
pos
|
|
12303
|
+
);
|
|
12304
|
+
}
|
|
12305
|
+
return this.resolveListStaticMemberRead(name, pos);
|
|
12306
|
+
}
|
|
12225
12307
|
const staticType = this.project.typeByName.get(receiverAst.name);
|
|
12226
12308
|
if (staticType && staticType.kind !== "enum") {
|
|
12227
12309
|
if (optional) {
|
|
@@ -12851,7 +12933,97 @@ var init_strict_resolver = __esm({
|
|
|
12851
12933
|
)
|
|
12852
12934
|
};
|
|
12853
12935
|
}
|
|
12854
|
-
|
|
12936
|
+
/**
|
|
12937
|
+
* P71 §1.2. A member read on the `List` qualifier. Nothing on `List` is
|
|
12938
|
+
* readable as a value: the statics are functions, and there are no
|
|
12939
|
+
* constants.
|
|
12940
|
+
*/
|
|
12941
|
+
resolveListStaticMemberRead(name, pos) {
|
|
12942
|
+
if (LIST_STATIC_FUNCTIONS.has(name)) {
|
|
12943
|
+
throw new CompileError(
|
|
12944
|
+
`'${NEOSCRIPT_LIST_TYPE_NAME}.${name}' must be called with \`()\`; it cannot be read as a value.`,
|
|
12945
|
+
pos
|
|
12946
|
+
);
|
|
12947
|
+
}
|
|
12948
|
+
throw new CompileError(
|
|
12949
|
+
`'${NEOSCRIPT_LIST_TYPE_NAME}' has no static member '${name}'.`,
|
|
12950
|
+
pos
|
|
12951
|
+
);
|
|
12952
|
+
}
|
|
12953
|
+
/** P71 §1.1. A static-factory call on the bare `List` qualifier. */
|
|
12954
|
+
resolveListStaticCall(name, args, scope, expected, pos) {
|
|
12955
|
+
const fn = LIST_STATIC_FUNCTIONS.get(name);
|
|
12956
|
+
if (!fn) {
|
|
12957
|
+
throw new CompileError(
|
|
12958
|
+
`'${NEOSCRIPT_LIST_TYPE_NAME}' has no static member '${name}'.`,
|
|
12959
|
+
pos
|
|
12960
|
+
);
|
|
12961
|
+
}
|
|
12962
|
+
requireArgCount(`${NEOSCRIPT_LIST_TYPE_NAME}.${name}`, args, fn.arity, pos);
|
|
12963
|
+
return this.resolveListRepeat(args, scope, expected);
|
|
12964
|
+
}
|
|
12965
|
+
/**
|
|
12966
|
+
* P71 §2/§3. `List.Repeat(value, count)`: the entry type is the value's
|
|
12967
|
+
* type joined with the contextual entry type — the list-literal join,
|
|
12968
|
+
* numeric widening included — and the count is an `int` with no implicit
|
|
12969
|
+
* narrowing. Lowers to a `listRepeat` intrinsic carrying the value pointer,
|
|
12970
|
+
* the count pointer, and the joined entry type the evaluators must not
|
|
12971
|
+
* re-derive.
|
|
12972
|
+
*/
|
|
12973
|
+
resolveListRepeat(args, scope, expected) {
|
|
12974
|
+
const label = `${NEOSCRIPT_LIST_TYPE_NAME}.${NEOSCRIPT_LIST_REPEAT_NAME}`;
|
|
12975
|
+
const expectedEntry = expected?.kind === "list" ? expected.elementType : void 0;
|
|
12976
|
+
const valueAst = requiredAt(args, 0);
|
|
12977
|
+
const countAst = requiredAt(args, 1);
|
|
12978
|
+
const value = this.resolveExpression(valueAst, scope, expectedEntry);
|
|
12979
|
+
const count = this.resolveExpression(countAst, scope, {
|
|
12980
|
+
kind: "primitive",
|
|
12981
|
+
name: "int"
|
|
12982
|
+
});
|
|
12983
|
+
if (isNullable(count.type)) {
|
|
12984
|
+
throw new CompileError(
|
|
12985
|
+
`${label} count must be a non-optional int; got ${this.describe(count.type)}.`,
|
|
12986
|
+
countAst.pos
|
|
12987
|
+
);
|
|
12988
|
+
}
|
|
12989
|
+
if (!isPrimitive(count.type, "int")) {
|
|
12990
|
+
throw new CompileError(
|
|
12991
|
+
`${label} count must be an int; got ${this.describe(count.type)}.`,
|
|
12992
|
+
countAst.pos
|
|
12993
|
+
);
|
|
12994
|
+
}
|
|
12995
|
+
const entryType = commonNeoScriptAssignableType(
|
|
12996
|
+
expectedEntry ?? value.type,
|
|
12997
|
+
value.type,
|
|
12998
|
+
this.project
|
|
12999
|
+
);
|
|
13000
|
+
if (entryType === null) {
|
|
13001
|
+
throw new CompileError(
|
|
13002
|
+
`${label} value ${this.describe(value.type)} is not a ${this.describe(expectedEntry ?? value.type)} entry.`,
|
|
13003
|
+
valueAst.pos
|
|
13004
|
+
);
|
|
13005
|
+
}
|
|
13006
|
+
const type = {
|
|
13007
|
+
kind: "list",
|
|
13008
|
+
elementType: entryType
|
|
13009
|
+
};
|
|
13010
|
+
const wire = toWireType(type, this.project);
|
|
13011
|
+
if (wire.type !== 6 /* List */) {
|
|
13012
|
+
throw new Error(
|
|
13013
|
+
"NeoScript strict compiler produced a non-list wire type for List.Repeat."
|
|
13014
|
+
);
|
|
13015
|
+
}
|
|
13016
|
+
return intrinsic(
|
|
13017
|
+
"listRepeat" /* ListRepeat */,
|
|
13018
|
+
{
|
|
13019
|
+
valuePointer: value.pointer,
|
|
13020
|
+
countPointer: count.pointer,
|
|
13021
|
+
entryTypeInfo: wire.entryTypeInfo
|
|
13022
|
+
},
|
|
13023
|
+
type
|
|
13024
|
+
);
|
|
13025
|
+
}
|
|
13026
|
+
resolveCall(callee, argumentsList2, scope, pos, expected) {
|
|
12855
13027
|
const variantCall = this.resolveVariantCall(
|
|
12856
13028
|
callee,
|
|
12857
13029
|
argumentsList2,
|
|
@@ -12953,6 +13125,21 @@ var init_strict_resolver = __esm({
|
|
|
12953
13125
|
}
|
|
12954
13126
|
return this.resolveMathCall(callee.name, argumentsList2, scope, pos);
|
|
12955
13127
|
}
|
|
13128
|
+
if (callee.receiver.name === NEOSCRIPT_LIST_TYPE_NAME) {
|
|
13129
|
+
if (callee.optional) {
|
|
13130
|
+
throw new CompileError(
|
|
13131
|
+
`Optional chaining is not valid on type '${NEOSCRIPT_LIST_TYPE_NAME}'.`,
|
|
13132
|
+
pos
|
|
13133
|
+
);
|
|
13134
|
+
}
|
|
13135
|
+
return this.resolveListStaticCall(
|
|
13136
|
+
callee.name,
|
|
13137
|
+
argumentsList2,
|
|
13138
|
+
scope,
|
|
13139
|
+
expected,
|
|
13140
|
+
pos
|
|
13141
|
+
);
|
|
13142
|
+
}
|
|
12956
13143
|
const staticType = this.project.typeByName.get(callee.receiver.name);
|
|
12957
13144
|
if (staticType && staticType.kind !== "enum") {
|
|
12958
13145
|
if (callee.optional) {
|
|
@@ -32824,7 +33011,7 @@ function memberType(member, environment, visiting, field) {
|
|
|
32824
33011
|
return typeParameter(
|
|
32825
33012
|
string2(member.genericParamId, `${field}.genericParamId`),
|
|
32826
33013
|
environment,
|
|
32827
|
-
|
|
33014
|
+
false
|
|
32828
33015
|
);
|
|
32829
33016
|
}
|
|
32830
33017
|
return { ...unknownType(), nullable };
|
|
@@ -42486,6 +42673,19 @@ function isNSFunctionMathOp(value) {
|
|
|
42486
42673
|
const decimal2 = info.decimal;
|
|
42487
42674
|
return decimal2 === void 0 || decimal2 === true;
|
|
42488
42675
|
}
|
|
42676
|
+
function isNSFunctionListRepeat(value) {
|
|
42677
|
+
const v = value;
|
|
42678
|
+
if (v?.type !== "listRepeat" /* listRepeat */) return false;
|
|
42679
|
+
const info = v.info;
|
|
42680
|
+
if (typeof info !== "object" || info === null) return false;
|
|
42681
|
+
if (!isNSPointer(info.valuePointer)) {
|
|
42682
|
+
return false;
|
|
42683
|
+
}
|
|
42684
|
+
if (!isNSPointer(info.countPointer)) {
|
|
42685
|
+
return false;
|
|
42686
|
+
}
|
|
42687
|
+
return isNSTypeInfo(info.entryTypeInfo);
|
|
42688
|
+
}
|
|
42489
42689
|
function isNSFunctionCount(value) {
|
|
42490
42690
|
const v = value;
|
|
42491
42691
|
if (v?.type !== "count" /* count */) return false;
|
|
@@ -42533,7 +42733,7 @@ function isNSFunction(value) {
|
|
|
42533
42733
|
return isNSFunctionClassConstructor(value) || isNSFunctionClassClone(value) || isNSFunctionListIndex(value) || isNSFunctionSelect(value) || isNSFunctionFirst(value) || isNSFunctionFirstOrDefault(value) || isNSFunctionWhere(value) || isNSFunctionContains(value) || // stringOp was missing from this chain since its introduction — a
|
|
42534
42734
|
// compiled getter using ToLower()/StartsWith() would fail pointer
|
|
42535
42735
|
// validation anywhere isNSFunction gates. Fixed alongside decimalOp.
|
|
42536
|
-
isNSFunctionStringOp(value) || isNSFunctionDecimalOp(value) || isNSFunctionMathOp(value) || isNSFunctionCount(value) || isNSFunctionVisitCount(value) || isNSFunctionHasVisited(value) || isNSFunctionVectorConstructor(value) || isNSFunctionImageSlice(value) || isNSFunctionVariantInitialize(value) || isNSFunctionVariantApply(value) || isNSFunctionDeclaredConstructor(value);
|
|
42736
|
+
isNSFunctionStringOp(value) || isNSFunctionDecimalOp(value) || isNSFunctionMathOp(value) || isNSFunctionListRepeat(value) || isNSFunctionCount(value) || isNSFunctionVisitCount(value) || isNSFunctionHasVisited(value) || isNSFunctionVectorConstructor(value) || isNSFunctionImageSlice(value) || isNSFunctionVariantInitialize(value) || isNSFunctionVariantApply(value) || isNSFunctionDeclaredConstructor(value);
|
|
42537
42737
|
}
|
|
42538
42738
|
function isNSInstructionVariable(value) {
|
|
42539
42739
|
const v = value;
|
|
@@ -69347,6 +69547,25 @@ function evalDecimalMathOp(info, fn, scope, ctx) {
|
|
|
69347
69547
|
rethrowDecimalError(error);
|
|
69348
69548
|
}
|
|
69349
69549
|
}
|
|
69550
|
+
function evalListRepeat(info, scope, ctx) {
|
|
69551
|
+
const value = evalPointer(info.valuePointer, scope, ctx);
|
|
69552
|
+
const count = numberArg(
|
|
69553
|
+
evalPointer(info.countPointer, scope, ctx),
|
|
69554
|
+
"List.Repeat count"
|
|
69555
|
+
);
|
|
69556
|
+
if (count < 0) {
|
|
69557
|
+
throw new NSGetterRuntimeError(
|
|
69558
|
+
`List.Repeat count must be non-negative; got ${count}.`
|
|
69559
|
+
);
|
|
69560
|
+
}
|
|
69561
|
+
consumeBudget(
|
|
69562
|
+
ctx,
|
|
69563
|
+
"producedCollectionEntries",
|
|
69564
|
+
count,
|
|
69565
|
+
"produced collection entry"
|
|
69566
|
+
);
|
|
69567
|
+
return new Array(count).fill(value);
|
|
69568
|
+
}
|
|
69350
69569
|
function stringifyForInterp(v) {
|
|
69351
69570
|
if (v === null || v === void 0) return "";
|
|
69352
69571
|
if (typeof v === "string") return v;
|
|
@@ -69868,6 +70087,8 @@ function evalFunction(fn, scope, ctx) {
|
|
|
69868
70087
|
}
|
|
69869
70088
|
case "mathOp" /* mathOp */:
|
|
69870
70089
|
return evalMathOp(fn.info, scope, ctx);
|
|
70090
|
+
case "listRepeat" /* listRepeat */:
|
|
70091
|
+
return evalListRepeat(fn.info, scope, ctx);
|
|
69871
70092
|
case "stringOp" /* stringOp */: {
|
|
69872
70093
|
const receiver = evalPointer(fn.info.receiverPointer, scope, ctx);
|
|
69873
70094
|
if (typeof receiver !== "string") {
|
|
@@ -107138,6 +107359,7 @@ function createCliNeoScriptContext(options) {
|
|
|
107138
107359
|
const members = [...options.documents.members];
|
|
107139
107360
|
const vm = {
|
|
107140
107361
|
project: options.documents.project,
|
|
107362
|
+
projectFiles: [...options.documents.projectFiles ?? []],
|
|
107141
107363
|
members,
|
|
107142
107364
|
classes: [...options.documents.classes],
|
|
107143
107365
|
enums: [...options.documents.enums],
|
|
@@ -107157,7 +107379,9 @@ function createCliNeoScriptContext(options) {
|
|
|
107157
107379
|
...options.functionReturnTypeInfo ? { functionReturnTypeInfo: options.functionReturnTypeInfo } : {},
|
|
107158
107380
|
...options.functionArguments ? { functionArguments: options.functionArguments } : {},
|
|
107159
107381
|
...options.functionDeferred !== void 0 ? { functionDeferred: options.functionDeferred } : {},
|
|
107160
|
-
...options.functionName ? { functionName: options.functionName } : {}
|
|
107382
|
+
...options.functionName ? { functionName: options.functionName } : {},
|
|
107383
|
+
...options.documents.variants?.length ? { variants: [...options.documents.variants] } : {},
|
|
107384
|
+
...options.documents.variantFolders?.length ? { variantFolders: [...options.documents.variantFolders] } : {}
|
|
107161
107385
|
});
|
|
107162
107386
|
if (!options.manifest) return compilerContext;
|
|
107163
107387
|
const projection = projectSchemaManifest(options.manifest, {
|
|
@@ -107796,11 +108020,14 @@ function readDocumentArrays(raw) {
|
|
|
107796
108020
|
}
|
|
107797
108021
|
return {
|
|
107798
108022
|
project: raw.project,
|
|
108023
|
+
projectFiles: arrayOf2("projectFiles"),
|
|
107799
108024
|
members: arrayOf2("members"),
|
|
107800
108025
|
classes: arrayOf2("classes"),
|
|
107801
108026
|
constructors: arrayOf2("constructors"),
|
|
107802
108027
|
enums: arrayOf2("enums"),
|
|
107803
108028
|
interfaces: arrayOf2("interfaces"),
|
|
108029
|
+
variants: arrayOf2("variants"),
|
|
108030
|
+
variantFolders: arrayOf2("variantFolders"),
|
|
107804
108031
|
values: arrayOf2("values"),
|
|
107805
108032
|
dialogues: arrayOf2("dialogues"),
|
|
107806
108033
|
dialogueRecords: arrayOf2("dialogueRecords"),
|
|
@@ -107808,7 +108035,6 @@ function readDocumentArrays(raw) {
|
|
|
107808
108035
|
dialogueGroups: arrayOf2("dialogueGroups"),
|
|
107809
108036
|
priorityGroups: arrayOf2("priorityGroups"),
|
|
107810
108037
|
migrations: arrayOf2("migrations"),
|
|
107811
|
-
projectFiles: arrayOf2("projectFiles"),
|
|
107812
108038
|
localizationConfig: raw.localizationConfig,
|
|
107813
108039
|
localizedTexts: arrayOf2("localizedTexts")
|
|
107814
108040
|
};
|
|
@@ -108411,12 +108637,19 @@ async function runScript(workspace, command, options, dependencies = {}) {
|
|
|
108411
108637
|
unit,
|
|
108412
108638
|
code: source
|
|
108413
108639
|
});
|
|
108414
|
-
const
|
|
108640
|
+
const compilerProject = {
|
|
108415
108641
|
project: document.project,
|
|
108642
|
+
projectFiles: document.projectFiles,
|
|
108416
108643
|
members: document.members,
|
|
108417
108644
|
classes: document.classes,
|
|
108645
|
+
constructors: document.constructors,
|
|
108418
108646
|
enums: document.enums,
|
|
108419
108647
|
interfaces: document.interfaces,
|
|
108648
|
+
variants: document.variants,
|
|
108649
|
+
variantFolders: document.variantFolders
|
|
108650
|
+
};
|
|
108651
|
+
const compileContext = {
|
|
108652
|
+
...compilerProject,
|
|
108420
108653
|
thisClass,
|
|
108421
108654
|
returnTypeInfo: parseReturns(options.returns, document),
|
|
108422
108655
|
dialogueContext: null
|
|
@@ -108465,11 +108698,7 @@ async function runScript(workspace, command, options, dependencies = {}) {
|
|
|
108465
108698
|
}
|
|
108466
108699
|
compiled = compileNeoScriptBodyOrThrow(
|
|
108467
108700
|
() => compileNSFunction(source, {
|
|
108468
|
-
|
|
108469
|
-
members: document.members,
|
|
108470
|
-
classes: document.classes,
|
|
108471
|
-
enums: document.enums,
|
|
108472
|
-
interfaces: document.interfaces,
|
|
108701
|
+
...compilerProject,
|
|
108473
108702
|
thisClass,
|
|
108474
108703
|
returnTypeInfo: nsFunctionDefinition.returnTypeInfo,
|
|
108475
108704
|
argumentTypes: nsFunctionDefinition.argumentTypes,
|
|
@@ -108485,11 +108714,7 @@ async function runScript(workspace, command, options, dependencies = {}) {
|
|
|
108485
108714
|
}
|
|
108486
108715
|
compiled = compileNeoScriptBodyOrThrow(
|
|
108487
108716
|
() => compileNSSetter(source, {
|
|
108488
|
-
|
|
108489
|
-
members: document.members,
|
|
108490
|
-
classes: document.classes,
|
|
108491
|
-
enums: document.enums,
|
|
108492
|
-
interfaces: document.interfaces,
|
|
108717
|
+
...compilerProject,
|
|
108493
108718
|
thisClass,
|
|
108494
108719
|
valueTypeInfo: resolveScriptPropertyReturnTypeInfo(
|
|
108495
108720
|
setterMember,
|
|
@@ -112398,10 +112623,27 @@ async function buildPostPushCompileSchema(workspace, status) {
|
|
|
112398
112623
|
}
|
|
112399
112624
|
return {
|
|
112400
112625
|
project,
|
|
112626
|
+
projectFiles: [...bucket("project-file").values()],
|
|
112401
112627
|
members: [...bucket("member").values()],
|
|
112402
112628
|
classes: [...bucket("class").values()],
|
|
112629
|
+
constructors: [...bucket("constructor").values()],
|
|
112403
112630
|
enums: [...bucket("enum").values()],
|
|
112404
|
-
interfaces: [...bucket("interface").values()]
|
|
112631
|
+
interfaces: [...bucket("interface").values()],
|
|
112632
|
+
variants: [...bucket("variant").values()],
|
|
112633
|
+
variantFolders: [...bucket("variant-folder").values()]
|
|
112634
|
+
};
|
|
112635
|
+
}
|
|
112636
|
+
function postPushCompilerProject(schema) {
|
|
112637
|
+
return {
|
|
112638
|
+
project: schema.project,
|
|
112639
|
+
projectFiles: schema.projectFiles,
|
|
112640
|
+
members: schema.members,
|
|
112641
|
+
classes: schema.classes,
|
|
112642
|
+
constructors: schema.constructors,
|
|
112643
|
+
enums: schema.enums,
|
|
112644
|
+
interfaces: schema.interfaces,
|
|
112645
|
+
variants: schema.variants,
|
|
112646
|
+
variantFolders: schema.variantFolders
|
|
112405
112647
|
};
|
|
112406
112648
|
}
|
|
112407
112649
|
function containingClass(schema, memberId) {
|
|
@@ -112433,11 +112675,7 @@ function compileNSPropertyChange(schema, memberData, locator) {
|
|
|
112433
112675
|
const code = memberData.code;
|
|
112434
112676
|
next.getter = compileNeoScriptBodyOrThrow(
|
|
112435
112677
|
() => compileNSGetter2(code, {
|
|
112436
|
-
|
|
112437
|
-
members: schema.members,
|
|
112438
|
-
classes: schema.classes,
|
|
112439
|
-
enums: schema.enums,
|
|
112440
|
-
interfaces: schema.interfaces,
|
|
112678
|
+
...postPushCompilerProject(schema),
|
|
112441
112679
|
thisClass,
|
|
112442
112680
|
returnTypeInfo,
|
|
112443
112681
|
dialogueContext: null,
|
|
@@ -112454,11 +112692,7 @@ function compileNSPropertyChange(schema, memberData, locator) {
|
|
|
112454
112692
|
const setterCode = memberData.setterCode;
|
|
112455
112693
|
next.setter = compileNeoScriptBodyOrThrow(
|
|
112456
112694
|
() => compileNSSetter2(setterCode, {
|
|
112457
|
-
|
|
112458
|
-
members: schema.members,
|
|
112459
|
-
classes: schema.classes,
|
|
112460
|
-
enums: schema.enums,
|
|
112461
|
-
interfaces: schema.interfaces,
|
|
112695
|
+
...postPushCompilerProject(schema),
|
|
112462
112696
|
thisClass,
|
|
112463
112697
|
valueTypeInfo: returnTypeInfo,
|
|
112464
112698
|
implicitMemberAccess: true,
|
|
@@ -112483,11 +112717,7 @@ function compileNSFunctionChange(schema, memberData, locator) {
|
|
|
112483
112717
|
const thisClass = containingClass(schema, memberData.id);
|
|
112484
112718
|
next.action = compileNeoScriptBodyOrThrow(
|
|
112485
112719
|
() => compileNSFunction2(code, {
|
|
112486
|
-
|
|
112487
|
-
members: schema.members,
|
|
112488
|
-
classes: schema.classes,
|
|
112489
|
-
enums: schema.enums,
|
|
112490
|
-
interfaces: schema.interfaces,
|
|
112720
|
+
...postPushCompilerProject(schema),
|
|
112491
112721
|
thisClass,
|
|
112492
112722
|
returnTypeInfo: contract.returnTypeInfo,
|
|
112493
112723
|
argumentTypes: contract.argumentTypes,
|
|
@@ -112827,11 +113057,7 @@ function compileMigrationAction(schema, migrationData, locator) {
|
|
|
112827
113057
|
const code = String(migrationData.code);
|
|
112828
113058
|
return compileNeoScriptBodyOrThrow(
|
|
112829
113059
|
() => compileNSVoidBody2(code, {
|
|
112830
|
-
|
|
112831
|
-
members: schema.members,
|
|
112832
|
-
classes: schema.classes,
|
|
112833
|
-
enums: schema.enums,
|
|
112834
|
-
interfaces: schema.interfaces,
|
|
113060
|
+
...postPushCompilerProject(schema),
|
|
112835
113061
|
thisClass,
|
|
112836
113062
|
dialogueContext: null,
|
|
112837
113063
|
migrationContext: true
|
|
@@ -112939,7 +113165,7 @@ var init_registry2 = __esm({
|
|
|
112939
113165
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
112940
113166
|
formatVersion: 3,
|
|
112941
113167
|
contractVersion: "3.13",
|
|
112942
|
-
cliVersion: "0.
|
|
113168
|
+
cliVersion: "0.34.0",
|
|
112943
113169
|
projectFileUploadBatchSize: 32,
|
|
112944
113170
|
documentRecords: {
|
|
112945
113171
|
member: {
|
|
@@ -116812,10 +117038,14 @@ async function runPendingMigrations(workspace, client, raw, migrations, onlyRef,
|
|
|
116812
117038
|
const compiled = pinned !== void 0 && pinned !== null ? pinned : compileNeoScriptBodyOrThrow(
|
|
116813
117039
|
() => compileNSVoidBody(migrationCode, {
|
|
116814
117040
|
project: document.project,
|
|
117041
|
+
projectFiles: document.projectFiles,
|
|
116815
117042
|
members: document.members,
|
|
116816
117043
|
classes: document.classes,
|
|
117044
|
+
constructors: document.constructors,
|
|
116817
117045
|
enums: document.enums,
|
|
116818
117046
|
interfaces: document.interfaces,
|
|
117047
|
+
variants: document.variants,
|
|
117048
|
+
variantFolders: document.variantFolders,
|
|
116819
117049
|
thisClass,
|
|
116820
117050
|
dialogueContext: null,
|
|
116821
117051
|
migrationContext: true
|
|
@@ -119534,7 +119764,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
119534
119764
|
async function main() {
|
|
119535
119765
|
const args = parseArgs(process.argv.slice(2));
|
|
119536
119766
|
if (args.command === "--version") {
|
|
119537
|
-
console.log("0.
|
|
119767
|
+
console.log("0.34.0");
|
|
119538
119768
|
return;
|
|
119539
119769
|
}
|
|
119540
119770
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@ description: >-
|
|
|
9
9
|
`@neocompose/cli` or `node cli/bin/neo.mjs` in the neo-compose repository.
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
<!-- reviewed-through-cli: 0.
|
|
12
|
+
<!-- reviewed-through-cli: 0.34.0 -->
|
|
13
13
|
|
|
14
14
|
# Neo Compose CLI
|
|
15
15
|
|
|
@@ -138,8 +138,8 @@ completely before editing:
|
|
|
138
138
|
variant folders, partial animation overrides, segments, tracks, and NeoFlow
|
|
139
139
|
dialogues.
|
|
140
140
|
- [NeoScript](references/neoscript.md): inline bodies, snippets, nullability,
|
|
141
|
-
numeric builtins, loops, switch, try/catch, ownership, evaluation,
|
|
142
|
-
migrations.
|
|
141
|
+
numeric and list builtins, loops, switch, try/catch, ownership, evaluation,
|
|
142
|
+
and migrations.
|
|
143
143
|
- [Commands and synchronization](references/commands-and-sync.md): pull/push,
|
|
144
144
|
conflicts, low-level repair, branches, releases, and history.
|
|
145
145
|
- [CLI development](references/cli-development.md): implementation source of
|
|
@@ -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.34.0 -->
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -8,6 +8,7 @@ runtime ownership, evaluation, and migrations.
|
|
|
8
8
|
- Inline bodies and snippets
|
|
9
9
|
- Nullability and ownership
|
|
10
10
|
- Numeric builtins
|
|
11
|
+
- List builtins
|
|
11
12
|
- Conditional and logical operators
|
|
12
13
|
- Loops and transfer
|
|
13
14
|
- Switch
|
|
@@ -127,6 +128,31 @@ enum, parameter, or local may shadow it. Qualified members use their owner's
|
|
|
127
128
|
namespace and may be named `Math`; access one as `this.Math` or
|
|
128
129
|
`SomeValue.Math` without colliding with the builtin qualifier.
|
|
129
130
|
|
|
131
|
+
## List builtins
|
|
132
|
+
|
|
133
|
+
Use `List.Repeat(value, count)` to build a list of `count` copies of a value
|
|
134
|
+
instead of hand-counting a literal or looping around `Add`:
|
|
135
|
+
|
|
136
|
+
```neo
|
|
137
|
+
List<int> scores = List.Repeat(0, 10);
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
The entry type is inferred from the value and joined with the assignment
|
|
141
|
+
context, exactly like a list literal, so assigning `List.Repeat(0, 4)` to a
|
|
142
|
+
`List<float>` widens the entries to `float`. Never spell type arguments on the
|
|
143
|
+
qualifier: `List<int>.Repeat(0, 3)` is an error, and bare `List` is a
|
|
144
|
+
qualifier, not a value.
|
|
145
|
+
|
|
146
|
+
`count` must be an `int` — a `float` count is a compile error, and a negative
|
|
147
|
+
count fails at runtime with `List.Repeat count must be non-negative; got
|
|
148
|
+
{count}.`. A count of `0` produces an empty `List<T>` whose entry type is
|
|
149
|
+
still known. The value is evaluated exactly once, then the count exactly once,
|
|
150
|
+
so side effects happen once regardless of `count`, and every entry is that one
|
|
151
|
+
value: for a reference-typed entry the same reference repeats `count` times.
|
|
152
|
+
Materializing the list charges `count` to the shared collection-entries
|
|
153
|
+
execution budget, so a runaway count fails with the existing budget error
|
|
154
|
+
before allocating.
|
|
155
|
+
|
|
130
156
|
## Conditional and logical operators
|
|
131
157
|
|
|
132
158
|
Use `condition ? whenTrue : whenFalse` for a value chosen by a condition:
|