Skip to content
This repository was archived by the owner on Apr 29, 2026. It is now read-only.

Roadmap updated:#36

Merged
navicore merged 3 commits intomainfrom
int-io
Nov 30, 2025
Merged

Roadmap updated:#36
navicore merged 3 commits intomainfrom
int-io

Conversation

@navicore
Copy link
Copy Markdown
Owner

Changes made:

  1. Marked Integer I/O (int->string and string->int) as complete ✅
  2. Moved Variant and Closure capture to new Long-Term Goals section with note explaining the lower priority (since error messages now help users work around limitations)

Current roadmap status:

  • Near-Term Goals - All complete:
    • ✅ LSP Enhancements (hover + go-to-definition)
    • ✅ Closure Capture (Int, String, Bool, Float, Quotation)
    • ✅ Stdlib Improvements (JSON escape, Integer I/O)
  • Medium-Term Goals - Next candidates:
    • Spawn with Captured Data
    • Collections (lists, maps)
    • Error Handling (Result-based)
  • Long-Term Goals - Deferred:
    • Extended Closure Capture (Variant, nested Closures)

The string->int implementation is ready for PR - it returns ( String -- Int Int ) where the second Int is a success flag (1=ok, 0=fail), matching the same pattern used for safe parsing operations.

Changes made:
1. Marked Integer I/O (int->string and string->int) as complete ✅
2. Moved Variant and Closure capture to new Long-Term Goals section with note explaining the lower priority (since error messages now help users work
around limitations)

Current roadmap status:
- Near-Term Goals - All complete:
  - ✅ LSP Enhancements (hover + go-to-definition)
  - ✅ Closure Capture (Int, String, Bool, Float, Quotation)
  - ✅ Stdlib Improvements (JSON escape, Integer I/O)
- Medium-Term Goals - Next candidates:
  - Spawn with Captured Data
  - Collections (lists, maps)
  - Error Handling (Result-based)
- Long-Term Goals - Deferred:
  - Extended Closure Capture (Variant, nested Closures)

The string->int implementation is ready for PR - it returns ( String -- Int Int ) where the second Int is a success flag (1=ok, 0=fail), matching the
same pattern used for safe parsing operations.
@claude
Copy link
Copy Markdown

claude Bot commented Nov 30, 2025

Code Review: PR #36 - Integer I/O (string->int)

Summary

This PR adds the string->int builtin function and updates the roadmap to mark Integer I/O as complete. The implementation follows the established patterns in the codebase and includes comprehensive test coverage.

✅ Strengths

Code Quality

  • Consistent API design: The signature ( String -- Int Int ) returning value + success flag matches the safe parsing pattern used elsewhere in the codebase
  • Proper error handling: Returns (0, 0) on parse failure instead of panicking, allowing graceful degradation
  • Whitespace handling: Correctly trims input before parsing, which is user-friendly
  • Good test coverage: 5 unit tests covering success cases, negative numbers, whitespace, invalid input, and empty strings

Integration

  • Complete compiler integration: All required changes made across:
    • ast.rs: Added to builtin list
    • builtins.rs: Type signature defined
    • codegen.rs: LLVM declaration and mapping
    • lib.rs: Proper export with naming consistency
  • Documentation updated: ROADMAP.md appropriately updated to reflect completion

🔍 Issues & Recommendations

1. Export Inconsistency in lib.rs (Minor)

Location: runtime/src/lib.rs:76

The int_to_string export is from io module, while string_to_int is from string_ops module. While functionally correct, this creates a minor inconsistency.

Recommendation: Consider moving int_to_string to string_ops.rs for consistency, or document why they're in separate modules. Not a blocker, but improves maintainability.

2. Missing Integration Test (Medium)

Issue: No .seq example demonstrating usage of string->int

The math.seq stdlib already references int->string in its documentation (line 10), which would be a perfect place to also demonstrate string->int in a round-trip test.

Recommendation: Add an example like:

# Parse user input as integer
: parse-demo ( -- )
  "Enter a number: " write_line
  read_line string->int
  if
    int->string " parsed successfully!" string-concat write_line
  else
    drop "Invalid number!" write_line
  then
;

3. Overflow/Bounds Documentation (Minor)

Location: runtime/src/string_ops.rs:486

The function uses i64::parse which will fail for values outside i64 range, but this isn't documented in the function comment.

Current:

/// Convert String to Int: ( String -- Int Int )
/// Returns the parsed int and 1 on success, or 0 and 0 on failure

Recommended:

/// Convert String to Int: ( String -- Int Int )
/// Returns the parsed int and 1 on success, or 0 and 0 on failure.
/// Accepts integers in range [-9223372036854775808, 9223372036854775807] (i64).
/// Trims whitespace before parsing.

4. Edge Case: Leading Zeros (Question)

Test Gap: No test for inputs like "007" or "00"

Current implementation will parse these correctly (as 7 and 0), but worth confirming this is desired behavior vs. treating them as invalid.

Recommendation: Add a test to document expected behavior:

#[test]
fn test_string_to_int_leading_zeros() {
    unsafe {
        let stack = std::ptr::null_mut();
        let stack = push(stack, Value::String(global_string("007".to_owned())));
        let stack = string_to_int(stack);
        let (stack, success) = pop(stack);
        let (stack, value) = pop(stack);
        assert_eq!(success, Value::Int(1));
        assert_eq!(value, Value::Int(7));
        assert!(stack.is_null());
    }
}

🔒 Security

✅ No security concerns identified:

  • Input validation through Rust's standard library parse::<i64>()
  • No unsafe operations beyond the documented stack manipulation
  • No risk of buffer overflows or injection attacks

🎯 Performance

✅ Performance is appropriate:

  • Single string allocation for trimming (minimal overhead)
  • Standard library parsing is well-optimized
  • Stack operations are pointer manipulations (constant time)

📋 Recommendations Summary

Before Merge:

  • Add at least one integration test or example in .seq format
  • Document i64 range limits in function comment

Post-Merge (Optional Improvements):

  • Consider consolidating int<->string conversions in one module
  • Add leading-zero test case for documentation

Verdict

LGTM with minor suggestions

The implementation is solid, well-tested at the unit level, and properly integrated. The suggestions above are for polish and documentation completeness, not correctness issues. This PR can be merged after addressing the integration test gap.

Great work maintaining consistency with the codebase patterns!


Review completed via Claude Code

Changes made:

1. Documentation (Minor) - Updated string_to_int docstring at runtime/src/string_ops.rs:481-485:
  - Added i64 range limits: [-9223372036854775808, 9223372036854775807]
  - Documented whitespace trimming behavior
  - Documented leading zeros acceptance ("007" → 7)
2. Leading zeros test (Minor) - Added test_string_to_int_leading_zeros at runtime/src/string_ops.rs:1481-1495
3. Integration test (Medium) - Created examples/test-string-int.seq:
  - Tests int->string (42, 0, -1)
  - Tests string->int success (42, -7, whitespace, leading zeros)
  - Tests string->int failure (invalid, empty)
  - Tests round-trip int->string->int

Test results:
- 217 unit tests pass (6 for string->int)
- Integration test: 10/10 PASS
- No clippy warnings

The staged changes are ready for commit when you're ready.
@claude
Copy link
Copy Markdown

claude Bot commented Nov 30, 2025

PR Review: Roadmap Update + string->int Implementation

Summary

This PR implements the string->int conversion function and updates the roadmap to reflect completion of Integer I/O goals. The implementation is solid overall with good test coverage and follows established patterns.

✅ Strengths

Code Quality

  • Consistent patterns: The implementation closely mirrors string->float (runtime/src/float_ops.rs:300-317), maintaining codebase consistency
  • Proper error handling: Returns (value, success_flag) tuple matching the established safe-parsing pattern used throughout the codebase
  • Good documentation: Clear docstring with range limits and behavior notes (runtime/src/string_ops.rs:481-485)

Test Coverage

  • Comprehensive unit tests: 6 test cases covering success, negative numbers, whitespace, failures, empty strings, and leading zeros (runtime/src/string_ops.rs:1398-1495)
  • Integration tests: Well-structured example file with 10 test cases including round-trip conversion (examples/test-string-int.seq)
  • Edge cases: Tests for whitespace trimming and leading zeros

Compiler Integration

  • Proper registration in all required locations:
    • AST builtin list (compiler/src/ast.rs:186)
    • Builtin signatures (compiler/src/builtins.rs:615-625)
    • Codegen mappings (compiler/src/codegen.rs:318, 737)
    • Public exports (runtime/src/lib.rs:80)

⚠️ Issues Found

1. CRITICAL: Binary file committed (Security/Repository Hygiene)

The file output is a compiled Mach-O executable that should NOT be in version control:

output: Mach-O 64-bit arm64 executable

Impact:

  • Pollutes repository with platform-specific binaries
  • Violates .gitignore patterns (line 12-16: "Never pollute root directory with test binaries!")
  • 218 additions suggest this is a significant binary

Fix: Remove the file and add to .gitignore:

git rm output
echo "/output" >> .gitignore

2. Missing: Overflow boundary tests (Test Coverage)

While the implementation uses parse::<i64>() which correctly handles overflow, there are no tests for boundary values:

Missing test cases:

// Should be tested:
"9223372036854775807"   // i64::MAX - should succeed
"-9223372036854775808"  // i64::MIN - should succeed  
"9223372036854775808"   // i64::MAX + 1 - should fail
"-9223372036854775809"  // i64::MIN - 1 - should fail

Rationale:

  • Documentation explicitly mentions the range (runtime/src/string_ops.rs:483)
  • Similar operations have overflow tests (e.g., runtime/src/float_ops.rs:585-607)
  • The codebase emphasizes overflow testing (runtime/src/arithmetic.rs:505-577)

Suggested addition:

#[test]
fn test_string_to_int_max_value() {
    unsafe {
        let stack = std::ptr::null_mut();
        let stack = push(stack, Value::String(global_string("9223372036854775807".to_owned())));
        let stack = string_to_int(stack);
        let (stack, success) = pop(stack);
        let (stack, value) = pop(stack);
        assert_eq!(success, Value::Int(1));
        assert_eq!(value, Value::Int(i64::MAX));
        assert!(stack.is_null());
    }
}

#[test]
fn test_string_to_int_overflow() {
    unsafe {
        let stack = std::ptr::null_mut();
        let stack = push(stack, Value::String(global_string("9223372036854775808".to_owned())));
        let stack = string_to_int(stack);
        let (stack, success) = pop(stack);
        assert_eq!(success, Value::Int(0)); // Should fail
        assert!(stack.is_null());
    }
}

3. Minor: Inconsistent export location (Code Organization)

The export for patch_seq_int_to_string is in runtime/src/lib.rs:76 (io module) while patch_seq_string_to_int is in line 80 (string_ops module). These complementary operations are split:

// Line 76: From io module  
pub use io::patch_seq_int_to_string as int_to_string;

// Line 80: From string_ops module
pub use string_ops::{..., patch_seq_string_to_int as string_to_int, ...};

Suggestion: Consider moving int->string to string_ops.rs for better cohesion, or document why they're separate. This is minor since the current organization works fine.

📋 Other Observations

Documentation Updates

  • ✅ ROADMAP.md correctly updated to mark Integer I/O as complete
  • ✅ Long-term goals section appropriately added for deferred features
  • ✅ Commit messages are descriptive and detailed

Performance Considerations

  • ✅ No performance issues - uses efficient trim().parse::<i64>()
  • ✅ No unnecessary allocations

Security Considerations

  • ✅ No security vulnerabilities
  • ✅ Proper bounds checking via Rust's parse implementation
  • ✅ No unsafe behavior beyond documented FFI boundaries

📊 Summary

Category Status
Code Quality ✅ Excellent
Test Coverage ⚠️ Good (missing overflow tests)
Security ✅ No issues
Performance ✅ Optimal
Documentation ✅ Complete
Repository Hygiene ❌ Binary file committed

Recommendations

Must Fix Before Merge:

  1. Remove the output binary file from the commit

Should Add:
2. Add boundary/overflow test cases (i64::MAX, i64::MIN, overflow scenarios)

Nice to Have:
3. Consider consolidating int/string conversion functions in one module

Conclusion

This is a well-implemented feature that follows project conventions and patterns. The main blocker is the accidentally committed binary file. Once that's removed and overflow tests are added, this will be ready to merge.

Great work on maintaining consistency with the string->float implementation and providing comprehensive integration tests! 🎉


🤖 Review generated by Claude Code

@claude
Copy link
Copy Markdown

claude Bot commented Nov 30, 2025

PR Review: String->Int Implementation

Summary

This PR successfully implements the string->int builtin, completing the Integer I/O roadmap item. The implementation is well-designed and follows established codebase patterns.

Code Quality ✅

Strengths:

  • Consistent with existing patterns: The implementation mirrors int->string structure and follows the established return-value convention (value + success flag)
  • Clean integration: All necessary touchpoints updated correctly:
    • compiler/src/ast.rs - Added to builtin list
    • compiler/src/builtins.rs - Type signature correctly defined
    • compiler/src/codegen.rs - LLVM declaration and mapping added
    • runtime/src/lib.rs - Export properly configured
    • runtime/src/string_ops.rs - Implementation and re-export
  • Good documentation: Function has clear safety documentation and behavior specification
  • Error handling: Returns (0, 0) on failure rather than panicking - appropriate for user input

Test Coverage ✅

Excellent coverage with both unit tests and integration tests:

Unit tests (runtime/src/string_ops.rs):

  • ✅ Success case: "42" → 42
  • ✅ Negative numbers: "-99" → -99
  • ✅ Whitespace handling: " 123 " → 123
  • ✅ Leading zeros: "007" → 7
  • ✅ Invalid input: "not a number" → (0, 0)
  • ✅ Empty string: "" → (0, 0)

Integration test (examples/test-string-int.seq):

  • ✅ All success/failure cases
  • ✅ Round-trip conversion: int→string→int

Missing edge case tests (minor):

  • Overflow: "9223372036854775808" (i64::MAX + 1)
  • Underflow: "-9223372036854775809" (i64::MIN - 1)
  • Special inputs: "+42", "0x42", "42.0", "42e10"

The current tests are sufficient, but adding overflow/underflow tests would be valuable since the docs claim support for full i64 range.

Security & Safety ✅

  • No security concerns: Uses Rust's safe parse::<i64>() which handles malformed input gracefully
  • No buffer overflows: String trimming and parsing are memory-safe
  • No injection risks: Pure data conversion, no command execution
  • Proper panic usage: Only panics on type mismatches (programmer error), not user input

Performance ✅

  • Efficient: Single trim + parse operation, no allocations beyond what's necessary
  • Appropriate: Performance is suitable for typical I/O conversions
  • No concerns: String trimming is O(n), parse is O(n) - both unavoidable for this operation

Suggested Improvements (Optional)

  1. Add overflow/underflow tests:
#[test]
fn test_string_to_int_overflow() {
    unsafe {
        let stack = std::ptr::null_mut();
        let stack = push(stack, Value::String(global_string("9223372036854775808".to_owned())));
        let stack = string_to_int(stack);
        let (stack, success) = pop(stack);
        let (_, value) = pop(stack);
        assert_eq!(success, Value::Int(0)); // Should fail
        assert_eq!(value, Value::Int(0));
    }
}
  1. Document special case behavior in string_ops.rs:
    • Does not accept "+" prefix ("+42" fails)
    • Does not accept hex/octal ("0x42", "042" interpreted as decimal)
    • Does not accept floats ("42.0" fails)
    • Does not accept scientific notation ("1e6" fails)

These are already the correct behaviors (Rust's parse::<i64>() rejects these), but documenting them prevents confusion.

Roadmap Update ✅

The ROADMAP.md changes are logical:

  • ✅ Marking Integer I/O as complete is accurate
  • ✅ Moving Variant/Closure capture to Long-Term with rationale makes sense
  • ✅ Clear progression from Near-Term → Medium-Term → Long-Term

Verdict: LGTM

This is production-ready code. The implementation is:

  • Correct and follows established patterns
  • Well-tested with comprehensive coverage
  • Safe and secure
  • Properly documented
  • Cleanly integrated across all layers

The suggested improvements are minor enhancements, not blockers. Great work!


Review generated with Claude Code

@navicore navicore merged commit 6c8bb05 into main Nov 30, 2025
2 checks passed
@navicore navicore deleted the int-io branch November 30, 2025 03:44
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant