⏺ Phase 7 is complete. Here's a summary of all changes: #8
No reviewers
Labels
No labels
bug
dependencies
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
rust
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
navicore/patch-rexx!8
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "phase7"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Files Modified
src/parser.rs — Added INTERPRET keyword dispatch in parse_clause() and a parse_interpret() method that consumes the INTERPRET keyword and parses an
optional expression (defaulting to empty string).
src/eval.rs — Three main additions:
New File
tests/phase7.rs — 27 integration tests covering:
Test Results
PR #8 Code Review: INTERPRET Implementation
Summary
This PR implements the REXX INTERPRET instruction, which evaluates a string as REXX code at runtime. The implementation adds ~375 lines across parser, evaluator, and comprehensive test coverage.
Issues Found
1. CRITICAL: Parse errors in INTERPRET may bypass SYNTAX trap (src/eval.rs:289-293)
Location:
src/eval.rs:289-293The parse happens BEFORE entering the SYNTAX trap handler:
Issue: These errors propagate via
?directly, bypassingexec_clause_outer()which provides SYNTAX trap handling (lines 146-169). The test attests/phase7.rs:197-202expects parse errors to fire SYNTAX traps, but the current code structure suggests they won't.Test claim:
Verification needed: Does this test actually pass? If it does, there's an outer wrapper I missed. If not, the implementation needs to wrap lex/parse in error handling and manually fire the SYNTAX trap.
Fix approach:
Severity: HIGH (correctness issue with trap semantics, potential test failure)
2. Depth limit test may not exercise intended code path (tests/phase7.rs:183-191)
Location:
tests/phase7.rs:183-191Issue: This constructs deeply nested code via string concatenation, which may fail during PARSING with Error 14 (IncompleteBlock) or Error 35 (InvalidExpression) rather than reaching runtime depth exhaustion.
Better test approach:
Severity: Medium (test may not validate the depth guard at src/eval.rs:283)
3. Unnecessary work after pending exit/signal detection (src/eval.rs:269-277)
Location:
src/eval.rs:269-277Issue: String conversion happens after checking pending signals, but if we're bailing out anyway, this is wasted work. Minor inefficiency.
Also: Most other clause handlers in
exec_clause()don't have this early-exit pattern; they rely on the outer signal propagation loop. Consider consistency.Severity: Low (minor efficiency issue)
Non-Issues (Confirmed Correct)
✓ Arithmetic error handling
Division by zero correctly returns Error 42 (ArithmeticOverflow). SYNTAX trap fires for runtime arithmetic errors inside INTERPRET (verified by test at line 206-212).
✓ SIGNAL propagation
Two-level signal handling is correct:
exec_interpret_bodylines 316-326)This matches REXX semantics where inner labels shadow outer labels.
✓ Variable scope sharing
INTERPRET operates in caller's scope (no new scope created), which is correct per REXX spec. Tests verify variables created/modified inside INTERPRET persist after.
✓ Control flow propagation
EXIT/LEAVE/ITERATE correctly propagate through INTERPRET boundaries. The
exec_interpret_from()method properly handles these signals by callingexec_clause_outer().✓ Trap inheritance
Traps set before INTERPRET apply inside interpreted code because
exec_interpret_from()callsexec_clause_outer(), which checksself.traps. Tests verify this at lines 224-241.✓ Cleanup handling
The
interpret_depthincrement/decrement (lines 303-305) uses proper RAII pattern. Errors propagate via?, ensuring decrement always happens due to Rust's ownership.✓ Parser correctness
INTERPRET with no expression defaults to empty string (parser.rs:1134-1138), matching SAY's behavior. Correct REXX semantics.
✓ Label semantics
Using
.entry().or_insert(i)(line 299) keeps FIRST occurrence of duplicate labels, matching the pattern inbuild_labels()(line 91). Classic REXX allows duplicate labels and uses the first, so this is correct.Test Coverage Assessment
Excellent coverage: 27 tests covering all major paths including:
Suggested addition:
do name myloop; interpret 'leave myloop'; endSummary & Recommendations
Must Fix Before Merge:
Issue #1 (HIGH): Verify SYNTAX trap behavior for parse errors. Run
cargo test interpret_parse_error_fires_syntax_trapand confirm it passes. If it fails, implement trap firing for lex/parse errors.Should Fix:
Issue #2 (MEDIUM): Improve
interpret_depth_limittest to actually execute recursive INTERPRET calls rather than relying on string construction depth.Consider:
Issue #3 (LOW): Move string conversion after pending signal checks for consistency and minor efficiency gain.
Overall Assessment:
Strong implementation with comprehensive tests. Core logic is sound and follows existing evaluator patterns. One critical verification needed (#1) to ensure trap semantics are correct. Everything else is minor polish.
Test results show 341 tests passing and clippy clean. Good work on INTERPRET! 🎯
REXX INTERPRET Implementation Review
I've reviewed PR #8 which implements the INTERPRET instruction for the REXX interpreter. Overall, this is a solid implementation with good test coverage and correct REXX semantics. Below are my findings:
✅ Strengths
1. Correct REXX Semantics
2. Proper Error Handling
3. Excellent Test Coverage
4. Safety
⚠️ Issues Found
CRITICAL: Potential Panic on Empty Interpreted Code with Labels
File:
src/eval.rs:321Issue: When interpreted code contains only a label with no following clause, signaling to that label will cause
start = idx + 1to point past the end of the clause array. The subsequent slice&clauses[start..]at line 333 will be empty (safe), but this behavior is inconsistent with how main program execution handles labels.REXX Semantics: In REXX, signaling to a label should resume execution at the clause following the label, not the label itself. If there's no clause after the label, execution should complete normally, not skip.
Evidence:
Fix Required: Add bounds check or match the main program's behavior (see exec_from at line 100-107).
Test Case to Add:
MODERATE: Division by Zero Error Number
File:
src/eval.rs:1223-1224(not in this PR, but affects INTERPRET)Issue: Division by zero uses
Error 42 (ArithmeticOverflow). According to ANSI X3.274-1996, division by zero should be Error 42 (overflow/underflow), which is technically correct. However, some REXX implementations distinguish this more clearly.Verdict: Actually correct per spec. No change needed, but worth noting for future reference.
MINOR: Duplicate Label Handling
File:
src/eval.rs:296-301Issue: The label map builder uses
.or_insert(), which silently ignores duplicate labels (first occurrence wins). REXX programs typically require unique labels, but this implementation provides no warning.Current behavior:
REXX Standard: Section 2.4.5 of ANSI X3.274-1996 states labels should be unique within a program, but doesn't mandate an error for duplicates.
Recommendation: Consider adding a warning (not an error) when duplicate labels are detected, or document this behavior. This affects both main program (line 87-95) and INTERPRET (line 296-301).
MINOR: Missing SourceLoc Context in Recursion Depth Error
File:
src/eval.rs:285Issue: The recursion depth error uses
SourceLoc::new(0, 0)instead of the actual INTERPRET clause location.Current:
Recommendation: Pass the actual clause location for better error reporting:
Impact: Low - error is still clear, just missing precise location info.
📋 Code Quality Notes
Good Practices Observed:
Performance:
🧪 Test Coverage Analysis
Covered:
Missing (non-critical):
Recommendation: Add test for the label-at-end case once fixed.
📝 REXX Semantics Compliance
🎯 Recommendations
Must Fix (Before Merge):
start = idx + 1in exec_interpret_body (src/eval.rs:321)Should Consider:
Nice to Have:
✅ Approval Status
Overall Assessment: This implementation is well-designed and mostly correct. The critical issue (label bounds) is a straightforward fix. Error handling is robust, test coverage is comprehensive, and REXX semantics are properly respected.
Recommendation: ✅ Approve with requested changes (fix the label bounds issue)
Files Reviewed:
Test Results: All 28 tests pass ✅
Great work on this implementation! The code is clean, well-tested, and demonstrates good understanding of REXX semantics.
Phase 7 INTERPRET Implementation Review
Reviewed the INTERPRET instruction implementation for correctness, REXX semantics, error handling, and performance.
✅ Strengths
Parser (src/parser.rs:1128-1143)
parse_clause()at line 289INTERPRET(defaults to empty string per REXX spec)Evaluator (src/eval.rs:265-345)
Control Flow
exec_from()patternexec_clause_outer()usage ensures SYNTAX trap fires for errors in interpreted codeTest Coverage (tests/phase7.rs)
🔍 Potential Issues
1. Missing test coverage for RETURN propagation (Medium confidence)
Location: tests/phase7.rs
The test suite covers EXIT, LEAVE, ITERATE propagation but has no test for RETURN. In REXX:
RETURNfrom main-level INTERPRET should act like EXITRETURNfrom INTERPRET within a subroutine should return from the subroutineSuggested test:
Expected: prints "AFTER", sets RESULT to 99
The implementation appears correct (line 340 propagates all non-Normal signals) but lacks explicit test verification.
2. Incorrect test count in PR description (Low severity)
Location: PR body
PR description states "27 phase7" tests but
tests/phase7.rscontains 29#[test]functions. Minor documentation inconsistency.3. Potential for quadratic behavior with deeply nested label maps (Low confidence)
Location: src/eval.rs:295-300
Each INTERPRET execution allocates a new
HashMapand clones label names. For recursive INTERPRET or loops containing INTERPRET, this creates per-evaluation allocations. However:build_labels()at line 87Verdict: Acceptable for Phase 7. Future optimization could use arena allocation for parsed programs, but that's out of scope.
🎯 REXX Semantics Verification
✅ String evaluation — Line 277 correctly uses
as_str()for "everything is a string"✅ No reserved words — Uses existing keyword checking (
check_keyword)✅ Case-insensitive keywords — Parser handles this (inherited behavior)
✅ Error numbers — Line 284 correctly uses Error 5 (ResourceExhausted) for depth limit
✅ Trap behavior — SYNTAX trap fires for both parse and runtime errors (exec_clause_outer handles this)
✅ Label scoping — Local labels shadow outer labels (line 319 checks local map first)
📊 Performance Notes
Result, caught by SYNTAX trapRexxValuecould be constructed dynamically✅ Verdict
APPROVE — Implementation is correct and well-tested. The RETURN propagation test gap is minor (implementation appears correct), and the test count discrepancy is cosmetic.
Recommendation: Add a test for RETURN from INTERPRET within a subroutine to achieve 100% control flow propagation coverage.
Excellent work on implementing complex control flow semantics correctly on the first try. The restart loop pattern for local signal handling is particularly elegant.