@creaothceann:All of it is fixed on the
devel branch - update to it (the installer lets you pin the branch) and check unleashed/docs/indexed-labels.md there, it was rewritten and now covers what previously only existed in this thread.
What changed, of the things you hit:
- The second dispatch gets a jump table. A goto over an indexed family is exempt from the case-size heuristic that turned small families into a compare chain, so BRK[0..7] is one table jump - no padding with unused labels.
- @Op[index] works, constant and runtime index both; a runtime index matching no member yields nil. That was your "Illegal qualifier", and the delta-table dispatch you described now builds without casting anything.
- goto on a pointer expression, arithmetic included, is documented, with your delta-table pattern as the example.
- Your internal error is gone. It reduced to a family with a declared-but-undefined member and a variable-index goto: codegen dereferenced a goto that had no label and crashed at -O2. An undefined member now falls through to the statement after the goto, as documented.
- label Op[u8] with only Op[$00] defined no longer warns 255 times. Undefined members of a family are legal by design, so they don't warn at all now. A constant-index goto naming an undefined member still errors.
- label Op[256] is a proper error now. The index spec is a set of values, never a count, so [256] declared the single label Op[256]. Use [256..256], a value list, or a type.
- Adding an index outside the range of an already generated variable-index goto is an error. Before, a lazily created label could land outside the dispatch and out-of-range indices silently fell through.
Btw. the Delta_Op above in line 13 is marked with the warning "does not seem to be initialized", even though it should be all zeroes at program start - which is what I do want. It seems there are 3 ways to suppress that warning, all rather lacking:
https://github.com/unleashedpascal/compiler/blob/main/unleashed/docs/zeroinit.md
@Akira1364:Confirmed, and it's worse than "not inlined" - the target is already known and still called indirectly. At -O2:
g := Doubler(21); // movl $42,g
g := Apply(@Doubler, 21); // leaq Doubler(%rip),%rax
// call *%rax
Apply gets inlined; the inner f(x) stays an indirect call through a register loaded with the address of Doubler one instruction earlier. Missing step: after inlining, spot that the target is now constant, turn the indirect call into a direct one, inline again. FPC inlines once and stops - the decision needs a resolved procdef, and a procvar call never has one.
The narrow case (argument is literally @Proc, or a local assigned @Proc) looks doable. The general one needs whole-function constant propagation FPC doesn't have. Not on my list before your post - it is now.