Put one item into a list, a struct staying whole, with Add item (#250)

A list could only grow through Join lists, and that takes its b apart:
a struct becomes one item per field and a list is joined. A list of
structs such as loot could not grow at all.

- Add item returns a new list with value as exactly one more item. A
  struct or a list goes in whole. The list that came in is left alone,
  like with Set item.
- index -1 or unset appends. Otherwise the item goes in before that
  index. An index outside the list appends, so the value is not lost.
- The rule that an item takes the kind of its slot moved out of Set item
  into fitToSlot. Both nodes use it, Set item behaves as before.
- No e2e check and no browser look. The node is covered by unit tests.

Tests:
- ./check.sh: 180 files, 2634 tests, CHECK EXIT 0
- 7 catalog cases, 4 cases in list-of-structs.test.ts, and index in the
  whole-number inputs of texture-kind.test.ts
- Counter-check: taking the value apart like Join lists fails 3 tests
- This commit alone: tsc and the three touched unit files pass
  (337 tests)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-09-27 21:07:04 +02:00
1 parent cb8a2d029a
commit b90b62886b
6 files changed
+102 -5

No files matched your search

+24
View File
@@ -1,4 +1,5 @@
import { describe, expect, it } from 'vitest';
import { AddItem } from '../../src/core/graph/nodes/data/AddItem';
import { Fill } from '../../src/core/graph/nodes/data/Fill';
import { IndexOf } from '../../src/core/graph/nodes/data/IndexOf';
import { ItemAt } from '../../src/core/graph/nodes/data/ItemAt';
@@ -130,6 +131,12 @@ describe('the list nodes with tagged items', () => {
result: [tagged('texture', 'b')],
});
});
it('adds a plain id to a list of pictures as a picture', () => {
expect(run(AddItem, { list: [tagged('texture', 'a')], value: 'b', index: -1 })).toEqual({
result: [tagged('texture', 'a'), tagged('texture', 'b')],
});
});
});
describe('the list nodes with struct items', () => {
@@ -148,6 +155,23 @@ describe('the list nodes with struct items', () => {
expect(run(IndexOf, { list: cells([1, 2]), value: { x: 9, y: 9 } })).toEqual({ index: -1 });
});
/** `Join lists` would take the struct apart into its field values. */
it('adds a struct as one whole item', () => {
expect(run(AddItem, { list: cells([1, 2]), value: { x: 3, y: 4 }, index: -1 })).toEqual({
result: cells([1, 2], [3, 4]),
});
});
it('adds a struct to an empty list as one whole item', () => {
expect(run(AddItem, { list: [], value: { x: 3, y: 4 }, index: -1 })).toEqual({ result: cells([3, 4]) });
});
it('leaves a number a number beside structs, since a mixed list has no kind to keep', () => {
expect(run(AddItem, { list: [7, { x: 1, y: 2 }], value: 8, index: -1 })).toEqual({
result: [7, { x: 1, y: 2 }, 8],
});
});
it('fills a list with a struct', () => {
expect(run(Fill, { value: { x: 1, y: 2 }, count: 2 })).toEqual({ result: cells([1, 2], [1, 2]) });
});
+29
View File
@@ -728,6 +728,35 @@ const CASES: Record<string, Case[]> = {
outputs: { result: [1, 2] },
},
],
AddItem: [
{ name: 'appends by default', inputs: { list: [1, 2], value: 3 }, outputs: { result: [1, 2, 3] } },
{
name: 'inserts before index',
inputs: { list: [1, 2, 3], value: 9, index: 1 },
outputs: { result: [1, 9, 2, 3] },
},
{
name: 'index equal to the length appends',
inputs: { list: [1, 2], value: 9, index: 2 },
outputs: { result: [1, 2, 9] },
},
{
name: 'an index outside the list appends instead of dropping the value',
inputs: { list: [1, 2], value: 9, index: 7 },
outputs: { result: [1, 2, 9] },
},
{
name: 'leaves the list it was given untouched – a graph may hold it elsewhere',
inputs: { list: Object.freeze([1, 2]), value: 3 },
outputs: { result: [1, 2, 3] },
},
{
name: 'a list goes in as one item, not joined',
inputs: { list: [[1]], value: [2, 3] },
outputs: { result: [[1], [2, 3]] },
},
{ name: 'an unset list starts empty', inputs: { value: 5 }, outputs: { result: [5] } },
],
SubList: [
{
name: 'takes count items from start',
+1
View File
@@ -123,6 +123,7 @@ describe('the whole-number inputs', () => {
const whole = [
['ItemAt', 'index'],
['SetItem', 'index'],
['AddItem', 'index'],
['SubList', 'start'],
['SubList', 'count'],
['Fill', 'count'],