@neocompose/cli 0.85.0 → 0.87.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 +22 -0
- package/dist/neo-runtime.mjs +82539 -73279
- package/dist/test-worker.mjs +6726 -1376
- package/package.json +1 -1
- package/skills/neocompose-cli/SKILL.md +1 -1
- package/skills/neocompose-cli/references/cli-development.md +1 -1
- package/skills/neocompose-cli/references/declarations-and-construction.md +67 -0
- package/skills/neocompose-cli/references/neoscript.md +161 -26
package/package.json
CHANGED
|
@@ -129,7 +129,7 @@ wrappers.
|
|
|
129
129
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
130
130
|
|
|
131
131
|
```html
|
|
132
|
-
<!-- reviewed-through-cli: 0.
|
|
132
|
+
<!-- reviewed-through-cli: 0.87.0 -->
|
|
133
133
|
```
|
|
134
134
|
|
|
135
135
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -8,6 +8,7 @@ constructors, and construction-time settlement.
|
|
|
8
8
|
- Declaration rules
|
|
9
9
|
- Annotations and settings
|
|
10
10
|
- Member and relation rules
|
|
11
|
+
- Function overloads
|
|
11
12
|
- Computed initializers and declared constructors
|
|
12
13
|
- Required constructors and settlement
|
|
13
14
|
- Inheritance construction
|
|
@@ -61,6 +62,13 @@ it may extend another class but cannot be extended, cannot also be abstract,
|
|
|
61
62
|
and can only be sealed while it has no subclasses. Interfaces can declare type
|
|
62
63
|
parameters and pass arguments to the interfaces they extend; see Interface
|
|
63
64
|
members.
|
|
65
|
+
A `closed` class is implicitly abstract and defines an exhaustive subtype
|
|
66
|
+
family within the project version. Do not combine `closed` with `abstract` or
|
|
67
|
+
`sealed`. Descendants remain open unless explicitly sealed or closed. Every
|
|
68
|
+
generic parameter of a direct subclass must appear in its base construction.
|
|
69
|
+
Changing the family requires recompilation of its switch-expression consumers.
|
|
70
|
+
Generated Unity C# uses an abstract class; C# 15 is not required.
|
|
71
|
+
|
|
64
72
|
A read-only override may narrow a class or interface contract to an assignable
|
|
65
73
|
class or derived interface, including a non-null value for a nullable contract.
|
|
66
74
|
Generated Unity C# keeps the inherited property type for Mono compatibility;
|
|
@@ -393,6 +401,11 @@ empty set.
|
|
|
393
401
|
public NeoAction<int> OnDamaged = [PlayHitFlash, ApplyDamage];
|
|
394
402
|
```
|
|
395
403
|
|
|
404
|
+
A nested field initializer such as `Watcher = new() { OnTally = [Handle] }`
|
|
405
|
+
can target an inherited generic method on its enclosing instance. The listener
|
|
406
|
+
uses that owning instance, including when declaration defaults are materialized.
|
|
407
|
+
Explicit receiver targets keep their captured instance.
|
|
408
|
+
|
|
396
409
|
An instance-bound listener reachable through a stable project root keeps its
|
|
397
410
|
receiver path, for example `public NeoAction<int> OnDamaged =
|
|
398
411
|
[root.Assets.OnDamage];`. Pull refuses a bound receiver that has no
|
|
@@ -423,6 +436,44 @@ For world layer links, instantiate a project-authored descendant of
|
|
|
423
436
|
`targetLayer` relation. The relation is the complete binding; do not add
|
|
424
437
|
value-level target metadata.
|
|
425
438
|
|
|
439
|
+
### Function overloads
|
|
440
|
+
|
|
441
|
+
A class may declare several functions with one name when their parameter
|
|
442
|
+
types differ:
|
|
443
|
+
|
|
444
|
+
```neo
|
|
445
|
+
class Inventory {
|
|
446
|
+
public int Add(Item item) { return 1; }
|
|
447
|
+
public int Add(Item item, int count) { return count; }
|
|
448
|
+
public int Add(List<Item> items) { return items.Count; }
|
|
449
|
+
}
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
A class's overload set for a name holds every function of that name it
|
|
453
|
+
declares or inherits. A derived class adding `Add(Item item, int count)` next
|
|
454
|
+
to an inherited `Add(Item item)` overloads it. Static and instance functions,
|
|
455
|
+
NSFunctions and native functions, and generic and non-generic functions mix
|
|
456
|
+
freely.
|
|
457
|
+
|
|
458
|
+
Every two functions in a set need different parameter types after dropping
|
|
459
|
+
nullability, substituting base type arguments, and renaming function type
|
|
460
|
+
parameters by position. So `Add(Item)` and `Add(Item?)` collide, and so do
|
|
461
|
+
`F()` and `F<T>()`. A `Find<T = Item>(T value)` occupies `Find(Item)`.
|
|
462
|
+
|
|
463
|
+
At most one function per name and class may be dispatched: `abstract`,
|
|
464
|
+
`virtual`, `override`, or an interface implementation. Overrides target that
|
|
465
|
+
one function. Interfaces can't overload, so an interface declares each
|
|
466
|
+
function name once. When several class functions share an interface
|
|
467
|
+
function's name, the one whose parameters match implements it.
|
|
468
|
+
|
|
469
|
+
`Equals` and names a platform class or interface declares, such as
|
|
470
|
+
`OnTriggerEnter2D` and lifecycle hooks, can't be overloaded. A function still
|
|
471
|
+
can't share a name with a field, property, getter, or action.
|
|
472
|
+
|
|
473
|
+
Overloads generate C# overloads with the same name. A plain overload stores
|
|
474
|
+
under the key `Name#<memberId>`. A dispatched or lone function keeps the key
|
|
475
|
+
`Name`, so a project without overloads stores exactly what it did before.
|
|
476
|
+
|
|
426
477
|
## Computed initializers and declared constructors
|
|
427
478
|
|
|
428
479
|
Inherited member initializers read parameters from the constructor that declared
|
|
@@ -704,3 +755,19 @@ A semicolon after `Main = ...` inside the initializer is invalid. Editor and CLI
|
|
|
704
755
|
diagnostics highlight that separator in the authored file, including global,
|
|
705
756
|
static member, and protected root initializers. Statement semicolons inside
|
|
706
757
|
function or delegate bodies remain valid.
|
|
758
|
+
|
|
759
|
+
## Stored tuples
|
|
760
|
+
|
|
761
|
+
Declare fixed positions with ordinary types and optional labels:
|
|
762
|
+
|
|
763
|
+
```neo
|
|
764
|
+
public (int Count, bool Enabled) State = (3, true);
|
|
765
|
+
public (int, (string Label, int Count))? Detail = null;
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
Each position has a derived member descriptor. Do not author descriptor IDs.
|
|
769
|
+
Changing a label preserves its position and identity. Changing arity or moving
|
|
770
|
+
stored positions requires migrating existing values. A required tuple without
|
|
771
|
+
a default must be supplied during construction; it has no automatic zero tuple.
|
|
772
|
+
Owned class and collection elements keep the ordinary single-owner rule. Use
|
|
773
|
+
an explicit reference or clone when another stored value already owns them.
|
|
@@ -7,7 +7,9 @@ runtime ownership, evaluation, and migrations.
|
|
|
7
7
|
|
|
8
8
|
- Inline bodies and snippets
|
|
9
9
|
- Nullability and ownership
|
|
10
|
+
- Tuples and destructuring
|
|
10
11
|
- References
|
|
12
|
+
- Overloaded calls
|
|
11
13
|
- Numeric builtins
|
|
12
14
|
- Collection builtins
|
|
13
15
|
- Conditional and logical operators
|
|
@@ -148,16 +150,17 @@ Functions, natives and interface functions can declare their own type
|
|
|
148
150
|
parameters after the name, each with an optional constraint and default:
|
|
149
151
|
|
|
150
152
|
```neo
|
|
151
|
-
public static T? FirstOf<T extends Item = Item>(List<
|
|
152
|
-
foreach (Item item in items) {
|
|
153
|
-
if (item is T match) return match;
|
|
154
|
-
}
|
|
155
|
-
return null;
|
|
156
|
-
}
|
|
153
|
+
public static T? FirstOf<T extends Item = Item>(List<T> items) => items.FirstOrDefault();
|
|
157
154
|
```
|
|
158
155
|
|
|
159
156
|
A call writes every type argument or omits the defaulted tail
|
|
160
|
-
(`FirstOf<Seed>(items)`, `FirstOf(items)`)
|
|
157
|
+
(`FirstOf<Seed>(items)`, `FirstOf(items)`). When `<...>` is omitted, supplied
|
|
158
|
+
arguments infer the function's type arguments. Lambda inputs bind first so their
|
|
159
|
+
returns can infer output parameters, as in `Map(seed, (value) => value.Price)`.
|
|
160
|
+
Defaults fill parameters with no inference evidence. The destination/expected
|
|
161
|
+
return type does not provide evidence. Explicit `<...>` keeps explicit/default
|
|
162
|
+
binding and does not infer omitted trailing arguments. Conflicting types require
|
|
163
|
+
explicit arguments; inference does not invent a shared ancestor for siblings. Function type
|
|
161
164
|
parameters take no `@id`, and an override declares the same count, constraints
|
|
162
165
|
and defaults, though it may rename them.
|
|
163
166
|
|
|
@@ -329,6 +332,30 @@ Save, Session, Setter, or otherwise writable. A constructor writes only its
|
|
|
329
332
|
`this` instance. A writable structured-leaf field still inherits the receiver's
|
|
330
333
|
effective storage restrictions.
|
|
331
334
|
|
|
335
|
+
## Tuples and destructuring
|
|
336
|
+
|
|
337
|
+
A tuple has at least two ordered elements. Labels are optional and explicit;
|
|
338
|
+
`Item1`, `Item2`, and later positional aliases always work. Labels do not affect
|
|
339
|
+
type identity. Slots are immutable, so replace a whole tuple to change a value.
|
|
340
|
+
Referenced objects retain their normal permissions and identity.
|
|
341
|
+
|
|
342
|
+
```neo
|
|
343
|
+
(int Row, int Col) position = (Row: 2, Col: 3);
|
|
344
|
+
var (row, col) = position;
|
|
345
|
+
(int first, (bool enabled, int _)) = (1, (true, 9));
|
|
346
|
+
var score = positions.Select(((r, c)) => r + c);
|
|
347
|
+
foreach (var (key, value) in weights) { Debug.Log(key); }
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
`((r, c)) =>` accepts one tuple; `(r, c) =>` accepts two parameters. Recursive
|
|
351
|
+
patterns work in declarations, loop bindings, and tuple lambda parameters. `_`
|
|
352
|
+
discards a position. Assignment deconstruction is not supported.
|
|
353
|
+
|
|
354
|
+
Tuple equality compares corresponding values recursively. Decimal scale does
|
|
355
|
+
not affect equality. Classes, collections, and explicit references compare by
|
|
356
|
+
identity. `Contains`, `IndexOf`, `Remove`, and `ToSet` use the same rule.
|
|
357
|
+
Nullable tuples use `(int, int)?`; nullable elements use `(int?, int)`.
|
|
358
|
+
|
|
332
359
|
## References
|
|
333
360
|
|
|
334
361
|
`Reference<T>` names one stored row. `T` can be any value type, including
|
|
@@ -382,14 +409,73 @@ The target row decides every write. Writing an asset-owned target errors, and a
|
|
|
382
409
|
`OnChanged` listeners fire when it rebinds and when its target's value changes.
|
|
383
410
|
Inside a generic body, `Reference<T>` takes the category of `T`'s binding.
|
|
384
411
|
|
|
412
|
+
## Overloaded calls
|
|
413
|
+
|
|
414
|
+
A call to an overloaded function picks one overload at compile time from its
|
|
415
|
+
arguments. Candidates are every overload the receiver's type sees, across all
|
|
416
|
+
inheritance levels; a type qualifier takes static ones, an instance receiver
|
|
417
|
+
instance ones. An overload applies when the argument count fits its required
|
|
418
|
+
and default parameters and each argument converts to its parameter. Lambdas,
|
|
419
|
+
method groups, `null`, collection literals, and `.North` apply by shape.
|
|
420
|
+
|
|
421
|
+
Among applicable overloads, the one whose parameters are closer to the
|
|
422
|
+
argument types wins: an exact type beats a conversion, and `Bag` beats `Item`
|
|
423
|
+
when `Bag : Item`. On a tie, the overload filling no defaults wins, then the
|
|
424
|
+
non-generic one. Otherwise the call is ambiguous: `Scale(float)` and
|
|
425
|
+
`Scale(decimal)` can't take an `int`, so write `2.0` or `2m`. A generic
|
|
426
|
+
overload takes explicit type arguments, or infers them from the arguments the
|
|
427
|
+
way a lone generic call does, with defaults filling parameters nothing infers.
|
|
428
|
+
An overload whose type arguments can't be inferred isn't a candidate: beside
|
|
429
|
+
`F(int a, string b)`, `F<T>(T a, T b)` takes `F(1, 2)` but not `F(1, "a")`.
|
|
430
|
+
|
|
431
|
+
A method group picks the overload whose parameters match the target delegate
|
|
432
|
+
type exactly, in assignments, `+=`, `OnChanged`, `@listeners`, and delegate
|
|
433
|
+
arguments. `var f = Read` is an error when `Read` is overloaded; give `f` a
|
|
434
|
+
delegate type.
|
|
435
|
+
|
|
436
|
+
Pass the delegate type to mock or spy on an overloaded function:
|
|
437
|
+
|
|
438
|
+
```neo
|
|
439
|
+
var quote = mock.function<NeoDelegate<int, Item, int>>(Pricing.Quote);
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Script evaluation selects an overload with a signature:
|
|
443
|
+
`neo script eval --function "Inventory.Add(Item, int)"`.
|
|
444
|
+
|
|
385
445
|
## Numeric types
|
|
386
446
|
|
|
387
|
-
`int`
|
|
388
|
-
|
|
389
|
-
|
|
447
|
+
`int` stores whole numbers and division truncates toward zero. Ordinary integer
|
|
448
|
+
arithmetic retains the precision of the stored number. `float` literals, stored
|
|
449
|
+
values, and every float arithmetic step round to 32 bits, matching Unity.
|
|
390
450
|
`decimal` is exact base-10 and is the only type to use for currency or other
|
|
391
451
|
values that must not drift.
|
|
392
452
|
|
|
453
|
+
## Bitwise integer operators
|
|
454
|
+
|
|
455
|
+
Use `~`, `&`, `^`, `|`, `<<`, `>>`, and `>>>` with non-nullable `int` operands.
|
|
456
|
+
The compound forms are `&=`, `^=`, `|=`, `<<=`, `>>=`, and `>>>=`.
|
|
457
|
+
Enums, bools, float literals such as `1.0`, and decimals are not accepted.
|
|
458
|
+
Use `Set<Enum>` for enum membership.
|
|
459
|
+
|
|
460
|
+
```neo
|
|
461
|
+
int mask = (region << 8) | (tile & 255);
|
|
462
|
+
bool hasEast = (mask & 2) != 0;
|
|
463
|
+
mask &= ~2;
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
Each operand wraps modulo 2^32 into signed int32 at the bitwise boundary.
|
|
467
|
+
Every result is signed int32. Ordinary integer arithmetic is unchanged.
|
|
468
|
+
Shift counts use their low five bits: 32 means 0, 33 means 1, and -1 means 31.
|
|
469
|
+
`>>` extends the sign bit; `>>>` fills with zero but still returns a signed
|
|
470
|
+
result. Thus `-1 >>> 1` is 2147483647 and `-1 >>> 0` is -1.
|
|
471
|
+
Operands evaluate once, left to right. A compound assignment captures its
|
|
472
|
+
target and reads its old value before evaluating the right operand.
|
|
473
|
+
|
|
474
|
+
Precedence from tightest to loosest: unary, switch expressions, multiplication/division/remainder,
|
|
475
|
+
addition/subtraction, shifts, comparisons, equality and `is`, `&`, `^`, `|`,
|
|
476
|
+
`&&`, `||`, `??`, then `?:`. Binary bitwise operators associate left to right.
|
|
477
|
+
Keep shift characters contiguous: `x >> 1` is valid; `x > > 1` is not.
|
|
478
|
+
|
|
393
479
|
## Numeric builtins
|
|
394
480
|
|
|
395
481
|
Use the `Math` namespace for numeric utilities with C# names and C# semantics:
|
|
@@ -692,33 +778,82 @@ switch (direction) {
|
|
|
692
778
|
Permit `int`, `string`, `bool`, enum, and nullable forms. Stack labels when
|
|
693
779
|
they share one body. End every reachable non-empty section with `break`,
|
|
694
780
|
`return`, `throw`, or `continue` when a surrounding loop makes it valid.
|
|
695
|
-
Do not use implicit fallthrough,
|
|
696
|
-
|
|
781
|
+
Do not use implicit fallthrough, pattern cases, guards, or `goto` in statement switches.
|
|
782
|
+
|
|
783
|
+
### Switch expressions
|
|
784
|
+
|
|
785
|
+
Use `value switch { pattern => result, ... }` to produce one value. Arms may
|
|
786
|
+
use scalar/enum constants, `null`, type patterns (`Damage`), declaration
|
|
787
|
+
patterns (`Damage damage`), or `_`. A declaration binding is scoped to its
|
|
788
|
+
arm's optional `when` guard and result. Patterns and guards run in order; the
|
|
789
|
+
selector runs once and only the chosen result runs.
|
|
790
|
+
|
|
791
|
+
```neo
|
|
792
|
+
closed class HitResult {}
|
|
793
|
+
sealed class Miss : HitResult {}
|
|
794
|
+
sealed class Damage : HitResult { public int Amount = 0; }
|
|
795
|
+
class Combat {
|
|
796
|
+
public string Describe(HitResult result) => result switch {
|
|
797
|
+
Miss => "miss",
|
|
798
|
+
Damage damage when damage.Amount > 10 => "strong hit",
|
|
799
|
+
Damage damage => $"{damage.Amount}",
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
Every switch expression must be exhaustive. Handle every bool/enum option or
|
|
805
|
+
closed-class branch, plus null for nullable input. Other types require a
|
|
806
|
+
covering type or `_` fallback. A guard contributes no exhaustive coverage
|
|
807
|
+
unless it is literally `true`. Missing and unreachable cases are compile
|
|
808
|
+
errors. Adding a new subtype recompiles affected consumers.
|
|
809
|
+
|
|
810
|
+
Result arms must fit the expected type or have a common assignable type.
|
|
811
|
+
Property, relational, list, and positional patterns are unsupported. Pattern
|
|
812
|
+
cases in statement switches remain unsupported. Install the matching Unity
|
|
813
|
+
SDK before exporting the new switch-expression IR; older SDKs reject it.
|
|
697
814
|
|
|
698
|
-
##
|
|
815
|
+
## Structured errors and finally
|
|
699
816
|
|
|
700
|
-
|
|
817
|
+
Throw a required string or any `NeoError` subclass. String throws create
|
|
818
|
+
`NeoError` values. Each error has a required read-only `Message`, including
|
|
819
|
+
an empty message. Derive ordinary classes from `NeoError` to carry typed data.
|
|
701
820
|
|
|
702
821
|
```neo
|
|
703
822
|
try {
|
|
704
823
|
return GetUnsafe();
|
|
705
824
|
}
|
|
706
|
-
catch (
|
|
707
|
-
|
|
708
|
-
}
|
|
709
|
-
catch (string message) {
|
|
825
|
+
catch (NeoArgumentError error) when (error.Message != "") {
|
|
826
|
+
Report(error.Message);
|
|
710
827
|
throw;
|
|
711
828
|
}
|
|
829
|
+
catch (NeoError error) {
|
|
830
|
+
return Fallback();
|
|
831
|
+
}
|
|
832
|
+
finally {
|
|
833
|
+
ReleaseResource();
|
|
834
|
+
}
|
|
712
835
|
```
|
|
713
836
|
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
837
|
+
A try needs catches, a finally block, or both. Catch bindings are read-only.
|
|
838
|
+
Typed catches match subclasses, and `catch (string message)` matches every
|
|
839
|
+
ordinary error while binding its Message. An unfiltered base catch must follow
|
|
840
|
+
all catches it covers. Filters run before any intervening finally blocks,
|
|
841
|
+
including across calls. A false or failing filter continues the original search.
|
|
842
|
+
Bare `throw;` rethrows the original payload from a catch.
|
|
843
|
+
|
|
844
|
+
Finally runs on normal completion, return, break, continue, and ordinary errors.
|
|
845
|
+
The return value is evaluated before cleanup. An error escaping cleanup replaces
|
|
846
|
+
the pending error; an error caught inside cleanup does not. Return and loop
|
|
847
|
+
transfers cannot escape a finally block. A nested loop may break or continue.
|
|
848
|
+
Bare throw inside finally needs its own inner catch.
|
|
849
|
+
|
|
850
|
+
Runtime failures use `NeoNullReferenceError`, `NeoIndexOutOfRangeError`,
|
|
851
|
+
`NeoKeyNotFoundError`, `NeoArgumentError`, `NeoArithmeticError`, or
|
|
852
|
+
`NeoInvalidOperationError`. Unexpected native failures become `NeoHostError`
|
|
853
|
+
with Message `"Check logs for more details."`. Execution limits, unavailable
|
|
854
|
+
preview natives, cancellation, and invalid compiled data are noncatchable.
|
|
855
|
+
Suspended Unity calls retain cleanup until resumed; abandonment skips cleanup.
|
|
856
|
+
Completed writes are not rolled back. Install the matching SDK for schema 45.
|
|
722
857
|
|
|
723
858
|
## Debug output
|
|
724
859
|
|