Skip to content

phase 8b: typeinfo is_int / is_int64 + int|int64 disjunction spike#2764

Merged
borisbat merged 1 commit into
masterfrom
bbatkin/longarr-phase8b-int-int64-disjunction
May 20, 2026
Merged

phase 8b: typeinfo is_int / is_int64 + int|int64 disjunction spike#2764
borisbat merged 1 commit into
masterfrom
bbatkin/longarr-phase8b-int-int64-disjunction

Conversation

@borisbat
Copy link
Copy Markdown
Collaborator

Summary

Spike for the next big chunk of the 64-bit array/table widening project (PR-D, linq surface widening). The question this PR answers: can a function accept int | int64 as a single parameter signature and fork inside the body via static_if, so the ~10 linq functions targeted by PR-D widen with one signature each instead of doubled overloads?

Yes. def take_or(x : int | int64) already parses — the disjunction-parameter shape is used in tests/language/option_type.das for ref/auto resolution. What was missing was a clean dispatch predicate inside the body; stripped_typename(x) == "int" is a string-compare hack for something this prominent.

What changed

Two new typeinfo traits in src/ast/ast_infer_type.cpp, placed right after is_numeric and following the is_string pattern (baseType match + dim.size() == 0):

typeinfo is_int(x)   -> baseType == tInt   && dim.size() == 0
typeinfo is_int64(x) -> baseType == tInt64 && dim.size() == 0

Scope is intentionally surgical — is_int + is_int64 only, matching PR-D's immediate need. Sibling traits (is_uint, is_int8/16/32, etc.) can be added later when a real call site needs them.

Test plan

  • tests/long_array_table/test_int_int64_disjunction.das — three tests:
    • test_int_branch / test_int64_branchdef take_or(x : int | int64) with static_if (typeinfo is_int(x)) dispatch returns the right value for both call shapes
    • test_typeinfo_is_int_traitsstatic_assert matrix locks is_int / is_int64 against silent reverts (true for the matching type, false for the other and for uint)
  • tests/long_array_table/ full dir: 48/48 pass
  • tests/apply/, tests/language/: no regressions from the trait addition
  • Lint clean, formatter clean
  • Pre-push hook formatter --verify + lint pass

Unblocks

PR-D (linq surface widening — take/skip/element_at/chunk/last/single/...) can now use one int | int64 signature per function with static_if (typeinfo is_int(x)) inside the body, instead of doubling overloads.

🤖 Generated with Claude Code

Spike for the next big chunk of the 64-bit array/table widening project
(PR-D, linq surface). Question: can a function accept `int | int64` as
a single signature and fork inside the body with static_if, so the ~10
linq functions targeted by PR-D widen with one signature each instead
of doubled overloads?

Answer: yes -- `def take_or(x : int | int64)` already parses (the
disjunction-parameter shape was used in tests/language/option_type.das
for ref/auto resolution). What was missing was a clean dispatch
predicate; `stripped_typename(x) == "int"` is a string-compare hack
for something this prominent.

Adds two `typeinfo` traits in src/ast/ast_infer_type.cpp next to
`is_numeric`, following the `is_string` pattern (baseType match +
`dim.size() == 0`):

  typeinfo is_int(x)   -> baseType == tInt   && dim.size() == 0
  typeinfo is_int64(x) -> baseType == tInt64 && dim.size() == 0

tests/long_array_table/test_int_int64_disjunction.das pins both halves
(disjunction-parameter dispatch + the two new traits) with
static_assert type-contract probes so silent reverts on either side
flip the test red.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 20, 2026 18:20
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds targeted typeinfo traits for discriminating int vs int64 at compile time, enabling int | int64 disjunction parameters to be handled with a single signature and static_if dispatch (supporting upcoming 64-bit linq surface widening work).

Changes:

  • Added typeinfo is_int(...) and typeinfo is_int64(...) traits in the compiler’s typeinfo trait folding.
  • Added a new regression test covering int | int64 parameter dispatch and a static-assert “contract” matrix for the traits.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
tests/long_array_table/test_int_int64_disjunction.das New tests validating disjunction parameter branching via typeinfo is_int / is_int64.
src/ast/ast_infer_type.cpp Implements constant-folding support for new typeinfo traits is_int and is_int64.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/ast/ast_infer_type.cpp
@borisbat borisbat merged commit a6559aa into master May 20, 2026
30 checks passed
pull Bot pushed a commit to forksnd/daScript that referenced this pull request May 21, 2026
First commit on the longarr phase 8c branch. Widens the decs storage
type-level surface to int64 and rewrites the FixedArrayIterator C++
runtime to int64 sizes. This is preparation -- the actual >INT_MAX
runtime scenario is gated by the entityLookup resize cascade
(decsState.entityLookup |> resize(int(id_base) + count) caps total
entities at INT_MAX globally) and EntityId.id : uint. Both follow in
subsequent commits on this same branch before the PR opens.

Changes:

daslib/decs.das
  Archetype.size : int -> int64        (the audit's silent-corruption site)
  entityLookup tuple .index : int -> int64
  get_eid(... index : int) -> int64
  remove_entity(... di : int) -> int64
  decs_array(... capacity : int) -> int64 (routes through _i64 builder)
  entity_count() : int keeps int return + panics if total > INT_MAX
                  (mirrors length() / long_length() surface contract)
  long_entity_count() : int64 NEW -- int64-safe accessor
  for_eid_archetype invoke(blk, ..., int(lookup.index)) cast at boundary
  create_entities_from_cmp invoke(fill_blk, ..., int(eidx), ...) cast at boundary
  get_default_ro / get_optional cap at INT_MAX with panic guard before
                  passing to repeat/repeat_ref (functional.das int64
                  widening is a separate followup)
  Stride multiplications (eidx * c.stride, arch.size * c.stride, etc.)
                  pick up int64(c.stride) casts at every site
  Comparisons with literal 0 widened to 0_l
  range(arch.size) -> range64(0_l, arch.size)

daslib/decs_state.das
  EcsArchetypeView.size : int -> int64
  Switched _builtin_make_temp_array -> _i64 variant for the dump path

daslib/builtin.das
  each(a : auto(TT)[]) passes int64(typeinfo dim(a)) to the widened
  iterator binding -- the only other in-tree caller of
  _builtin_make_fixed_array_iterator besides decs.das.

C++ runtime (the "rewrite said iterator to use 64 bit" piece):
  include/daScript/simulate/runtime_array.h
    FixedArrayIterator::size           : uint32_t -> uint64_t
    SimNode_FixedArrayIterator::size   : uint32_t -> uint64_t
  include/daScript/simulate/aot_builtin.h
    builtin_make_fixed_array_iterator(... int size, ...) -> int64_t size
  src/builtin/module_builtin_runtime.cpp
    Same widening in the impl; negative size clamps to empty (same
    pattern as builtin_make_temp_array_i64).

Tests
  tests/decs/test_archetype.das
    Five comparison literals widened to *_l (existing tests, same logic).
  tests/decs/test_archetype_size_type.das NEW
    static_assert type-contract probes locking Archetype.size : int64,
    long_entity_count() : int64, entity_count() : int. Uses
    stripped_typename so the test doesn't depend on PR GaijinEntertainment#2764 (typeinfo
    is_int64) landing first.
  tests/decs/test_archetype_bulk_create_int64.das NEW
    Small-N (100K + 1K) runtime regression covering bulk-create + delete
    arithmetic neighbors. The genuine >INT_MAX memory-gated probe waits
    for the cascade widening to enable past-INT_MAX creation.

Test status: tests/decs/ 244/244 pass. tests/language/ 1003/1003 pass.
tests/long_array_table/ 45/45 pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
pull Bot pushed a commit to forksnd/daScript that referenced this pull request May 21, 2026
Closes the last int-only gaps in the daslib/builtin.das array surface
that prevent code from reaching insertion positions past INT_MAX. The
underlying C++ runtime (`__builtin_array_push` / `_push_zero` and
`__builtin_array_resize_i64`) has been int64-capable since the Phase 2+3
landings; only the daslang wrappers needed widening.

Widened (int -> int | int64 + static_if (typeinfo is_int(at)) dispatch,
so the int64 branch never pays an int64(at) ExprCall cost):
  * push(arr, value, at)               -- copy + move variants (lines 113, 126)
  * emplace(arr, var value, at)        -- line 224
  * push_clone(arr, value, at)         -- copy + move variants (lines 274, 287)
  * resize_and_init(arr, newSize)      -- + 2-arg initValue variant (lines 53, 69)

For resize_and_init, the static_if also picks the matching backing call
(__builtin_array_resize vs _i64), length() vs long_length(), range() vs
range64() -- the int variant stays on the int-flavor SimNode path
unchanged.

Tests:
  * tests/long_array_table/test_int64_overloads.das -- 5 new
    overload-resolution unit tests (push/emplace/push_clone at int64,
    resize_and_init int64 + initValue). Fails on master with "no matching
    overload"; passes here.
  * tests/long_array_table/test_huge_array_push_emplace_clone.das --
    extended with 3 huge insertion-path probes (push/emplace/push_clone
    at position > INT_MAX). Memory-gated on DASLANG_HUGE_HEAP_TESTS=1;
    verified locally on a 2.2 GB uint8 array (6 tests, 2.6s).
  * tests/long_array_table/test_huge_array_erase.das -- NEW. 2 probes
    for the already-widened erase(at:int64) / erase(at,count:int64)
    paths past INT_MAX. Same gate; verified locally (2 tests, 0.8s).

Side-effects:
  * doc/source/reference/language/generic_programming.rst -- adds
    typeinfo is_int / is_int64 to the trait list (carry-over from
    PR GaijinEntertainment#2764 deferral).
  * daslib/builtin.das -- swept all 31 pre-existing lint warnings
    (STYLE024/025/026/005) per the bundling pattern. 6 of the clone /
    clone_to_move variants carry an explicit `// nolint:STYLE025` with
    the reason -- `var clone_dest : TT -#` is conditionally unsafe (the
    is_unsafe_when_uninitialized type set), and the unsafe block scope
    cannot be narrower than the var-decl.

Regression locally: 1785 tests pass across
  long_array_table (58) + decs (245) + linq (1228) + daslib (92) +
  algorithm (162). `dasfmt --verify` clean on full tree (17470 files).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants