diff --git a/core/io.carbon b/core/io.carbon index b5a917e37a45..00e5fa300519 100644 --- a/core/io.carbon +++ b/core/io.carbon @@ -1,8 +1,9 @@ // Part of the Carbon Language project, under the Apache License v2.0 with LLVM // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// AUTOUPDATE + +// TODO: This library is not part of the design. Either write a matching +// proposal or remove this. package Core library "io"; diff --git a/core/range.carbon b/core/range.carbon new file mode 100644 index 000000000000..e0601f50e1c4 --- /dev/null +++ b/core/range.carbon @@ -0,0 +1,46 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// TODO: This library is not part of the design. Either write a matching +// proposal or remove this. + +package Core library "range"; + +import library "prelude/iterate"; +import library "prelude/operators/arithmetic"; +import library "prelude/operators/as"; +import library "prelude/operators/comparison"; +import library "prelude/types/int"; +import library "prelude/types/int_literal"; +import library "prelude/types/optional"; + +class IntRange(N:! IntLiteral()) { + fn Make(start: Int(N), end: Int(N)) -> Self { + return {.start = start, .end = end}; + } + + impl as Iterate where .CursorType = Int(N) and .ElementType = Int(N) { + fn NewCursor[self: Self]() -> Int(N) { return self.start; } + fn Next[self: Self](cursor: Int(N)*) -> Optional(Int(N)) { + var value: Int(N) = *cursor; + if (value < self.end) { + ++*cursor; + return Optional(Int(N)).Some(value); + } else { + return Optional(Int(N)).None(); + } + } + } + + private var start: Int(N); + private var end: Int(N); +} + +fn Range(end: i32) -> IntRange(32) { + return IntRange(32).Make(0, end); +} + +fn InclusiveRange(start: i32, end: i32) -> IntRange(32) { + return IntRange(32).Make(start, end + 1); +} diff --git a/examples/advent2024/day10_common.carbon b/examples/advent2024/day10_common.carbon index 839965030215..7ff721a0a5ee 100644 --- a/examples/advent2024/day10_common.carbon +++ b/examples/advent2024/day10_common.carbon @@ -7,20 +7,17 @@ library "day10_common"; import Core library "io"; +import Core library "range"; import library "io_utils"; class Terrain { fn Read() -> Terrain { returned var me: Terrain; - var y: i32 = 0; - while (y < 43) { - var x: i32 = 0; - while (x < 43) { + for (y: i32 in Core.Range(43)) { + for (x: i32 in Core.Range(43)) { me.height[x][y] = ReadChar() - 0x30; - ++x; } SkipNewline(); - ++y; } return var; } diff --git a/examples/advent2024/day10_part1.carbon b/examples/advent2024/day10_part1.carbon index a8a59c511976..3f79753021a8 100644 --- a/examples/advent2024/day10_part1.carbon +++ b/examples/advent2024/day10_part1.carbon @@ -5,6 +5,7 @@ // https://adventofcode.com/2024/day/10 import Core library "io"; +import Core library "range"; import library "day10_common"; import library "io_utils"; @@ -26,27 +27,21 @@ class Reachable { fn Make(terrain: Terrain) -> Reachable { returned var me: Reachable; var next: u256 = 1; - var y: i32 = 0; - while (y < 43) { - var x: i32 = 0; - while (x < 43) { + for (y: i32 in Core.Range(43)) { + for (x: i32 in Core.Range(43)) { if (terrain.height[x][y] == 0) { me.trailheads[x][y] = next; next <<= 1; } - ++x; } - ++y; } return var; } fn AddLevel[addr self: Self*](terrain: Terrain, level: i32) { let adj: array((i32, i32), 4) = ((-1, 0), (0, -1), (1, 0), (0, 1)); - var y: i32 = 0; - while (y < 43) { - var x: i32 = 0; - while (x < 43) { + for (y: i32 in Core.Range(43)) { + for (x: i32 in Core.Range(43)) { if (terrain.height[x][y] == level) { var reach: u256 = 0; var i: i32 = 0; @@ -62,24 +57,18 @@ class Reachable { } self->trailheads[x][y] = reach; } - ++x; } - ++y; } } fn Count[self: Self](terrain: Terrain, level: i32) -> i32 { var total: i32 = 0; - var y: i32 = 0; - while (y < 43) { - var x: i32 = 0; - while (x < 43) { + for (y: i32 in Core.Range(43)) { + for (x: i32 in Core.Range(43)) { if (terrain.height[x][y] == level) { total += PopCount(self.trailheads[x][y]); } - ++x; } - ++y; } return total; } @@ -90,10 +79,8 @@ class Reachable { fn Run() { var terrain: Terrain = Terrain.Read(); var reachable: Reachable = Reachable.Make(terrain); - var i: i32 = 1; - while (i <= 9) { + for (i: i32 in Core.InclusiveRange(1, 9)) { reachable.AddLevel(terrain, i); - ++i; } Core.Print(reachable.Count(terrain, 9)); } diff --git a/examples/advent2024/day10_part2.carbon b/examples/advent2024/day10_part2.carbon index 37ef31fe30d3..290e0b4e887a 100644 --- a/examples/advent2024/day10_part2.carbon +++ b/examples/advent2024/day10_part2.carbon @@ -5,6 +5,7 @@ // https://adventofcode.com/2024/day/10 import Core library "io"; +import Core library "range"; import library "day10_common"; import library "io_utils"; @@ -12,16 +13,12 @@ import library "io_utils"; class PathsToTop { fn Make(terrain: Terrain) -> PathsToTop { returned var me: PathsToTop; - var y: i32 = 0; - while (y < 43) { - var x: i32 = 0; - while (x < 43) { + for (y: i32 in Core.Range(43)) { + for (x: i32 in Core.Range(43)) { // TODO: We shouldn't need an explicit cast here. me.paths[x][y] = if terrain.height[x][y] == 9 then 1 as i64 else 0; - ++x; } - ++y; } return var; } @@ -29,14 +26,12 @@ class PathsToTop { fn AddLevel[addr self: Self*](terrain: Terrain, level: i32) -> i64 { var total: i64 = 0; let adj: array((i32, i32), 4) = ((-1, 0), (0, -1), (1, 0), (0, 1)); - var y: i32 = 0; - while (y < 43) { - var x: i32 = 0; - while (x < 43) { + for (y: i32 in Core.Range(43)) { + for (x: i32 in Core.Range(43)) { if (terrain.height[x][y] == level) { var paths: i64 = 0; - var i: i32 = 0; - while (i < 4) { + // TODO: for ((adj_x: i32, adj_y: i32) in adj) { + for (i: i32 in Core.Range(4)) { let adj_x: i32 = x + adj[i].0; let adj_y: i32 = y + adj[i].1; if (adj_x >= 0 and adj_x < 43 and @@ -44,14 +39,11 @@ class PathsToTop { terrain.height[adj_x][adj_y] == level + 1) { paths += self->paths[adj_x][adj_y]; } - ++i; } self->paths[x][y] = paths; total += paths; } - ++x; } - ++y; } return total; } @@ -62,11 +54,9 @@ class PathsToTop { fn Run() { var terrain: Terrain = Terrain.Read(); var paths: PathsToTop = PathsToTop.Make(terrain); - var i: i32 = 8; var total: i64; - while (i >= 0) { - total = paths.AddLevel(terrain, i); - --i; + for (i: i32 in Core.InclusiveRange(0, 8)) { + total = paths.AddLevel(terrain, 8 - i); } PrintInt64(total); } diff --git a/examples/advent2024/day11_part2.carbon b/examples/advent2024/day11_part2.carbon index 4f3a78f8ab8a..7c2d4a4111bd 100644 --- a/examples/advent2024/day11_part2.carbon +++ b/examples/advent2024/day11_part2.carbon @@ -5,6 +5,7 @@ // https://adventofcode.com/2024/day/11 import Core library "io"; +import Core library "range"; import library "day11_common"; import library "io_utils"; @@ -12,31 +13,23 @@ import library "io_utils"; class Digits { fn Make() -> Digits { returned var me: Digits; - var digit: i32 = 0; - while (digit < 10) { - var depth: i32 = 0; - while (depth < 75) { + for (digit: i32 in Core.Range(10)) { + for (depth: i32 in Core.Range(75)) { me.count[digit][depth] = 0; - ++depth; } - ++digit; } return var; } fn Print[self: Self](max_depth: i32) { - var digit: i32 = 0; - while (digit < 10) { + for (digit: i32 in Core.Range(10)) { Core.PrintChar(digit + 0x30); Core.PrintChar(0x3A); - var depth: i32 = 0; - while (depth <= max_depth) { + for (depth: i32 in Core.Range(max_depth)) { Core.PrintChar(0x20); PrintInt64NoNewline(self.count[digit][depth]); - ++depth; } Core.PrintChar(0x0A); - ++digit; } Core.PrintChar(0x0A); } @@ -74,15 +67,13 @@ fn Run() { while (depth >= 0) { PrintInt64(total); digits.Print(depth); - var digit: i64 = 0; - while (digit < 10) { - let m: i64 = digits.count[digit as i32][depth]; + for (digit: i32 in Core.Range(10)) { + let m: i64 = digits.count[digit][depth]; if (m > 0) { - let next: (i64, i64) = Next(digit); + let next: (i64, i64) = Next(digit as i64); total += ReduceToDigits(next.0, depth, m, &digits) + ReduceToDigits(next.1, depth, m, &digits); } - ++digit; } --depth; } diff --git a/examples/advent2024/day12_common.carbon b/examples/advent2024/day12_common.carbon index 464d9981886d..604b1fb80316 100644 --- a/examples/advent2024/day12_common.carbon +++ b/examples/advent2024/day12_common.carbon @@ -7,20 +7,17 @@ library "day12_common"; import Core library "io"; +import Core library "range"; import library "io_utils"; class Map { fn Read() -> Map { returned var me: Self; - var y: i32 = 0; - while (y < 140) { - var x: i32 = 0; - while (x < 140) { + for (y: i32 in Core.Range(140)) { + for (x: i32 in Core.Range(140)) { me.kind[x][y] = ReadChar(); - ++x; } SkipNewline(); - ++y; } return var; } @@ -37,12 +34,10 @@ class Map { class DisjointSetForest { fn Make() -> DisjointSetForest { returned var me: Self; - var i: i32 = 0; - while (i < 140 * 140) { + for (i: i32 in Core.Range(140 * 140)) { me.nodes[i].next = i; me.nodes[i].weight = 1; me.nodes[i].unions = 0; - ++i; } return var; } @@ -93,12 +88,9 @@ fn MakeRegions(map: Map) -> DisjointSetForest { returned var forest: DisjointSetForest = DisjointSetForest.Make(); - var x: i32 = 0; - while (x < 140) { - var y: i32 = 0; - while (y < 140) { - var a: i32 = 0; - while (a < 2) { + for (x: i32 in Core.Range(140)) { + for (y: i32 in Core.Range(140)) { + for (a: i32 in Core.Range(2)) { // TODO: Crashes toolchain: // let adj: (i32, i32) = if a == 0 then (x - 1, y) else (x, y - 1); // if (map.At(adj.0, adj.1) == map.At(x, y)) { @@ -109,11 +101,8 @@ fn MakeRegions(map: Map) -> DisjointSetForest { if (map.At(adj_x, adj_y) == map.At(x, y)) { forest.Union(y * 140 + x, adj_y * 140 + adj_x); } - ++a; } - ++y; } - ++x; } return var; diff --git a/examples/advent2024/day12_part1.carbon b/examples/advent2024/day12_part1.carbon index 4cc354c0c9f8..3b3e37517006 100644 --- a/examples/advent2024/day12_part1.carbon +++ b/examples/advent2024/day12_part1.carbon @@ -5,6 +5,7 @@ // https://adventofcode.com/2024/day/12 import Core library "io"; +import Core library "range"; import library "day12_common"; import library "io_utils"; @@ -15,15 +16,13 @@ fn Run() { var total: i32 = 0; - var i: i32 = 0; - while (i < 140 * 140) { + for (i: i32 in Core.Range(140 * 140)) { if (regions.Lookup(i) == i) { let area: i32 = regions.Weight(i); let internal_edges: i32 = regions.Unions(i); let perimeter: i32 = area * 4 - internal_edges * 2; total += area * perimeter; } - ++i; } Core.Print(total); diff --git a/examples/advent2024/day12_part2.carbon b/examples/advent2024/day12_part2.carbon index ddcebcb94d08..df75a9515bc3 100644 --- a/examples/advent2024/day12_part2.carbon +++ b/examples/advent2024/day12_part2.carbon @@ -5,16 +5,15 @@ // https://adventofcode.com/2024/day/12 import Core library "io"; +import Core library "range"; import library "day12_common"; import library "io_utils"; fn CountExtensions(map: Map, regions: DisjointSetForest*) -> array(i32, 140 * 140) { returned var extensions: array(i32, 140 * 140); - var i: i32 = 0; - while (i < 140 * 140) { + for (i: i32 in Core.Range(140 * 140)) { extensions[i] = 0; - ++i; } var ext: array({.same: (i32, i32), .adj: (i32, i32)}, 4) = ( @@ -24,24 +23,18 @@ fn CountExtensions(map: Map, regions: DisjointSetForest*) -> array(i32, 140 * 14 {.same = (0, -1), .adj = (1, 0)}, ); - var x: i32 = 0; - while (x < 140) { - var y: i32 = 0; - while (y < 140) { + for (x: i32 in Core.Range(140)) { + for (y: i32 in Core.Range(140)) { let kind: i32 = map.At(x, y); - var e: i32 = 0; - while (e < 4) { + for (e: i32 in Core.Range(4)) { if (map.At(x + ext[e].same.0, y + ext[e].same.1) == kind and map.At(x + ext[e].adj.0, y + ext[e].adj.1) != kind and map.At(x + ext[e].same.0 + ext[e].adj.0, y + ext[e].same.1 + ext[e].adj.1) != kind) { ++extensions[regions->Lookup(y * 140 + x)]; } - ++e; } - ++y; } - ++x; } return var; } @@ -53,8 +46,7 @@ fn Run() { var total: i32 = 0; - var i: i32 = 0; - while (i < 140 * 140) { + for (i: i32 in Core.Range(140 * 140)) { if (regions.Lookup(i) == i) { let area: i32 = regions.Weight(i); let internal_edges: i32 = regions.Unions(i); @@ -62,7 +54,6 @@ fn Run() { let perimeter: i32 = area * 4 - internal_edges * 2 - extensions; total += area * perimeter; } - ++i; } Core.Print(total); diff --git a/examples/advent2024/day1_part1.carbon b/examples/advent2024/day1_part1.carbon index 9a422a651b6a..733e82280f76 100644 --- a/examples/advent2024/day1_part1.carbon +++ b/examples/advent2024/day1_part1.carbon @@ -5,6 +5,7 @@ // https://adventofcode.com/2024/day/1 import Core library "io"; +import Core library "range"; import library "day1_common"; import library "sort"; @@ -18,11 +19,9 @@ fn Run() { Quicksort(&a, 0, n); Quicksort(&b, 0, n); - var i: i32 = 0; var difference: i32 = 0; - while (i < n) { + for (i: i32 in Core.Range(n)) { difference += Abs(a[i] - b[i]); - i += 1; } Core.Print(difference); } diff --git a/examples/advent2024/day4_part1.carbon b/examples/advent2024/day4_part1.carbon index 7bcce71d2fa6..33ae4018c9ac 100644 --- a/examples/advent2024/day4_part1.carbon +++ b/examples/advent2024/day4_part1.carbon @@ -5,6 +5,7 @@ // https://adventofcode.com/2024/day/4 import Core library "io"; +import Core library "range"; import library "day4_common"; import library "io_utils"; @@ -14,25 +15,16 @@ fn Run() { var xmas: array(i32, 4) = (0x58, 0x4D, 0x41, 0x53); var found: i32 = 0; - // TODO: Use for loops once they're implemented. - var y: i32 = 0; - while (y < 140) { - var x: i32 = 0; - while (x < 140) { - var dy: i32 = -1; - while (dy <= 1) { - var dx: i32 = -1; - while (dx <= 1) { + for (y: i32 in Core.Range(140)) { + for (x: i32 in Core.Range(140)) { + for (dy: i32 in Core.InclusiveRange(-1, 1)) { + for (dx: i32 in Core.InclusiveRange(-1, 1)) { if (search.Check4(xmas, x, y, dx, dy)) { ++found; } - ++dx; } - ++dy; } - ++x; } - ++y; } Core.Print(found); } diff --git a/examples/advent2024/day4_part2.carbon b/examples/advent2024/day4_part2.carbon index e685434c450d..4bea28406cd2 100644 --- a/examples/advent2024/day4_part2.carbon +++ b/examples/advent2024/day4_part2.carbon @@ -5,6 +5,7 @@ // https://adventofcode.com/2024/day/4 import Core library "io"; +import Core library "range"; import library "day4_common"; import library "io_utils"; @@ -14,20 +15,15 @@ fn Run() { var mas: array(i32, 3) = (0x4D, 0x41, 0x53); var found: i32 = 0; - // TODO: Use for loops once they're implemented. - var y: i32 = 1; - while (y < 139) { - var x: i32 = 1; - while (x < 139) { + for (y: i32 in Core.InclusiveRange(1, 138)) { + for (x: i32 in Core.InclusiveRange(1, 138)) { if ((search.Check3(mas, x - 1, y - 1, 1, 1) or search.Check3(mas, x + 1, y + 1, -1, -1)) and (search.Check3(mas, x - 1, y + 1, 1, -1) or search.Check3(mas, x + 1, y - 1, -1, 1))) { ++found; } - ++x; } - ++y; } Core.Print(found); } diff --git a/examples/advent2024/day5_common.carbon b/examples/advent2024/day5_common.carbon index 3311cea82af1..dbd225a28cfd 100644 --- a/examples/advent2024/day5_common.carbon +++ b/examples/advent2024/day5_common.carbon @@ -6,6 +6,8 @@ library "day5_common"; +import Core library "range"; + import library "io_utils"; fn PageMask(page: i32) -> Core.UInt(100) { @@ -16,10 +18,8 @@ fn PageMask(page: i32) -> Core.UInt(100) { class Rules { fn Read() -> Rules { returned var rules: Rules; - var i: i32 = 0; - while (i < 100) { + for (i: i32 in Core.Range(100)) { rules.disallowed_before[i] = 0; - ++i; } var a: i32; @@ -68,39 +68,33 @@ class PageList { fn FollowsRules[self: Self](rules: Rules) -> bool { var seen: Core.UInt(100) = 0; - var i: i32 = 0; - while (i < self.num_pages) { + for (i: i32 in Core.Range(self.num_pages)) { let page: i32 = self.pages[i]; if (seen & rules.disallowed_before[page] != 0) { return false; } seen |= PageMask(page); - ++i; } return true; } fn IsPossibleFirstPage[self: Self](rules: Rules, page: i32) -> bool { - var i: i32 = 0; - while (i < self.num_pages) { + for (i: i32 in Core.Range(self.num_pages)) { if (not rules.IsValidOrder(page, self.pages[i])) { return false; } - ++i; } return true; } fn ExtractPossibleFirstPage[addr self: Self*](rules: Rules) -> i32 { - var i: i32 = 0; - while (i < self->num_pages) { + for (i: i32 in Core.Range(self->num_pages)) { var page: i32 = self->pages[i]; if (self->IsPossibleFirstPage(rules, page)) { self->pages[i] = self->pages[self->num_pages - 1]; --self->num_pages; return page; } - ++i; } // TODO: Assert. return 0; diff --git a/examples/advent2024/day8_common.carbon b/examples/advent2024/day8_common.carbon index e86918cd9d3e..1eab40fb3858 100644 --- a/examples/advent2024/day8_common.carbon +++ b/examples/advent2024/day8_common.carbon @@ -7,20 +7,17 @@ library "day8_common"; import Core library "io"; +import Core library "range"; import library "io_utils"; class Grid { fn Read() -> Grid { returned var me: Grid; - var y: i32 = 0; - while (y < 50) { - var x: i32 = 0; - while (x < 50) { + for (y: i32 in Core.Range(50)) { + for (x: i32 in Core.Range(50)) { me.data[x][y] = ReadChar(); - ++x; } SkipNewline(); - ++y; } return var; } diff --git a/examples/advent2024/day8_part1.carbon b/examples/advent2024/day8_part1.carbon index 08898a9df430..5437c7595b09 100644 --- a/examples/advent2024/day8_part1.carbon +++ b/examples/advent2024/day8_part1.carbon @@ -5,17 +5,16 @@ // https://adventofcode.com/2024/day/8 import Core library "io"; +import Core library "range"; import library "day8_common"; import library "io_utils"; fn IsAntinode(grid: Grid, ox: i32, oy: i32) -> bool { - var ay: i32 = 0; - while (ay < 50) { + for (ay: i32 in Core.Range(50)) { let by: i32 = ay * 2 - oy; if (by >= 0 and by < 50) { - var ax: i32 = 0; - while (ax < 50) { + for (ax: i32 in Core.Range(50)) { let bx: i32 = ax * 2 - ox; if (bx >= 0 and bx < 50 and (ax != bx or ay != by)) { if (grid.data[ax][ay] != 0x2E and @@ -23,26 +22,20 @@ fn IsAntinode(grid: Grid, ox: i32, oy: i32) -> bool { return true; } } - ++ax; } } - ++ay; } return false; } fn CountAntinodes(grid: Grid) -> i32 { var count: i32 = 0; - var y: i32 = 0; - while (y < 50) { - var x: i32 = 0; - while (x < 50) { + for (y: i32 in Core.Range(50)) { + for (x: i32 in Core.Range(50)) { if (IsAntinode(grid, x, y)) { ++count; } - ++x; } - ++y; } return count; } diff --git a/examples/advent2024/day8_part2.carbon b/examples/advent2024/day8_part2.carbon index 6ee243c1fc37..6a522f2cf6fe 100644 --- a/examples/advent2024/day8_part2.carbon +++ b/examples/advent2024/day8_part2.carbon @@ -5,6 +5,7 @@ // https://adventofcode.com/2024/day/8 import Core library "io"; +import Core library "range"; import library "day8_common"; import library "io_utils"; @@ -19,14 +20,11 @@ fn MarkAndCount(marks: array(array(bool, 50), 50)*, x: i32, y: i32) -> i32 { fn MarkAndCountAntinodesFor(grid: Grid, marks: array(array(bool, 50), 50)*, ax: i32, ay: i32) -> i32 { var count: i32 = 0; - var by: i32 = 0; - while (by < 50) { - var bx: i32 = 0; - while (bx < 50) { + for (by: i32 in Core.Range(50)) { + for (bx: i32 in Core.Range(50)) { let dx: i32 = bx - ax; let dy: i32 = by - ay; if (grid.data[bx][by] != grid.data[ax][ay] or (dx == 0 and dy == 0)) { - ++bx; continue; } @@ -37,39 +35,29 @@ fn MarkAndCountAntinodesFor(grid: Grid, marks: array(array(bool, 50), 50)*, ax: x += dx; y += dy; } - ++bx; } - ++by; } return count; } fn MarkAndCountAntinodes(grid: Grid, marks: array(array(bool, 50), 50)*) -> i32 { var count: i32 = 0; - var y: i32 = 0; - while (y < 50) { - var x: i32 = 0; - while (x < 50) { + for (y: i32 in Core.Range(50)) { + for (x: i32 in Core.Range(50)) { if (grid.data[x][y] != 0x2E) { count += MarkAndCountAntinodesFor(grid, marks, x, y); } - ++x; } - ++y; } return count; } fn Run() { var marks: array(array(bool, 50), 50); - var y: i32 = 0; - while (y < 50) { - var x: i32 = 0; - while (x < 50) { + for (y: i32 in Core.Range(50)) { + for (x: i32 in Core.Range(50)) { marks[x][y] = false; - ++x; } - ++y; } Core.Print(MarkAndCountAntinodes(Grid.Read(), &marks)); diff --git a/examples/advent2024/day9_common.carbon b/examples/advent2024/day9_common.carbon index 9b66138f5036..049b8a8ae7e2 100644 --- a/examples/advent2024/day9_common.carbon +++ b/examples/advent2024/day9_common.carbon @@ -7,6 +7,7 @@ library "day9_common"; import Core library "io"; +import Core library "range"; import library "io_utils"; class SectorList { @@ -19,11 +20,9 @@ class SectorList { var c: i32 = ReadChar(); while (c != Core.EOF() and c != 0xA) { let v: i32 = if used then sector else -1; - var n: i32 = c - 0x30; - while (n > 0) { + for (_: i32 in Core.Range(c - 0x30)) { me.data[me.size] = v; ++me.size; - --n; } if (used) { ++sector; @@ -52,21 +51,17 @@ class SectorList { } fn HasSpace[addr self: Self*](start: i32, size: i32) -> bool { - var i: i32 = start; - while (i < start + size) { + for (i: i32 in Core.InclusiveRange(start, start + size - 1)) { if (self->data[i] != -1) { return false; } - ++i; } return true; } fn Fill[addr self: Self*](start: i32, size: i32, sector: i32) { - var i: i32 = start; - while (i < start + size) { + for (i: i32 in Core.InclusiveRange(start, start + size - 1)) { self->data[i] = sector; - ++i; } } @@ -106,12 +101,10 @@ class SectorList { fn Checksum[self: Self]() -> i64 { var total: i64 = 0; - var i: i32 = 0; - while (i < self.size) { + for (i: i32 in Core.Range(self.size)) { if (self.data[i] != -1) { total = total + ((i * self.data[i]) as i64); } - ++i; } return total; } diff --git a/examples/advent2024/io_utils.carbon b/examples/advent2024/io_utils.carbon index 96443864abf1..bb16cb32f6e7 100644 --- a/examples/advent2024/io_utils.carbon +++ b/examples/advent2024/io_utils.carbon @@ -5,6 +5,7 @@ library "io_utils"; import Core library "io"; +import Core library "range"; // If non-zero, this is the most recently read character plus 2. // The +2 is necessary to distinguish the case of no unread character @@ -114,12 +115,10 @@ fn SkipNewline() -> bool { } fn SkipNChars(n: i32) -> bool { - var i: i32 = 0; - while (i < n) { + for (_: i32 in Core.Range(n)) { if (ReadChar() == Core.EOF()) { return false; } - ++i; } return true; } diff --git a/examples/sieve.carbon b/examples/sieve.carbon index 0753cc604fb0..32a1c597db49 100644 --- a/examples/sieve.carbon +++ b/examples/sieve.carbon @@ -3,20 +3,16 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception import Core library "io"; +import Core library "range"; // Compute and return the number of primes less than 1000. class Sieve { fn Make() -> Sieve { returned var s: Sieve; - - // TODO: `for` loop. - var n: i32 = 0; - while (n < 1000) { + for (n: i32 in Core.Range(1000)) { s.is_prime[n] = true; - ++n; } - return var; } @@ -35,14 +31,12 @@ fn Run() -> i32 { var s: Sieve = Sieve.Make(); var number_of_primes: i32 = 0; - var n: i32 = 2; - while (n < 1000) { + for (n: i32 in Core.InclusiveRange(2, 999)) { if (s.is_prime[n]) { ++number_of_primes; Core.Print(n); s.MarkMultiplesNotPrime(n); } - ++n; } return number_of_primes;