From 2b2f27a9ce4f526abd65cfb56c6a3c103c516d3e Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 4 Apr 2024 13:13:01 -0700 Subject: [PATCH] Add core library with operator interface definitions and an example program. (#3856) This is almost certainly not how we'll want these to be organized, and if the examples/ directory is kept it should have BUILD files. But this at least lets me park these files somewhere that's more global than my own checkout. --- core/prelude/i32.carbon | 128 +++++++++++++++++++++++++++ core/prelude/operators.carbon | 104 ++++++++++++++++++++++ examples/sieve.carbon | 161 ++++++++++++++++++++++++++++++++++ 3 files changed, 393 insertions(+) create mode 100644 core/prelude/i32.carbon create mode 100644 core/prelude/operators.carbon create mode 100644 examples/sieve.carbon diff --git a/core/prelude/i32.carbon b/core/prelude/i32.carbon new file mode 100644 index 000000000000..6b3068e8bac0 --- /dev/null +++ b/core/prelude/i32.carbon @@ -0,0 +1,128 @@ +// 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 + +package Core library "i32" api; + +import library "prelude/operators"; + +impl i32 as Add { + fn Op[self: Self](other: Self) -> Self = "int.add"; +} +impl i32 as AddAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self + other; + } +} +impl i32 as Inc { + fn Op[addr self: Self*]() { + *self += 1; + } +} + +impl i32 as BitAnd { + fn Op[self: Self](other: Self) -> Self = "int.and"; +} +impl i32 as BitAndAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self + other; + } +} + +impl i32 as BitComplement { + fn Op[self: Self]() -> Self = "int.complement"; +} + +impl i32 as BitOr { + fn Op[self: Self](other: Self) -> Self = "int.or"; +} +impl i32 as BitOrAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self + other; + } +} + +impl i32 as BitXor { + fn Op[self: Self](other: Self) -> Self = "int.xor"; +} +impl i32 as BitXorAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self ^ other; + } +} + +impl i32 as Div { + fn Op[self: Self](other: Self) -> Self = "int.div"; +} +impl i32 as DivAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self / other; + } +} + +impl i32 as Eq { + fn Equal[self: Self](other: Self) -> bool = "int.eq"; + fn NotEqual[self: Self](other: Self) -> bool = "int.neq"; +} + +impl i32 as LeftShift { + fn Op[self: Self](other: Self) -> Self = "int.left_shift"; +} +impl i32 as LeftShiftAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self << other; + } +} + +impl i32 as Mod { + fn Op[self: Self](other: Self) -> Self = "int.mod"; +} +impl i32 as ModAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self % other; + } +} + +impl i32 as Mul { + fn Op[self: Self](other: Self) -> Self = "int.mul"; +} +impl i32 as MulAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self * other; + } +} + +impl i32 as Negate { + fn Op[self: Self]() -> Self = "int.negate"; +} + +impl i32 as Ordered { + // TODO: fn Compare + fn Less[self: Self](other: Self) -> bool = "int.less"; + fn LessOrEquivalent[self: Self](other: Self) -> bool = "int.less_eq"; + fn Greater[self: Self](other: Self) -> bool = "int.greater"; + fn GreaterOrEquivalent[self: Self](other: Self) -> bool = "int.greater_eq"; +} + +impl i32 as RightShift { + fn Op[self: Self](other: Self) -> Self = "int.right_shift"; +} +impl i32 as RightShiftAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self >> other; + } +} + +impl i32 as Sub { + fn Op[self: Self](other: Self) -> Self = "int.sub"; +} +impl i32 as SubAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self - other; + } +} +impl i32 as Dec { + fn Op[addr self: Self*]() { + *self -= 1; + } +} diff --git a/core/prelude/operators.carbon b/core/prelude/operators.carbon new file mode 100644 index 000000000000..7854c9768716 --- /dev/null +++ b/core/prelude/operators.carbon @@ -0,0 +1,104 @@ +// 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 + +package Core library "prelude/operators" api; + +interface Add { + fn Op[self: Self](other: Self) -> Self; +} +interface AddAssign { + fn Op[addr self: Self*](other: Self); +} + +interface BitAnd { + fn Op[self: Self](other: Self) -> Self; +} +interface BitAndAssign { + fn Op[addr self: Self*](other: Self); +} + +interface BitComplement { + fn Op[self: Self]() -> Self; +} + +interface BitOr { + fn Op[self: Self](other: Self) -> Self; +} +interface BitOrAssign { + fn Op[addr self: Self*](other: Self); +} + +interface BitXor { + fn Op[self: Self](other: Self) -> Self; +} +interface BitXorAssign { + fn Op[addr self: Self*](other: Self); +} + +interface Dec { + fn Op[addr self: Self*](); +} + +interface Div { + fn Op[self: Self](other: Self) -> Self; +} +interface DivAssign { + fn Op[addr self: Self*](other: Self); +} + +interface Eq { + fn Equal[self: Self](other: Self) -> bool; + fn NotEqual[self: Self](other: Self) -> bool; +} + +interface Inc { + fn Op[addr self: Self*](); +} + +interface LeftShift { + fn Op[self: Self](other: Self) -> Self; +} +interface LeftShiftAssign { + fn Op[addr self: Self*](other: Self); +} + +interface Mod { + fn Op[self: Self](other: Self) -> Self; +} +interface ModAssign { + fn Op[addr self: Self*](other: Self); +} + +interface Mul { + fn Op[self: Self](other: Self) -> Self; +} +interface MulAssign { + fn Op[addr self: Self*](other: Self); +} + +interface Negate { + fn Op[self: Self]() -> Self; +} + +interface Ordered { + // TODO: fn Compare + fn Less[self: Self](other: Self) -> bool; + fn LessOrEquivalent[self: Self](other: Self) -> bool; + fn Greater[self: Self](other: Self) -> bool; + fn GreaterOrEquivalent[self: Self](other: Self) -> bool; +} + +interface RightShift { + fn Op[self: Self](other: Self) -> Self; +} +interface RightShiftAssign { + fn Op[addr self: Self*](other: Self); +} + +interface Sub { + fn Op[self: Self](other: Self) -> Self; +} +interface SubAssign { + fn Op[addr self: Self*](other: Self); +} diff --git a/examples/sieve.carbon b/examples/sieve.carbon new file mode 100644 index 000000000000..18eba08ccdd5 --- /dev/null +++ b/examples/sieve.carbon @@ -0,0 +1,161 @@ +// 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 + +// Compute and return the number of primes less than 1000. + +import Core library "operators"; + +// TODO: Copied from i32.carbon. +// Remove the following, once we do cross-file impl lookup. +// import Core library "i32"; + +impl i32 as Core.Add { + fn Op[self: Self](other: Self) -> Self = "int.add"; +} +impl i32 as Core.AddAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self + other; + } +} +impl i32 as Core.Inc { + fn Op[addr self: Self*]() { + *self += 1; + } +} + +impl i32 as Core.BitAnd { + fn Op[self: Self](other: Self) -> Self = "int.and"; +} +impl i32 as Core.BitAndAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self + other; + } +} + +impl i32 as Core.BitComplement { + fn Op[self: Self]() -> Self = "int.complement"; +} + +impl i32 as Core.BitOr { + fn Op[self: Self](other: Self) -> Self = "int.or"; +} +impl i32 as Core.BitOrAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self + other; + } +} + +impl i32 as Core.BitXor { + fn Op[self: Self](other: Self) -> Self = "int.xor"; +} +impl i32 as Core.BitXorAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self ^ other; + } +} + +impl i32 as Core.Div { + fn Op[self: Self](other: Self) -> Self = "int.div"; +} +impl i32 as Core.DivAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self / other; + } +} + +impl i32 as Core.Eq { + fn Equal[self: Self](other: Self) -> bool = "int.eq"; + fn NotEqual[self: Self](other: Self) -> bool = "int.neq"; +} + +impl i32 as Core.LeftShift { + fn Op[self: Self](other: Self) -> Self = "int.left_shift"; +} +impl i32 as Core.LeftShiftAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self << other; + } +} + +impl i32 as Core.Mod { + fn Op[self: Self](other: Self) -> Self = "int.mod"; +} +impl i32 as Core.ModAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self % other; + } +} + +impl i32 as Core.Mul { + fn Op[self: Self](other: Self) -> Self = "int.mul"; +} +impl i32 as Core.MulAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self * other; + } +} + +impl i32 as Core.Negate { + fn Op[self: Self]() -> Self = "int.negate"; +} + +impl i32 as Core.Ordered { + // TODO: fn Compare + fn Less[self: Self](other: Self) -> bool = "int.less"; + fn LessOrEquivalent[self: Self](other: Self) -> bool = "int.less_eq"; + fn Greater[self: Self](other: Self) -> bool = "int.greater"; + fn GreaterOrEquivalent[self: Self](other: Self) -> bool = "int.greater_eq"; +} + +impl i32 as Core.RightShift { + fn Op[self: Self](other: Self) -> Self = "int.right_shift"; +} +impl i32 as Core.RightShiftAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self >> other; + } +} + +impl i32 as Core.Sub { + fn Op[self: Self](other: Self) -> Self = "int.sub"; +} +impl i32 as Core.SubAssign { + fn Op[addr self: Self*](other: Self) { + *self = *self - other; + } +} +impl i32 as Core.Dec { + fn Op[addr self: Self*]() { + *self -= 1; + } +} + +// --- + +fn Run() -> i32 { + var is_prime: [bool; 1000]; + + // TODO: `for` loop. + var n: i32 = 0; + while (n < 1000) { + is_prime[n] = true; + ++n; + } + + var number_of_primes: i32 = 0; + n = 2; + while (n < 1000) { + if (is_prime[n]) { + ++number_of_primes; + var k: i32 = 2 * n; + while (k < 1000) { + is_prime[k] = false; + k += n; + } + } + ++n; + } + + return number_of_primes; +}