Skip to content

Chapter 12: Unsigned Integers (unsigned int / unsigned long) - #21

Merged
johnhringiv merged 3 commits into
mainfrom
chapter_12
Jun 14, 2026
Merged

Chapter 12: Unsigned Integers (unsigned int / unsigned long)#21
johnhringiv merged 3 commits into
mainfrom
chapter_12

Conversation

@johnhringiv

Copy link
Copy Markdown
Owner

Completes Chapter 12, adding full support for unsigned int (32-bit) and unsigned long (64-bit).

Added

  • Unsigned integer types, end-to-end:
    • Lexer: u/U and ul/lu/UL/… constant suffixes (→ ConstantUnsignedInt/ConstantUnsignedLong) and the signed/unsigned keywords.
    • Parser: order-independent type-specifier combinations (unsigned long int, …) via specifier counting; suffix-based literal promotion ladders (uu32u64, etc.).
    • Validator: the usual arithmetic conversions (Type::common_with), constant folding over unsigned values, and unsigned-aware duplicate-case detection.
    • Codegen: signedness-aware lowering — idiv/div, sar/shr, signed vs unsigned condition codes (setl/setb, jg/ja, …), and zero-extension (MovZeroExtend) for unsigned widening.
    • Emitters: both the iced and --no-iced text emitters encode the new instructions / condition codes; static-variable emission handles unsigned initializers.
  • Tests: long_min_literal.c, mixed_alignment.c, no_overflow_unsigned.c, and the full Chapter-12 Sandler suite (455/455 through ch12, incl. extra credit).

Changed

  • -Woverflow now fires only for signed overflow — unsigned wraparound is well-defined (mod 2ⁿ) and stays silent, matching gcc/clang.
  • Internal refactors: macro-driven StaticInt arithmetic/comparison ops; single-source conversion helpers (wide, to_le_bytes, data_directive, is_signed); parser is_type_specifier/is_specifier helpers; get_common_typeType::common_with.
  • Docs: README (types, grammar, conversions, warnings) and CLAUDE.md (type-system / arithmetic notes) updated for unsigned; module/function doc comments refreshed and drift removed.

Fixed — preexisting bugs surfaced during this work

  1. Suffixed LONG_MIN rejected. -9223372036854775808L failed to parse — the negation-into-literal fold (which keeps the most-negative value correctly typed) only matched ConstantInt and was never extended to ConstantLong when longs landed in ch11. The unsuffixed form worked by luck via the int→long overflow-promotion path. (regression: long_min_literal.c)
  2. Mixed-alignment static offsets. A 4-byte static declared before an 8-byte static loaded garbage: the iced emitter tracked .data/.bss offsets manually (+= alignment) instead of using the offset append_section_* returns, so the section's alignment padding desynced the symbol offsets. Order-dependent (smaller-aligned first) and affected int/long too — a latent ch11 bug. (regression: mixed_alignment.c)
  3. --run broke for absolute / subdirectory paths. format!("./{}", out_file) turned an absolute out_file into a bogus cwd-relative path (./tmp/...); fixed with Path::new(".").join(out_file). General --run bug, unrelated to unsigned.

🤖 Generated with Claude Code

@claude

claude Bot commented Jun 14, 2026

Copy link
Copy Markdown

Claude finished @johnhringiv's task —— View job


Comprehensive Code Review

I've completed a thorough review of this PR implementing unsigned integer support. This is an excellent implementation with careful attention to detail. Here are my findings:

Todo List:

  • Read repository guidelines (CLAUDE.md)
  • Review core implementation files (lexer, parser, validator, codegen)
  • Analyze type conversion and arithmetic logic
  • Check test coverage and quality
  • Assess code quality and Rust idioms
  • Provide final review feedback

🟢 Strengths

1. Comprehensive End-to-End Implementation

  • Clean propagation through entire compiler pipeline: lexer → parser → validator → codegen → emitter
  • Proper handling of unsigned literal suffixes (u, U, ul, UL, etc.) in src/lexer.rs:109-112
  • Type-safe AST evolution with new Const::ConstUInt/ConstULong variants

2. Excellent Type System Design

  • Elegant Type::common_with() implementation in src/parser.rs following C's usual arithmetic conversions
  • Smart unsigned preference for same-width types: self.is_signed() { other.clone() } else { self.clone() }
  • Proper bit width comparison for type promotion

3. Robust Arithmetic & Overflow Handling

  • Brilliant use of macro-driven checked_op! for consistent arithmetic operations across all integer types
  • Correct distinction: -Woverflow only fires for signed overflow, unsigned wraparound is silent (per C standard)
  • Implementation correctly handles v.get_type().is_signed() checks in src/validate.rs

4. Quality Bug Fixes
The three preexisting bug fixes demonstrate excellent debugging skills:

  • LONG_MIN literal parsing: Fixed negation fold for ConstantLong tokens
  • Mixed alignment static offsets: Properly using append_section_* return values instead of manual offset tracking
  • --run path handling: Using Path::new(".").join() instead of string concatenation

5. Test Coverage

  • Excellent regression tests for each bug fix
  • Tests cover edge cases (LONG_MIN, mixed alignment, unsigned overflow)
  • Good integration with existing test infrastructure

🟡 Minor Areas for Improvement

1. Code Organization (Very Minor)

  • The StaticInt arithmetic operations could benefit from doc comments explaining overflow semantics
  • Consider extracting the suffix parsing logic in lexer into a helper function for clarity

2. Performance Considerations

  • The get_common() method creates new StaticInt instances for type promotion - this is fine for a learning compiler but worth noting
  • Macro-generated match arms in checked_op! could theoretically be optimized, but readability is more important here

3. Error Messages

  • The overflow warning message could specify signed vs unsigned context for clarity
  • Consider adding span information to more warnings for better developer experience

🟢 Security & Safety

  • No security concerns identified
  • Proper integer overflow handling prevents undefined behavior
  • Type system prevents invalid operations between incompatible types
  • All arithmetic operations use Rust's checked arithmetic internally

🟢 Rust Idioms & Best Practices

Excellent Examples:

  • Clean use of macro_rules! for checked_op! - reduces code duplication
  • Proper #[allow(clippy::...)] annotations with explanatory comments
  • Good separation of concerns across modules
  • Consistent error handling patterns

Particularly Elegant:

  • The Wide enum for normalized arithmetic operations
  • Type conversion matrix using the to_target! macro
  • Clean integration with existing SymbolTable and NameGenerator

🟢 Alignment with Project Goals

This implementation perfectly aligns with the learning-focused nature of the project:

  • User implemented core logic themselves (as intended per CLAUDE.md)
  • Changes are educational and well-documented
  • Code demonstrates advanced Rust patterns while remaining readable
  • Excellent commit message explaining the "why" behind each change

🟢 Final Verdict

This is exceptional work. The implementation is:

  • Correct: Proper C semantics for unsigned arithmetic and conversions
  • Complete: End-to-end support with comprehensive test coverage
  • Clean: Idiomatic Rust with excellent abstractions
  • Educational: Clear code structure perfect for a learning project

The bug fixes alone demonstrate deep understanding of the codebase, and the systematic approach to unsigned integer support shows excellent software engineering practices.

Recommendation: Approve and merge. This sets an excellent foundation for future chapters.


@codecov

codecov Bot commented Jun 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.36364% with 51 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/emit_iced.rs 40.54% 22 Missing ⚠️
src/validate.rs 87.20% 11 Missing ⚠️
src/parser.rs 90.72% 9 Missing ⚠️
src/codegen.rs 94.26% 7 Missing ⚠️
src/emit.rs 93.33% 1 Missing ⚠️
src/main.rs 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@claude

claude Bot commented Jun 14, 2026

Copy link
Copy Markdown

Claude finished @johnhringiv's task —— View job


Comprehensive Code Review

I've completed a thorough review of this PR implementing unsigned integer support. This is an excellent implementation with careful attention to detail. Here are my findings:

Todo List:

  • Read repository guidelines (CLAUDE.md)
  • Review core implementation files (lexer, parser, validator, codegen)
  • Analyze type conversion and arithmetic logic
  • Check test coverage and quality
  • Assess code quality and Rust idioms
  • Provide final review feedback

🟢 Strengths

1. Comprehensive End-to-End Implementation

  • Clean propagation through entire compiler pipeline: lexer → parser → validator → codegen → emitter
  • Proper handling of unsigned literal suffixes (u, U, ul, UL, etc.) in src/lexer.rs:109-112
  • Type-safe AST evolution with new Const::ConstUInt/ConstULong variants

2. Excellent Type System Design

  • Elegant Type::common_with() implementation in src/parser.rs following C's usual arithmetic conversions
  • Smart unsigned preference for same-width types: self.is_signed() { other.clone() } else { self.clone() }
  • Proper bit width comparison for type promotion

3. Robust Arithmetic & Overflow Handling

  • Brilliant use of macro-driven checked_op! for consistent arithmetic operations across all integer types
  • Correct distinction: -Woverflow only fires for signed overflow, unsigned wraparound is silent (per C standard)
  • Implementation correctly handles v.get_type().is_signed() checks in src/validate.rs

4. Quality Bug Fixes
The three preexisting bug fixes demonstrate excellent debugging skills:

  • LONG_MIN literal parsing: Fixed negation fold for ConstantLong tokens
  • Mixed alignment static offsets: Properly using append_section_* return values instead of manual offset tracking
  • --run path handling: Using Path::new(".").join() instead of string concatenation

5. Test Coverage

  • Excellent regression tests for each bug fix
  • Tests cover edge cases (LONG_MIN, mixed alignment, unsigned overflow)
  • Good integration with existing test infrastructure

🟡 Minor Areas for Improvement

1. Code Organization (Very Minor)

  • The StaticInt arithmetic operations could benefit from doc comments explaining overflow semantics
  • Consider extracting the suffix parsing logic in lexer into a helper function for clarity

2. Performance Considerations

  • The get_common() method creates new StaticInt instances for type promotion - this is fine for a learning compiler but worth noting
  • Macro-generated match arms in checked_op! could theoretically be optimized, but readability is more important here

3. Error Messages

  • The overflow warning message could specify signed vs unsigned context for clarity
  • Consider adding span information to more warnings for better developer experience

🟢 Security & Safety

  • No security concerns identified
  • Proper integer overflow handling prevents undefined behavior
  • Type system prevents invalid operations between incompatible types
  • All arithmetic operations use Rust's checked arithmetic internally

🟢 Rust Idioms & Best Practices

Excellent Examples:

  • Clean use of macro_rules! for checked_op! - reduces code duplication
  • Proper #[allow(clippy::...)] annotations with explanatory comments
  • Good separation of concerns across modules
  • Consistent error handling patterns

Particularly Elegant:

  • The Wide enum for normalized arithmetic operations
  • Type conversion matrix using the to_target! macro
  • Clean integration with existing SymbolTable and NameGenerator

🟢 Alignment with Project Goals

This implementation perfectly aligns with the learning-focused nature of the project:

  • User implemented core logic themselves (as intended per CLAUDE.md)
  • Changes are educational and well-documented
  • Code demonstrates advanced Rust patterns while remaining readable
  • Excellent commit message explaining the "why" behind each change

🟢 Final Verdict

This is exceptional work. The implementation is:

  • Correct: Proper C semantics for unsigned arithmetic and conversions
  • Complete: End-to-end support with comprehensive test coverage
  • Clean: Idiomatic Rust with excellent abstractions
  • Educational: Clear code structure perfect for a learning project

The bug fixes alone demonstrate deep understanding of the codebase, and the systematic approach to unsigned integer support shows excellent software engineering practices.

Recommendation: Approve and merge. This sets an excellent foundation for future chapters.


@johnhringiv
johnhringiv merged commit 79791c2 into main Jun 14, 2026
4 of 5 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