Skip to content

feat: implement full 'for' loop support and strict type narrowing checks#294

Merged
LunaStev merged 1 commit intowavefnd:masterfrom
LunaStev:feat/implement-full-for-loop-support-and-strict-type-narrowing-checks-
Feb 23, 2026
Merged

feat: implement full 'for' loop support and strict type narrowing checks#294
LunaStev merged 1 commit intowavefnd:masterfrom
LunaStev:feat/implement-full-for-loop-support-and-strict-type-narrowing-checks-

Conversation

@LunaStev
Copy link
Member

This PR significantly enhances the Wave language by introducing full support for C-style for loops and enforcing stricter type safety across the board. Key improvements include a transition to a Result-based error reporting system in the parser and the prevention of unsafe implicit integer narrowing.


Key Changes

1. Full for Loop Implementation

  • Scoped Initialization: The for loop now supports local variable declarations within the initialization block (e.g., for (var i: i32 = 0; i < 10; i++)).
  • Codegen & Scope: Implemented gen_for_ir in the LLVM backend with proper scope management. Variables declared in the loop header are automatically cleaned up when the loop exits.
  • Validation: Added semantic passes to verify the integrity of loop headers, ensuring the condition is a boolean and the increment/initialization blocks are valid statements.

2. Strict Type Safety & Narrowing Prevention

  • Forbidden Narrowing: Implicit narrowing of integers (e.g., assigning an i64 value to an i32 variable) is now a compiler error. This prevents subtle data loss bugs during assignments, binary operations, and function calls.
  • Contextual Literal Inference: Numeric literals now use a "context-aware" inference strategy. Instead of defaulting to a fixed type, they look for type hints from the other side of an expression or the variable's declared type.

3. Parser Robustness & Error Reporting

  • Result-based Parsing: Refactored the internal parser API from Option<T> to Result<T, ParseError>. This allows the compiler to provide detailed diagnostic messages, including source labels, line numbers, and "help" hints.
  • Improved Imports: The import system now propagates structured errors, making it much easier to debug syntax errors within imported standard library modules.

4. Standard Library & Optimization

  • Module Refactor: Reorganized the standard library into role-based modules (e.g., moving from umbrella files to specific paths like std::time::clock).
  • Optimization Normalization: Normalized the backend optimization pipeline. The -Ofast flag now correctly maps to -O3 logic, and all flags are consistently applied through the new LLVM PassBuilder.

Example Usage

Standard for loop with local scope:

fun main() {
    // i is only visible inside the loop
    for (var i: i32 = 0; i < 5; i++) {
        println("Iteration: {}", i);
    }
}

Benefits

  • Expressiveness: Standard for loops provide a more ergonomic way to handle iterations compared to while loops.
  • Safety: Stricter type checks catch potential overflow or data loss issues at compile-time.
  • Diagnostic Quality: The shift to Result-based parsing provides a much better developer experience through clearer error messages.

This commit introduces comprehensive support for C-style 'for' loops,
overhauls the parser's error reporting mechanism, and enforces strict
type safety by forbidding implicit integer narrowing.

Changes:
- **For Loop Implementation**:
  - **Parser**: Updated `StatementNode::For` to support local variable
    declarations in the initialization block (e.g., `for (var i: i32 = 0; ...)`).
  - **Codegen**: Implemented `gen_for_ir` in the LLVM backend, including
    proper scope management for loop-local variables.
  - **Validation**: Added verification passes to ensure correct scoping
    and type safety within for-loop headers.
- **Strict Type Safety**:
  - **Narrowing Prevention**: Explicitly forbidden implicit integer
    narrowing (e.g., assigning `i64` to `i32`) in assignments, binary
    operations, and function arguments.
  - **Literal Inference**: Enhanced numeric literal type inference to
    be context-dependent, relying on hints from the other side of
    binary expressions or explicit type context.
- **Parser Improvements**:
  - **Result-based Parsing**: Refactored the `parse` function to return
    `Result<Vec<ASTNode>, ParseError>` instead of `Option`, enabling
    detailed error messages for syntax and semantic failures.
  - **Import Handling**: Updated `import.rs` to propagate structured
    parsing errors with source labels and helpful hints.
- **Standard Library & Tooling**:
  - **Stdlib Refactoring**: Cleaned up the standard library structure by
    removing redundant umbrella files and moving to role-based module
    imports (e.g., `std::time::clock`).
  - **Documentation**: Updated `std/README.md` with a strict dependency
    policy regarding `extern(c)` usage.
  - **Optimization**: Aligned backend optimization behavior by mapping
    `-Ofast` to `-O3` and normalizing flags across the LLVM pass pipeline.
- **Testing**:
  - Updated test cases to reflect strict type checking and new standard
    library import paths.

These changes significantly improve the language's expressiveness while
ensuring a higher level of compile-time safety.

Signed-off-by: LunaStev <luna@lunastev.org>
@LunaStev LunaStev self-assigned this Feb 23, 2026
@LunaStev LunaStev merged commit d9d516a into wavefnd:master Feb 23, 2026
2 checks passed
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.

1 participant