Skip to content

Commit 6f0181a

Browse files
docs: update test-failures-not-quick-fix.md with implementation status
Mark implemented items: taint skip, delete local, tied scalar code deref, printf array flattening, stat/lstat validation, \(LIST JVM backend. Update priority ranking and recommended next steps. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> EOF )
1 parent b289fbc commit 6f0181a

File tree

1 file changed

+64
-146
lines changed

1 file changed

+64
-146
lines changed

dev/prompts/test-failures-not-quick-fix.md

Lines changed: 64 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -41,27 +41,11 @@ estimated difficulty level.
4141

4242
## 1. Taint Tracking
4343

44-
**Test:** `op/taint.t` (4/1065)
45-
**Blocked tests:** ~1061
44+
**Status:** SKIP WORKAROUND IMPLEMENTED (2026-04-01)
4645

47-
### What is needed
48-
49-
Full taint tracking system:
50-
- A taint flag on every `RuntimeScalar` value
51-
- Propagation of taint through string/numeric operations
52-
- Enforcement of taint checks on dangerous ops (`kill`, `exec`, `system`, backticks, `open` with pipes)
53-
- "Insecure dependency in X while running with -T switch" error mechanism
54-
- The `-T` command-line switch activating taint mode
55-
56-
### Current state
57-
58-
`RuntimeScalar.isTainted()` always returns `false`. The `$^X` variable is never marked tainted. The `Config.pm` does not set `taint_support` key, so the test does not skip.
46+
`Config.pm` now has `taint_support => ''` and `ccflags => '-DSILENT_NO_TAINT_SUPPORT'`, so `op/taint.t` skips gracefully. Full taint tracking remains unimplemented (`RuntimeScalar.isTainted()` always returns `false`).
5947

60-
### Quick workaround
61-
62-
Add `taint_support => ''` to `Config.pm` so the test skips entirely.
63-
64-
### Difficulty: Very Hard (full implementation), Trivial (skip workaround)
48+
### Difficulty: Very Hard (full implementation) - skip workaround already applied
6549

6650
---
6751

@@ -122,98 +106,33 @@ Making `(?{UNIMPLEMENTED_CODE_BLOCK})` non-fatal (replace with `(?:)` no-op) wou
122106

123107
## 4. delete local Construct
124108

125-
**Test:** `op/local.t` (0/319 - crashes before any output)
126-
**Blocked tests:** ~319
127-
128-
### What is needed
129-
130-
The `delete local` syntax:
131-
```perl
132-
delete local $hash{key}; # Save value, delete, restore on scope exit
133-
delete local $array[idx];
134-
```
135-
136-
Currently:
137-
- The parser (`parseDelete` in `OperatorParser.java` line 549) does NOT check for a `local` keyword after `delete`
138-
- No `DeleteLocalNode` or compilation path exists
139-
- The test crashes at line 164 with "Not implemented: delete with dynamic patterns"
140-
141-
### Implementation plan
142-
143-
1. **Parser**: `parseDelete` must check for `local` keyword and produce a new AST node
144-
2. **Compiler**: Emit save-state, delete, and scope-exit restore
145-
3. **Runtime**: Use existing `dynamicSaveState`/`dynamicRestoreState` mechanism on hash/array elements
146-
147-
### Note
109+
**Status:** FULLY IMPLEMENTED (2026-04-01)
148110

149-
Many tests before line 161 in local.t don't use `delete local`. If the parser didn't crash, ~100+ tests might pass.
111+
`delete local` is fully implemented across all layers: parser (`OperatorParser.parseDelete`), JVM backend (`EmitOperatorDeleteExists`), bytecode compiler (`CompileExistsDelete.visitDeleteLocal`), opcodes (`HASH_DELETE_LOCAL`, `ARRAY_DELETE_LOCAL`, slices), runtime (`RuntimeHash.deleteLocal`, `RuntimeArray.deleteLocal`), and disassembler. Supports all forms: `delete local $hash{key}`, `delete local @hash{@keys}`, `delete local $array[idx]`, `delete local @array[@idx]`, and arrow-deref variants.
150112

151-
### Difficulty: Moderate
113+
### Difficulty: Done
152114

153115
---
154116

155117
## 5. \(LIST) Reference Creation
156118

157-
**Test:** `op/ref.t` (97/265)
158-
**Blocked tests:** ~155
119+
**Status:** JVM BACKEND IMPLEMENTED (2026-04-01)
159120

160-
### What is needed
161-
162-
`\(LIST)` should return a list of references to each element. E.g., `\(@array)` returns refs to each element; `\($a, $b)` returns `(\$a, \$b)`.
163-
164-
### Root cause
165-
166-
`RuntimeList.flattenElements()` (line 424) does not handle `PerlRange` objects. When `\(1..3)` is evaluated, the PerlRange passes through unflattened, then `createReference()` throws "Can't create reference to list".
167-
168-
### Fix
169-
170-
Add PerlRange handling to `flattenElements()` (~5 lines):
171-
```java
172-
} else if (element instanceof PerlRange range) {
173-
for (RuntimeScalar scalar : range) {
174-
result.elements.add(scalar);
175-
}
176-
}
177-
```
178-
179-
Also need to update `InlineOpcodeHandler.executeCreateRef()` for the bytecode interpreter path.
121+
JVM backend works correctly: `EmitOperator.handleCreateReference` calls `flattenElements()` then `createListReference()`. `RuntimeList.flattenElements()` handles `PerlRange`, `RuntimeArray`, and `RuntimeHash`.
180122

181-
### Key files
182-
183-
- `src/main/java/org/perlonjava/runtime/RuntimeList.java` (flattenElements, createListReference)
184-
- `src/main/java/org/perlonjava/runtime/PerlRange.java`
185-
- `src/main/java/org/perlonjava/codegen/EmitOperator.java` (handleCreateReference)
123+
**Remaining:** Bytecode interpreter (`InlineOpcodeHandler.executeCreateRef`) does NOT call `flattenElements()`, so `\(@array)`, `\(1..3)` fail in `eval STRING` and `--interpreter` mode.
186124

187-
### Difficulty: Easy (this is actually a quick fix, ~5 lines)
125+
### Difficulty: Easy (1-line fix in interpreter)
188126

189127
---
190128

191129
## 6. Tied Scalar Code Deref
192130

193-
**Test:** `op/tie_fetch_count.t` (64/343)
194-
**Blocked tests:** ~279
195-
196-
### What is needed
131+
**Status:** FULLY IMPLEMENTED (2026-04-01)
197132

198-
`RuntimeCode.apply()` does not handle `TIED_SCALAR` type. When `$tied_var` holds a CODE ref and you call `&$tied_var`, the code falls through to "Not a CODE reference" error instead of calling `tiedFetch()` first.
133+
All three `RuntimeCode.apply()` overloads handle `TIED_SCALAR` by calling `tiedFetch()` before proceeding. `RuntimeScalar.codeDerefNonStrict()`, `globDeref()`, and `globDerefNonStrict()` also handle tied scalars.
199134

200-
### Fix
201-
202-
Add `TIED_SCALAR` handling in all three `RuntimeCode.apply()` overloads:
203-
```java
204-
if (runtimeScalar.type == RuntimeScalarType.TIED_SCALAR) {
205-
return apply(runtimeScalar.tiedFetch(), subroutineName, args, callContext);
206-
}
207-
```
208-
209-
Also fix `RuntimeScalar.codeDerefNonStrict()` and `globDeref()` for the same pattern.
210-
211-
### Key files
212-
213-
- `src/main/java/org/perlonjava/runtime/RuntimeCode.java` (three apply overloads)
214-
- `src/main/java/org/perlonjava/runtime/RuntimeScalar.java` (codeDerefNonStrict, globDeref)
215-
216-
### Difficulty: Easy (this is actually a quick fix, ~6 lines across 3 methods)
135+
### Difficulty: Done
217136

218137
---
219138

@@ -372,42 +291,27 @@ The `-C` flags are **parsed** in `ArgumentParser.java` (lines 469-563) and **sto
372291
**Test:** `op/stat.t` (64/111)
373292
**Blocked tests:** ~47
374293

375-
### What is needed
294+
**Status:** Item 1 IMPLEMENTED (2026-04-01) - `lstat _` validation now checks `lastStatWasLstat` in `Stat.java` (lines 111, 129, 249). Items 2-5 remain open.
376295

377-
1. **`lstat _` validation** - `Stat.lstatLastHandle()` does NOT validate `lastStatWasLstat`. Should throw "The stat preceding lstat() wasn't an lstat" when the previous call was `stat` not `lstat`. `FileTestOperator.java` already has this check for `-l _` but `Stat.java` doesn't.
296+
### Remaining items
297+
298+
1. ~~**`lstat _` validation**~~ - DONE
378299
2. **`lstat *FOO{IO}`** - lstat on IO reference
379300
3. **`stat *DIR{IO}`** - stat on directory handles
380301
4. **`-T _` breaking the stat buffer**
381302
5. **stat on filenames with `\0`**
382303

383-
### Key files
384-
385-
- `src/main/java/org/perlonjava/operators/Stat.java` (lstatLastHandle)
386-
- `src/main/java/org/perlonjava/operators/FileTestOperator.java`
387-
388-
### Difficulty: Easy-Medium (lstat validation is a 1-line fix; other items are moderate)
304+
### Difficulty: Easy-Medium (remaining items)
389305

390306
---
391307

392308
## 15. printf Array Flattening
393309

394-
**Test:** `io/print.t` (8/24)
395-
**Blocked tests:** ~16
396-
397-
### What is needed
310+
**Status:** IMPLEMENTED (2026-04-01)
398311

399-
When `printf @array` is called, the RuntimeArray argument is not flattened before extracting the format string. `IOOperator.printf()` calls `list.add(args[i])` which adds the array as-is; then `removeFirst()` expects a RuntimeScalar but gets a RuntimeArray.
312+
Both `printf` methods in `IOOperator.java` now flatten `RuntimeArray` elements. `printf +()` (empty list) also handled. Remaining io/print.t failures may relate to `$\` null bytes or `%n` format specifier.
400313

401-
Additional issues:
402-
- Null bytes in `$\` (output record separator)
403-
- `%n` format specifier (writes char count via substr)
404-
- `printf +()` (empty list)
405-
406-
### Key files
407-
408-
- `src/main/java/org/perlonjava/operators/IOOperator.java` (printf method, line 2386)
409-
410-
### Difficulty: Medium
314+
### Difficulty: Done (core issue); remaining edge cases Medium
411315

412316
---
413317

@@ -606,9 +510,20 @@ The Perl `class` feature (added in Perl 5.38) is partially implemented. Missing:
606510

607511
---
608512

609-
## 25. Test Failures Investigated 2026-04-01 (Not Quick Fixes)
513+
## 25. Test Failures Investigated 2026-04-01 (Status Update)
514+
515+
Items marked FIXED were implemented on the `feature/test-failure-fixes` branch.
610516

611-
These were investigated during the `feature/test-failure-fixes` branch work session.
517+
### FIXED items
518+
519+
| Test | Before | After | Fix |
520+
|------|--------|-------|-----|
521+
| op/oct.t | 79/81 | **81/81** | Oct/hex overflow detection with double fallback |
522+
| op/my.t | 52/59 | **59/59** | `my() in false conditional` detection in 3 places |
523+
| op/push.t | 29/32 | **32/32** | Error messages + readonly array handling |
524+
| op/unshift.t | 16/19 | **19/19** | Error messages + readonly array handling |
525+
| op/lex_assign.t | 349/353 | **350/353** | Select 4-arg LIST context fix |
526+
| op/while.t | 22/26 | **23/26** | While loop returns false condition value |
612527

613528
### op/time.t (71/72) - MOSTLY FIXED
614529
- **Remaining failure:** Test 7 `changes to $ENV{TZ} respected` - Java caches timezone on startup via `ZoneId.systemDefault()`. Changing `$ENV{TZ}` at runtime has no effect.
@@ -701,55 +616,58 @@ These were investigated during the `feature/test-failure-fixes` branch work sess
701616

702617
---
703618

704-
## Priority Ranking by Impact
705-
706-
### Tier 1: Highest impact (1000+ tests unlocked)
619+
## Priority Ranking by Impact (Updated 2026-04-01)
620+
621+
### Already Implemented
622+
| Feature | Status |
623+
|---------|--------|
624+
| Taint skip workaround | Done - Config.pm has `taint_support => ''` |
625+
| Tied scalar code deref | Done - all apply() overloads handle TIED_SCALAR |
626+
| delete local | Done - full implementation across all layers |
627+
| \(LIST) reference creation (JVM) | Done - JVM backend works; interpreter fix pending |
628+
| printf array flattening | Done |
629+
| stat/lstat _ validation (item 1) | Done |
630+
| op/my.t false conditional | Done - 59/59 |
631+
| op/push.t / op/unshift.t | Done - 32/32, 19/19 |
632+
| op/oct.t overflow | Done - 81/81 |
633+
634+
### Tier 1: Highest impact remaining
707635
| Feature | Tests blocked | Difficulty |
708636
|---------|--------------|------------|
709-
| Taint skip workaround | 1061 | Trivial |
710637
| Regex code blocks (non-fatal workaround) | 500+ | Medium |
711638
| Format/write system | 658 | Hard |
712639

713640
### Tier 2: High impact (100-500 tests)
714641
| Feature | Tests blocked | Difficulty |
715642
|---------|--------------|------------|
716-
| delete local | 319 | Moderate |
717-
| Tied scalar code deref | 279 | Easy |
718-
| \(LIST) reference creation | 155 | Easy |
719-
| comp/parser.t (?{} non-fatal) | 132 | Medium |
720-
| In-place editing ($^I) | 120+ | Hard |
721643
| 64-bit integer ops | 274 | Medium-Hard |
644+
| Attribute system | 160+ | Medium-Hard |
645+
| comp/parser.t (non-fatal (?{}) + #line) | 132 | Medium |
646+
| In-place editing ($^I) | 120+ | Hard |
722647

723648
### Tier 3: Medium impact (30-100 tests)
724649
| Feature | Tests blocked | Difficulty |
725650
|---------|--------------|------------|
726651
| caller() extended fields | 66 | Medium-Hard |
727-
| Attribute system | 160+ | Medium-Hard |
728652
| MRO @ISA invalidation | 50+ | Hard |
729-
| stat/lstat validation | 47 | Easy-Medium |
653+
| stat/lstat remaining items (2-5) | 47 | Easy-Medium |
730654
| Duplicate named captures | 36 | Hard |
731655
| Class feature completion | 30 | Medium |
732656

733-
### Tier 4: Lower impact but easy
657+
### Tier 4: Lower impact
734658
| Feature | Tests blocked | Difficulty |
735659
|---------|--------------|------------|
736-
| -C unicode switch | 13 | Medium |
737-
| printf array flattening | 16 | Medium |
738660
| Closures (edge cases) | 20 | Medium-Hard |
739-
| %^H hints (advanced) | 8 | Medium-Hard |
740661
| Special blocks lifecycle | 17 | Medium-Hard |
662+
| -C unicode switch | 13 | Medium |
663+
| %^H hints (advanced) | 8 | Medium-Hard |
741664

742665
---
743666

744-
## Recommended Implementation Order (effort vs. impact)
745-
746-
1. **Taint skip** (Trivial) - 1061 tests
747-
2. **\(LIST) flattenElements fix** (Easy, ~5 lines) - 155 tests
748-
3. **Tied scalar code deref** (Easy, ~6 lines) - 279 tests
749-
4. **(?{...}) non-fatal workaround** (Medium) - 500+ tests
750-
5. **stat/lstat _ validation** (Easy) - ~7 tests + unblocks others
751-
6. **delete local** (Moderate) - 319 tests
752-
7. **printf array flattening** (Medium) - 16 tests
753-
8. **-C switch application** (Medium) - 13 tests
754-
9. **caller() extended fields** (Medium-Hard) - 66 tests
755-
10. **attributes.pm module** (Medium-Hard) - 160+ tests
667+
## Recommended Next Steps
668+
669+
1. **\(LIST) interpreter fix** (Easy, 1-line) - fix `InlineOpcodeHandler.executeCreateRef`
670+
2. **(?{...}) non-fatal workaround** (Medium) - change `UNIMPLEMENTED_CODE_BLOCK` from fatal to `(?:)` fallback - 500+ tests
671+
3. **64-bit integer ops** (Medium-Hard) - unsigned semantics, overflow handling
672+
4. **caller() extended fields** (Medium-Hard) - wantarray, evaltext, is_require
673+
5. **Attribute system** (Medium-Hard) - attributes.pm module, MODIFY_*_ATTRIBUTES callbacks

0 commit comments

Comments
 (0)