LLVM type conversions,
+Documenting limitations is also helpful, for instance, can is `@call` ok to
+use? Can I directly write phi nodes? I had a lot of difficulty interacting
+with anything that returns a `!llvm.struct` or `!llvm.vec`.
+
+### `pop.inline_asm`
+
+A lot of CPU functionality doesn't have LLVM intrinsics and we'll need to use
+assembly (CPU time stamp counters, poking MSRs for runtime capability
+discovery, etc). I personally ran into difficulties doing multiple return
+(ex: x86 `cpuid` returns results in 4 registers). Information on the asm
+dialect, how to create clobbers and scratch registers, and rules for control
+flow (ex: can I implement computed gotos, jump into the middle of a function or
+return from the current function?).
+
+### `!lit.origin.set`
+
+This is used in Coroutines (presumably to store capture origins), but it looks
+like it may be useful for storing collections of references.
+
+### The backing allocator(s) for `pop.aligned_alloc` and `pop.global_alloc`
+
+Time spent in GDB has led me to believe this is tcmalloc, but knowing for
+sure means we have information like the minimum alignment the allocator will
+provide (storing information in the lower bits), what kind of caching it does,
+information about how it handles memory overcommit being off (db servers), and
+what kind of instrumentation we might have access to.
diff --git a/stdlib/benchmarks/algorithm/bench_elementwise.mojo b/stdlib/benchmarks/algorithm/bench_elementwise.mojo
index 42ab4732f0..2a302ec80f 100644
--- a/stdlib/benchmarks/algorithm/bench_elementwise.mojo
+++ b/stdlib/benchmarks/algorithm/bench_elementwise.mojo
@@ -15,6 +15,7 @@
# the -t flag. Remember to replace it again before pushing any code.
from sys import simdwidthof
+
from algorithm import elementwise
from benchmark import Bench, BenchConfig, Bencher, BenchId
from buffer import Buffer
@@ -22,11 +23,11 @@ from buffer import Buffer
from utils.index import Index, IndexList
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark elementwise
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
-fn bench_elementwise[n: Int](inout b: Bencher) raises:
+fn bench_elementwise[n: Int](mut b: Bencher) raises:
var vector = Buffer[DType.index, n].stack_allocation()
for i in range(len(vector)):
diff --git a/stdlib/benchmarks/builtin/bench_int.mojo b/stdlib/benchmarks/builtin/bench_int.mojo
index 5a469936f8..2d65c690c3 100644
--- a/stdlib/benchmarks/builtin/bench_int.mojo
+++ b/stdlib/benchmarks/builtin/bench_int.mojo
@@ -17,11 +17,11 @@
from benchmark import Bench, BenchConfig, Bencher, BenchId
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmarks
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
-fn bench_stringify_small_integers(inout b: Bencher) raises:
+fn bench_stringify_small_integers(mut b: Bencher) raises:
@always_inline
@parameter
fn call_fn():
@@ -32,9 +32,9 @@ fn bench_stringify_small_integers(inout b: Bencher) raises:
b.iter[call_fn]()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Main
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
def main():
var m = Bench(BenchConfig(num_repetitions=1))
m.bench_function[bench_stringify_small_integers](
diff --git a/stdlib/benchmarks/builtin/bench_sort.mojo b/stdlib/benchmarks/builtin/bench_sort.mojo
index 57bfcc9e5b..a44fc3a150 100644
--- a/stdlib/benchmarks/builtin/bench_sort.mojo
+++ b/stdlib/benchmarks/builtin/bench_sort.mojo
@@ -14,26 +14,27 @@
# NOTE: to test changes on the current branch using run-benchmarks.sh, remove
# the -t flag. Remember to replace it again before pushing any code.
-from benchmark import Bench, Bencher, BenchId, keep, BenchConfig, Unit, run
-from memory import UnsafePointer
from random import *
+
+from benchmark import Bench, BenchConfig, Bencher, BenchId, Unit, keep, run
+from memory import UnsafePointer
from stdlib.builtin.sort import (
- sort,
- _small_sort,
- _insertion_sort,
_heap_sort,
+ _insertion_sort,
+ _small_sort,
_SortWrapper,
+ sort,
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Utils
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
fn randomize_list[
dt: DType
-](inout list: List[Scalar[dt]], size: Int, max: Scalar[dt] = Scalar[dt].MAX):
+](mut list: List[Scalar[dt]], size: Int, max: Scalar[dt] = Scalar[dt].MAX):
@parameter
if dt.is_integral():
randint(list.data, size, 0, int(max))
@@ -45,7 +46,7 @@ fn randomize_list[
@always_inline
-fn insertion_sort[type: DType](inout list: List[Scalar[type]]):
+fn insertion_sort[type: DType](mut list: List[Scalar[type]]):
@parameter
fn _less_than(
lhs: _SortWrapper[Scalar[type]], rhs: _SortWrapper[Scalar[type]]
@@ -56,7 +57,7 @@ fn insertion_sort[type: DType](inout list: List[Scalar[type]]):
@always_inline
-fn small_sort[size: Int, type: DType](inout list: List[Scalar[type]]):
+fn small_sort[size: Int, type: DType](mut list: List[Scalar[type]]):
@parameter
fn _less_than(
lhs: _SortWrapper[Scalar[type]], rhs: _SortWrapper[Scalar[type]]
@@ -67,7 +68,7 @@ fn small_sort[size: Int, type: DType](inout list: List[Scalar[type]]):
@always_inline
-fn heap_sort[type: DType](inout list: List[Scalar[type]]):
+fn heap_sort[type: DType](mut list: List[Scalar[type]]):
@parameter
fn _less_than(
lhs: _SortWrapper[Scalar[type]], rhs: _SortWrapper[Scalar[type]]
@@ -77,19 +78,19 @@ fn heap_sort[type: DType](inout list: List[Scalar[type]]):
_heap_sort[_less_than](list)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark sort functions with a tiny list size
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
-fn bench_tiny_list_sort[type: DType](inout m: Bench) raises:
+fn bench_tiny_list_sort[type: DType](mut m: Bench) raises:
alias small_list_size = 5
@parameter
for count in range(2, small_list_size + 1):
@parameter
- fn bench_sort_list(inout b: Bencher) raises:
+ fn bench_sort_list(mut b: Bencher) raises:
seed(1)
var ptr = UnsafePointer[Scalar[type]].alloc(count)
var list = List[Scalar[type]](ptr=ptr, length=count, capacity=count)
@@ -108,7 +109,7 @@ fn bench_tiny_list_sort[type: DType](inout m: Bench) raises:
_ = list^
@parameter
- fn bench_small_sort(inout b: Bencher) raises:
+ fn bench_small_sort(mut b: Bencher) raises:
seed(1)
var ptr = UnsafePointer[Scalar[type]].alloc(count)
var list = List[Scalar[type]](ptr=ptr, length=count, capacity=count)
@@ -127,7 +128,7 @@ fn bench_tiny_list_sort[type: DType](inout m: Bench) raises:
_ = list^
@parameter
- fn bench_insertion_sort(inout b: Bencher) raises:
+ fn bench_insertion_sort(mut b: Bencher) raises:
seed(1)
var ptr = UnsafePointer[Scalar[type]].alloc(count)
var list = List[Scalar[type]](ptr=ptr, length=count, capacity=count)
@@ -156,14 +157,14 @@ fn bench_tiny_list_sort[type: DType](inout m: Bench) raises:
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark sort functions with a small list size
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
-fn bench_small_list_sort[type: DType](inout m: Bench, count: Int) raises:
+fn bench_small_list_sort[type: DType](mut m: Bench, count: Int) raises:
@parameter
- fn bench_sort_list(inout b: Bencher) raises:
+ fn bench_sort_list(mut b: Bencher) raises:
seed(1)
var ptr = UnsafePointer[Scalar[type]].alloc(count)
var list = List[Scalar[type]](ptr=ptr, length=count, capacity=count)
@@ -182,7 +183,7 @@ fn bench_small_list_sort[type: DType](inout m: Bench, count: Int) raises:
_ = list^
@parameter
- fn bench_insertion_sort(inout b: Bencher) raises:
+ fn bench_insertion_sort(mut b: Bencher) raises:
seed(1)
var ptr = UnsafePointer[Scalar[type]].alloc(count)
var list = List[Scalar[type]](ptr=ptr, length=count, capacity=count)
@@ -208,14 +209,14 @@ fn bench_small_list_sort[type: DType](inout m: Bench, count: Int) raises:
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark sort functions with a large list size
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
-fn bench_large_list_sort[type: DType](inout m: Bench, count: Int) raises:
+fn bench_large_list_sort[type: DType](mut m: Bench, count: Int) raises:
@parameter
- fn bench_sort_list(inout b: Bencher) raises:
+ fn bench_sort_list(mut b: Bencher) raises:
seed(1)
var ptr = UnsafePointer[Scalar[type]].alloc(count)
var list = List[Scalar[type]](ptr=ptr, length=count, capacity=count)
@@ -234,7 +235,7 @@ fn bench_large_list_sort[type: DType](inout m: Bench, count: Int) raises:
_ = list^
@parameter
- fn bench_heap_sort(inout b: Bencher) raises:
+ fn bench_heap_sort(mut b: Bencher) raises:
seed(1)
var ptr = UnsafePointer[Scalar[type]].alloc(count)
var list = List[Scalar[type]](ptr=ptr, length=count, capacity=count)
@@ -261,16 +262,14 @@ fn bench_large_list_sort[type: DType](inout m: Bench, count: Int) raises:
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark sort functions with low delta lists
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
-fn bench_low_cardinality_list_sort(
- inout m: Bench, count: Int, delta: Int
-) raises:
+fn bench_low_cardinality_list_sort(mut m: Bench, count: Int, delta: Int) raises:
@parameter
- fn bench_sort_list(inout b: Bencher) raises:
+ fn bench_sort_list(mut b: Bencher) raises:
seed(1)
var ptr = UnsafePointer[UInt8].alloc(count)
var list = List[UInt8](ptr=ptr, length=count, capacity=count)
@@ -289,7 +288,7 @@ fn bench_low_cardinality_list_sort(
_ = list^
@parameter
- fn bench_heap_sort(inout b: Bencher) raises:
+ fn bench_heap_sort(mut b: Bencher) raises:
seed(1)
var ptr = UnsafePointer[UInt8].alloc(count)
var list = List[UInt8](ptr=ptr, length=count, capacity=count)
@@ -315,9 +314,9 @@ fn bench_low_cardinality_list_sort(
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Main
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
def main():
diff --git a/stdlib/benchmarks/collections/bench_dict.mojo b/stdlib/benchmarks/collections/bench_dict.mojo
index d8c782846e..e93406f837 100644
--- a/stdlib/benchmarks/collections/bench_dict.mojo
+++ b/stdlib/benchmarks/collections/bench_dict.mojo
@@ -14,19 +14,19 @@
# NOTE: to test changes on the current branch using run-benchmarks.sh, remove
# the -t flag. Remember to replace it again before pushing any code.
+from collections import Dict, Optional
+from collections.dict import DictEntry
+from math import ceil
from random import *
+from sys import sizeof
from benchmark import Bench, BenchConfig, Bencher, BenchId, Unit, keep, run
-from sys import sizeof
from bit import bit_ceil
-from math import ceil
-from collections import Dict, Optional
-from collections.dict import DictEntry
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Data
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
fn make_dict[size: Int]() -> Dict[Int, Int]:
var d = Dict[Int, Int]()
for i in range(0, size):
@@ -34,11 +34,11 @@ fn make_dict[size: Int]() -> Dict[Int, Int]:
return d
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Dict init
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
-fn bench_dict_init(inout b: Bencher) raises:
+fn bench_dict_init(mut b: Bencher) raises:
@always_inline
@parameter
fn call_fn():
@@ -50,11 +50,11 @@ fn bench_dict_init(inout b: Bencher) raises:
b.iter[call_fn]()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Dict Insert
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
-fn bench_dict_insert[size: Int](inout b: Bencher) raises:
+fn bench_dict_insert[size: Int](mut b: Bencher) raises:
"""Insert 100 new items."""
var items = make_dict[size]()
@@ -68,11 +68,11 @@ fn bench_dict_insert[size: Int](inout b: Bencher) raises:
keep(bool(items))
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Dict Lookup
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
-fn bench_dict_lookup[size: Int](inout b: Bencher) raises:
+fn bench_dict_lookup[size: Int](mut b: Bencher) raises:
"""Lookup 100 items."""
var items = make_dict[size]()
var closest_divisor = ceil(100 / size)
@@ -96,9 +96,9 @@ fn bench_dict_lookup[size: Int](inout b: Bencher) raises:
keep(bool(items))
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Dict Memory Footprint
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
fn total_bytes_used(items: Dict[Int, Int]) -> Int:
@@ -121,9 +121,9 @@ fn total_bytes_used(items: Dict[Int, Int]) -> Int:
return amnt_bytes
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Main
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
def main():
seed()
var m = Bench(BenchConfig(num_repetitions=1))
diff --git a/stdlib/benchmarks/collections/bench_string.mojo b/stdlib/benchmarks/collections/bench_string.mojo
index be397e082e..3cee895b73 100644
--- a/stdlib/benchmarks/collections/bench_string.mojo
+++ b/stdlib/benchmarks/collections/bench_string.mojo
@@ -14,18 +14,20 @@
# NOTE: to test changes on the current branch using run-benchmarks.sh, remove
# the -t flag. Remember to replace it again before pushing any code.
-from benchmark import Bench, BenchConfig, Bencher, BenchId, Unit, keep, run
-from random import random_si64, seed
-from pathlib import _dir_of_current_file
-from collections import Optional, Dict
-from os import abort
+from collections import Dict, Optional
from collections.string import String
+from os import abort
+from pathlib import _dir_of_current_file
+from random import random_si64, seed
+
+from benchmark import Bench, BenchConfig, Bencher, BenchId, Unit, keep, run
+
from utils._utf8_validation import _is_valid_utf8
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Data
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
fn make_string[
length: UInt = 0
](filename: StringLiteral = "UN_charter_EN.txt") -> String:
@@ -59,11 +61,11 @@ fn make_string[
return abort[String]()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark string init
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
-fn bench_string_init(inout b: Bencher) raises:
+fn bench_string_init(mut b: Bencher) raises:
@always_inline
@parameter
fn call_fn():
@@ -74,15 +76,15 @@ fn bench_string_init(inout b: Bencher) raises:
b.iter[call_fn]()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark string count
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
fn bench_string_count[
length: UInt = 0,
filename: StringLiteral = "UN_charter_EN",
sequence: StringLiteral = "a",
-](inout b: Bencher) raises:
+](mut b: Bencher) raises:
var items = make_string[length](filename + ".txt")
@always_inline
@@ -95,15 +97,15 @@ fn bench_string_count[
keep(bool(items))
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark string split
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
fn bench_string_split[
length: UInt = 0,
filename: StringLiteral = "UN_charter_EN",
sequence: Optional[StringLiteral] = None,
-](inout b: Bencher) raises:
+](mut b: Bencher) raises:
var items = make_string[length](filename + ".txt")
@always_inline
@@ -122,13 +124,13 @@ fn bench_string_split[
keep(bool(items))
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark string splitlines
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
fn bench_string_splitlines[
length: UInt = 0, filename: StringLiteral = "UN_charter_EN"
-](inout b: Bencher) raises:
+](mut b: Bencher) raises:
var items = make_string[length](filename + ".txt")
@always_inline
@@ -141,13 +143,13 @@ fn bench_string_splitlines[
keep(bool(items))
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark string lower
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
fn bench_string_lower[
length: UInt = 0, filename: StringLiteral = "UN_charter_EN"
-](inout b: Bencher) raises:
+](mut b: Bencher) raises:
var items = make_string[length](filename + ".txt")
@always_inline
@@ -160,13 +162,13 @@ fn bench_string_lower[
keep(bool(items))
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark string upper
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
fn bench_string_upper[
length: UInt = 0, filename: StringLiteral = "UN_charter_EN"
-](inout b: Bencher) raises:
+](mut b: Bencher) raises:
var items = make_string[length](filename + ".txt")
@always_inline
@@ -179,16 +181,16 @@ fn bench_string_upper[
keep(bool(items))
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark string replace
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
fn bench_string_replace[
length: UInt = 0,
filename: StringLiteral = "UN_charter_EN",
old: StringLiteral = "a",
new: StringLiteral = "A",
-](inout b: Bencher) raises:
+](mut b: Bencher) raises:
var items = make_string[length](filename + ".txt")
@always_inline
@@ -201,13 +203,13 @@ fn bench_string_replace[
keep(bool(items))
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark string _is_valid_utf8
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
fn bench_string_is_valid_utf8[
length: UInt = 0, filename: StringLiteral = "UN_charter_EN"
-](inout b: Bencher) raises:
+](mut b: Bencher) raises:
var items = make_string[length](filename + ".html")
@always_inline
@@ -220,9 +222,9 @@ fn bench_string_is_valid_utf8[
keep(bool(items))
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Main
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
def main():
seed()
var m = Bench(BenchConfig(num_repetitions=5))
diff --git a/stdlib/benchmarks/hashlib/bench_hash.mojo b/stdlib/benchmarks/hashlib/bench_hash.mojo
index 1f4f93c0cc..6d2ba54044 100644
--- a/stdlib/benchmarks/hashlib/bench_hash.mojo
+++ b/stdlib/benchmarks/hashlib/bench_hash.mojo
@@ -14,20 +14,21 @@
# NOTE: to test changes on the current branch using run-benchmarks.sh, remove
# the -t flag. Remember to replace it again before pushing any code.
-from benchmark import Bench, BenchConfig, Bencher, BenchId
-from bit import byte_swap, rotate_bits_left
-from memory import UnsafePointer
-from hashlib.hash import hash as old_hash
from hashlib._ahash import (
+ MULTIPLE,
+ ROT,
+ U128,
+ U256,
AHasher,
_folded_multiply,
_read_small,
- U256,
- U128,
- MULTIPLE,
- ROT,
)
from hashlib._hasher import _hash_with_hasher
+from hashlib.hash import hash as old_hash
+
+from benchmark import Bench, BenchConfig, Bencher, BenchId
+from bit import byte_swap, rotate_bits_left
+from memory import UnsafePointer
# Source: https://www.101languages.net/arabic/most-common-arabic-words/
alias words_ar = """
@@ -48,7 +49,7 @@ alias words_ar = """
تحت, الأشياء, معه, يريد, أننا, أنظر, لما, اعرف, إلي, ثلاثة, انتظر, الرجال, الذين, حصلت, أني,
سعيد, لابد, عزيزتي, الشيء,
فكرة, انهم, الله, الباب, سيدى, دائما, رأيت, مشكلة, استطيع, تكن, تذهب, ليلة, شيئ, أظن, طوال,
- جميل, وهو, الشرطة, او, دولار, السيارة, وهذا, كبير, مني, بسرعة, النار, الأمور, سمعت, أشعر, يعرف,
+ جميل, وهو, الشرطة, او, دولار, السيارة, وهذا, كبير, مني, بسرعة, النار, الأمور, سمعت, أشعر, يعرف,
أعني, لدى, بهذه, أحب, سنوات, بأس, الأفضل, بالنسبة,
أنتم, عظيم, يقول, جميلة, جون, جاك, بسبب, الوحيد, أمر, بل, بالفعل, الشخص, الي, دعني, خارج, اجل, الخير, ــ,
حالك, للغاية, فحسب, كانوا, أردت, فتاة, بشأن, يعني, كبيرة, ترى, آسفة, دقيقة, أنهم, يستطيع, احد, بأنك, تعمل,
@@ -79,7 +80,7 @@ alias words_ar = """
غدا, ظننت, ولن, المرأة, لهذه, تحرك, يهم, تبقى, الطبيب, اسم, انظري, تبا, أتذكر, فترة, ساعات, تفكر, تحصل,
بأي, النقود, لعبة, زوجتي, الكلام, ستفعل, أسف, فهو, الملك, مدينة, بكم, الوحيدة, أمام, عدد, اخرج, بول, سأعود,
جئت, لأني, تحدث, السلامة, الماضية, أمك, اعتقدت, مره, مساء, بطريقة, الرب, ابدا, أهذا, وفي, وكل, أتيت, منكم,
- انتهى, بوب, بعيدا, ضع, وجود, تعود, زلت, اللعينة, نقوم, كلنا, أحصل, يريدون, تأخذ, المحتمل, الشمس, بدأ,
+ انتهى, بوب, بعيدا, ضع, وجود, تعود, زلت, اللعينة, نقوم, كلنا, أحصل, يريدون, تأخذ, المحتمل, الشمس, بدأ,
ارجوك, المسيح, جاء, كهذا, سنذهب, تعالى, إثنان, فعلا, حتي, سيحدث, الجيد, وشك, القادم,
معرفة, صورة, أعود, اسمي, طلب, آنسة, الثانية, فقدت, حفلة, تنظر, مثير, اننى, وصلت, أنتظر, السماء, يقولون, الهراء,
معهم, ابي, وعندما, مجموعة, العاهرة, ماري, حسن, الزواج, نحو, دعيني, الجديدة, مهم, أمس, اتصل, ابتعد, هراء, ستة,
@@ -90,7 +91,7 @@ alias words_ar = """
الدخول, جين, امرأة, متأكدة, هيه, تخبرني, مدى, إلهى, احب, عما, نرى, بيننا, تعيش, قتلت, الأحمق, تشارلي,
بيل,
عليكم, سؤال, طلبت, الهواء, وهذه, صوت, انتم, ميلاد, ماكس,
- تعتقدين, الحديث, الجانب, صديقك, ذا, خطر, أطلق, الشارع, عملية, ببعض, تتكلم, مختلف, تحمل, مساعدة,
+ تعتقدين, الحديث, الجانب, صديقك, ذا, خطر, أطلق, الشارع, عملية, ببعض, تتكلم, مختلف, تحمل, مساعدة,
بضعة, المناسب, المنطقة, قم, بالداخل, البداية, لأجل, زوجتك, مقابل, يحب, هاري, ممتاز, قريبا, سنكون,
فعلته, بتلك, التفكير, أسفل, للعمل, العجوز, امي, الكلب, انتظري, مازال, إننا, اشعر, الجيش, شرطة
"""
@@ -255,13 +256,13 @@ alias words_he = """
לגרום, המשחק, שרה, לעצמך, במיוחד, המשטרה, צוות, אחזור, שאמרתי, גברים, קורא, בראש, רחוק,
למקום, לשלם, להפסיק, מיוחד, הז, שמו, שמחה, כיף, אגיד, למי, ניתן, מאחורי, תמשיך, כיצד,
להוציא, מתים, כולכם, אצל, חבל, האישה, לעצמי, גברתי, תוכלי, רואים, דוד, להציל, שצריך,
- בעלי, דוקטור, חג, לעבודה, בוודאי, תעשי, הוד, מילה, ברצינות, הארץ, עשינו, לאנשים, רצה,
+ בעלי, דוקטור, חג, לעבודה, בוודאי, תעשי, הוד, מילה, ברצינות, הארץ, עשינו, לאנשים, רצה,
עזוב, יצא, נתן,
שניות, בעיר, סי, חשבת, שאלות, אלינו, ידע, תנו, לשים, שאולי, בכך, יכולת, אן, היד, שאוכל,
מין, דקה, לדאוג, שמה, תרצה, ראה, הצילו, נוסף, החרא, אופן, כשהוא, צעיר, הפה, עולה, עובדת,
שמך, לתפוס, נמצאת, כלבה, האקדח, עדיף, הטלפון, טום, פול, חכו, קר, תלך, במקרה, יעשה, שניכם,
הארי, זוז, יקירתי, בהצלחה, לשבת, אנא, דין, מכיוון, יד, הקטנה, לבן, בנו, בעצמי, יין, תוריד,
- למישהו, מייק, מול, נזוז, ככל, הלוואי, בעצמך, לרגע, קשור, בשקט, האל, ישנה, מעמד, כזאת,
+ למישהו, מייק, מול, נזוז, ככל, הלוואי, בעצמך, לרגע, קשור, בשקט, האל, ישנה, מעמד, כזאת,
רד, אחורה, איכפת, איתם, ממנה, חם, מבקש, שש, מידע, השנה,
אכן, אהבתי, בשעה, בסוף, שקרה, לכו, אליה, לבחור, תחשוב, ספק, המים, הפנים, לכולם, תדאגי,
קחי, שתוק, לברוח, מתוק, ארלי, התיק, שים, מישהי, לקרות, לטפל, לחפש, הידיים, ח, במצב, ואל
@@ -269,313 +270,313 @@ alias words_he = """
# Source: https://www.101languages.net/latvian/most-common-latvian-words/
alias words_lv = """
- ir, es, un, tu, tas, ka, man, to, vai, ko, ar, kas, par, tā, kā, viņš, uz, no, tev,
- mēs, nav, jūs, bet, labi, jā, lai, nē, mani, ja, bija, viņa, esmu, viņu, tevi, esi,
- mums, tad, tikai, ne, viņi, kad, jums, arī, viss, nu, kur, pie, jau, tik, tur, te, vēl,
- būs, visu, šeit, tagad, kaut, ļoti, pēc, viņam, taču, savu, gan, paldies, būtu, mūsu,
- šo, lūdzu, mans, kāpēc, kungs, kāds, varbūt, tās, jūsu, cik, ak, daudz, jo, esam,
- zinu, mana, zini, visi, būt, tam, šī, var, līdz, viens, pa, pat, esat, nekad, domāju,
- nezinu, vairs, tiešām, tie, vien, kurš, varētu, dievs, neesmu, prom, tieši, kādu, aiziet,
- šis, manu, protams, vajag, neko, vienkārši, tāpēc, gribu, varu, nāc, atpakaļ, mūs,
- kārtībā, iet, kopā, viņiem, pats, pirms, domā, vienmēr, gribi, nekas, bez, tava,
- vienu, ej, viņai, vairāk, notiek, nevaru, pret, tavs, teica, tavu, biju, dēļ, viņas,
- laiku, neviens, kādēļ, vari, labāk, patīk, dari, mājās, nebija, cilvēki, ārā, viņus,
- ejam, kāda, piedod, laikam, atkal, šķiet, trīs, sevi, ser, laiks, laika, nekā, manis,
- iekšā, labs, tāds, darīt, harij, nevar, viena, lieliski, kuru, šīs, sauc, šurp, teicu,
- laikā, tos, pagaidi, neesi, tevis, draugs, pārāk, tēvs, šodien, teikt, dienu, visiem,
- tātad, notika, hei, zināt, bijis, sveiks, atvainojiet, tika, naudu, varam, savas, citu,
- tādu, manas, redzi, šajā, kam, tajā, jābūt, vecīt, tiem, runā, cilvēku, taisnība, saka,
- visus, mīlu, lietas, grib, tēt, izskatās, tiek, noteikti, nozīmē, kamēr, divi, it, tāpat,
- tāda, ilgi, katru, dēls, noticis, jauki, redzēt, pareizi, lūk, kundze, aiz, iespējams,
- pateikt, nebūtu, gandrīz, vīrs, cilvēks, ātri, žēl, pasaules, rokas, liekas, palīdzēt,
- līdzi, visas, saki, negribu, vietā, gadus, starp, skaties, tomēr, tūlīt, džek, nevajag,
- sev, vajadzētu, būšu, dzīvi, droši, gadu, priekšu, skaidrs, gribēju, nāk, paskaties, mazliet,
- tikko, nebūs, augšā, ceru, joprojām, nevis, ātrāk, ļauj, gribētu, liels, zina, vārdu, reizi,
- pasaulē, savā, sveiki, dienas, miris, dod, priekšā, galā, klau, cilvēkiem, tavas, patiesībā,
- visa, vārds, gatavs, durvis, velns, nedaudz, naudas, redzēju, velna, manā, drīz, pāri, dzīve,
- vēlies, nemaz, priekš, bērni, vieta, pāris, darbu, vajadzīgs, tālāk, rīt, roku, klāt, grūti,
- beidz, laba, klausies, dara, varat, sveika, biji, vismaz, kopš, redzu, saproti, kura, draugi,
- zemes, šovakar, patiešām, kaa, vietu, dieva, vajadzēja, mašīnu, lejā, saku, ceļu, gada, tādēļ,
- cauri, runāt, ņem, oh, divas, lieta, tikt, šie, teici, vēlāk, vaļā, nogalināt, redzējis, jāiet,
- nespēju, savus, atceries, ūdens, šejienes, labu, diena, mīļā, atvaino, doties, atrast, saprotu,
- abi, reiz, jādara, nesaprotu, meitene, darbs, nevari, tai, nedomāju, pilnīgi, nakti, nekādu,
- pati, gadiem, vēlos, taa, kādas, cits, ejiet, pirmais, a, būsi, mamma, lietu, slikti, pašu,
- acis, diezgan, pasaki, gadā, puiši, asv, sava, nost, cilvēkus, džeks, manuprāt, mājas, o,
- bērns, leo, otru, nopietni, vecais, laukā, caur, dzīves, izdarīt, sieviete, vienalga,
- nogalināja, dzīvo, kādreiz, čau, sirds, paliec, gribat, vēlreiz, kuras, mazais, vietas,
- piedodiet, laipni, palikt, brauc, ei, the, paliek, apkārt, sievietes, tālu, garām, pirmo,
- dzīvot, nāciet, runāju, kuri, tiks, jüs, ceļā, nauda, nevienam, māja, vienīgais, īsti,
- sapratu, gluži, svarīgi, atvainojos, i, sen, iespēja, tavā, pavisam, nāves, māte, citi,
- viegli, zem, notiks, darba, nepatīk, daži, galvu, dienā, hallo, bērnu, neesam, kungi, beidzot,
- nedrīkst, vajadzēs, māju, sieva, kādam, puika, kļūst, prieks, esot, iesim, daļa, pasaule,
- pietiek, visā, saviem, rīta, pagaidiet, tētis, mājā, mieru, vīru, palīdzību, dzirdēju,
- tādas, dzīvs, strādā, tām, vēlas, nakts, īpaši, jūtos, nolādēts, meitenes, pusi, mammu, mees,
- aizveries, vispār, dzīvību, kurā, kādā, vārdā, mašīna, būsim, vispirms, vinji, nevienu, šos,
- tiksimies, džeik, vinjsh, vaina, turpini, kādi, jaunu, tuvu, atradu, vēlu, varēja, citādi, šim,
- satikt, neuztraucies, pārliecināts, liec, diez, liela, doktor, nevaram, palīdzi, uzmanīgi, dažas,
- šiem, atgriezies, gribēja, priecājos, parasti, valsts, asinis, tēti, you, mierā, piemēram,
- jautājums, atā, bijām, zemē, pasauli, spēlē, blakus, izskaties, pirmā, nomira, paši, šobrīd,
- daru, gaida, tādi, iešu, labākais, jauks, maz, pieder, jauns, nezināju, uzmanību, skaista,
- prātā, brālis, patiesību, mierīgi, šai, dr, patiesi, jēzus, mārtij, zināju, suns, juus, sievu,
- dzirdi, tepat, mamm, tēvu, tēva, frodo, sasodīts, desmit, stundas, tavi, mazā, džon, cita,
- vajadzīga, forši, minūtes, mīlestība, nebiju, saprast, izbeidz, šoreiz, labā, dāmas, kurienes,
- problēma, šādi, spēj, gadījumā, tiesa, kuģi, pēdējā, tici, esiet, atceros, katrs, nee, palīgā,
- mister, liek, likās, domāt, vīri, pēdējo, traks, reizes, vienīgā, tiesības, skolā, turies, beigas,
- karš, pīter, uguni, pietiks, vienam, vienā, pakaļ, jauna, zemi, puisis, ziniet, negribi, labrīt,
- ap, cilvēka, draugu, atver, nezini, sāra, vēlaties, gadi, dažreiz, rokās, dabūt, nomierinies,
- istabā, agrāk, ieroci, savām, meiteni, paņem, meklē, pār, seju, ziņu, dzirdējis, zinām, gatavi,
- braukt, sāka, sāk, dievam, neesat, dzirdēt, spēle, bērniem, izdarīja, muļķības, doma, pēdējais,
- dīvaini, atdod, ziņas, bankas, darāt, vakar, ceļš, neviena, brāli, otrā, atgriezties, galvas,
- pietiekami, gulēt, uzreiz, iespēju, bijusi, karalis, bobij, šrek, tikpat, palīdziet, durvīm,
- vecāki, atrodas, smieklīgi, kuģa, bail, godīgi, pēkšņi, nedēļas, māsa, skrien, ceļa, džeims, gars,
- lielu, mašīnā, bojā, kurieni, ļaudis, dārgais, vecs, ūdeni, kūper, eju, mašīnas, ideja, kājas,
- spēles, galvenais, citiem, jātiek, skaisti, nāvi, vinju, problēmas, vērts, drīkstu, domājat, visur,
- bieži, manai, citas, apsolu, zelta, strādāju, dzimšanas, jūtu, naktī, dārgā, atbildi, noticēt,
- klājas, izdevās, dok, redzat, gana, divus, ģimene, runa, stāsts, braucam, brīnišķīgi, ģimenes,
- kuģis, čārlij, hey, kä, sheit, ved, atrada, mirusi, meita, paklau, nevēlos, bērnus, boss, kaptein,
- nekāda, roze, nespēj, vīrietis, brīdi, īsts, dzīvē, tādā, manī, jūras, jaunkundz, iemesls, sakot,
- manam, daudzi, varēsi, pateicos, jaunais, policija, pilnībā, nekur, jauka, nedari, kurus, zināms,
- jautājumu, seko, re, padomā, pusē, visām, mīļais, dolāru, gadžet, katram, izdarīji, šīm, vienīgi,
- mirt, apmēram, spēku, jauno, mr, celies, iepriekš, prātu, vēlētos, četri, lietām, redzēji, nevajadzētu,
- donna, jaa, ticu, minūtēm, sievieti, nāve, jūties, nezina, parādi, malā, redz, uh, gredzenu, uzmanies,
- kara, drošībā, sapnis, bijāt, grāmatu, slepkava, vinja, paga, pieci, pilsētā, drošs, pateikšu, gāja,
- spēli, beigās, hanna, princese, jebkad, dakter, veids, palīdzība, stāstu, izmantot, spēlēt, gaisā,
- darīšu, došos, dodas, kreisi, negribēju, mazāk, pastāsti, tak, devās, sirdi, misis, vis, patiesība,
- veidā, harijs, cenšos, tuvāk, kurp, klausieties, sāp, ļaujiet, neticami, kungu, sīkais, iedomāties,
- daļu, mazs, iedod, mazo, meklēju, parunāt, jādodas, sevis, pārējie, veicas, otra, mīlestību, zēns,
- dodies, galam, sem, bīstami, zvēru, iespējas, maza, ellē, virs, nekādas, maniem, skatieties, šonakt,
- svēto, kapteinis, iepazīties, pazīstu, turp, gredzens, nepareizi, lieliska, īstais, pagaidām, kājām,
- mirklīti, pašlaik, d, poter, saprati, aprunāties, paša, šejieni, interesanti, nevarētu, pašā, paskat,
- bailes, skolas, vārdus, aizmirsti, gaismas, kāp, zēni, darīsim, pašam, beidzies, sauca, māti, akmens,
+ ir, es, un, tu, tas, ka, man, to, vai, ko, ar, kas, par, tā, kā, viņš, uz, no, tev,
+ mēs, nav, jūs, bet, labi, jā, lai, nē, mani, ja, bija, viņa, esmu, viņu, tevi, esi,
+ mums, tad, tikai, ne, viņi, kad, jums, arī, viss, nu, kur, pie, jau, tik, tur, te, vēl,
+ būs, visu, šeit, tagad, kaut, ļoti, pēc, viņam, taču, savu, gan, paldies, būtu, mūsu,
+ šo, lūdzu, mans, kāpēc, kungs, kāds, varbūt, tās, jūsu, cik, ak, daudz, jo, esam,
+ zinu, mana, zini, visi, būt, tam, šī, var, līdz, viens, pa, pat, esat, nekad, domāju,
+ nezinu, vairs, tiešām, tie, vien, kurš, varētu, dievs, neesmu, prom, tieši, kādu, aiziet,
+ šis, manu, protams, vajag, neko, vienkārši, tāpēc, gribu, varu, nāc, atpakaļ, mūs,
+ kārtībā, iet, kopā, viņiem, pats, pirms, domā, vienmēr, gribi, nekas, bez, tava,
+ vienu, ej, viņai, vairāk, notiek, nevaru, pret, tavs, teica, tavu, biju, dēļ, viņas,
+ laiku, neviens, kādēļ, vari, labāk, patīk, dari, mājās, nebija, cilvēki, ārā, viņus,
+ ejam, kāda, piedod, laikam, atkal, šķiet, trīs, sevi, ser, laiks, laika, nekā, manis,
+ iekšā, labs, tāds, darīt, harij, nevar, viena, lieliski, kuru, šīs, sauc, šurp, teicu,
+ laikā, tos, pagaidi, neesi, tevis, draugs, pārāk, tēvs, šodien, teikt, dienu, visiem,
+ tātad, notika, hei, zināt, bijis, sveiks, atvainojiet, tika, naudu, varam, savas, citu,
+ tādu, manas, redzi, šajā, kam, tajā, jābūt, vecīt, tiem, runā, cilvēku, taisnība, saka,
+ visus, mīlu, lietas, grib, tēt, izskatās, tiek, noteikti, nozīmē, kamēr, divi, it, tāpat,
+ tāda, ilgi, katru, dēls, noticis, jauki, redzēt, pareizi, lūk, kundze, aiz, iespējams,
+ pateikt, nebūtu, gandrīz, vīrs, cilvēks, ātri, žēl, pasaules, rokas, liekas, palīdzēt,
+ līdzi, visas, saki, negribu, vietā, gadus, starp, skaties, tomēr, tūlīt, džek, nevajag,
+ sev, vajadzētu, būšu, dzīvi, droši, gadu, priekšu, skaidrs, gribēju, nāk, paskaties, mazliet,
+ tikko, nebūs, augšā, ceru, joprojām, nevis, ātrāk, ļauj, gribētu, liels, zina, vārdu, reizi,
+ pasaulē, savā, sveiki, dienas, miris, dod, priekšā, galā, klau, cilvēkiem, tavas, patiesībā,
+ visa, vārds, gatavs, durvis, velns, nedaudz, naudas, redzēju, velna, manā, drīz, pāri, dzīve,
+ vēlies, nemaz, priekš, bērni, vieta, pāris, darbu, vajadzīgs, tālāk, rīt, roku, klāt, grūti,
+ beidz, laba, klausies, dara, varat, sveika, biji, vismaz, kopš, redzu, saproti, kura, draugi,
+ zemes, šovakar, patiešām, kaa, vietu, dieva, vajadzēja, mašīnu, lejā, saku, ceļu, gada, tādēļ,
+ cauri, runāt, ņem, oh, divas, lieta, tikt, šie, teici, vēlāk, vaļā, nogalināt, redzējis, jāiet,
+ nespēju, savus, atceries, ūdens, šejienes, labu, diena, mīļā, atvaino, doties, atrast, saprotu,
+ abi, reiz, jādara, nesaprotu, meitene, darbs, nevari, tai, nedomāju, pilnīgi, nakti, nekādu,
+ pati, gadiem, vēlos, taa, kādas, cits, ejiet, pirmais, a, būsi, mamma, lietu, slikti, pašu,
+ acis, diezgan, pasaki, gadā, puiši, asv, sava, nost, cilvēkus, džeks, manuprāt, mājas, o,
+ bērns, leo, otru, nopietni, vecais, laukā, caur, dzīves, izdarīt, sieviete, vienalga,
+ nogalināja, dzīvo, kādreiz, čau, sirds, paliec, gribat, vēlreiz, kuras, mazais, vietas,
+ piedodiet, laipni, palikt, brauc, ei, the, paliek, apkārt, sievietes, tālu, garām, pirmo,
+ dzīvot, nāciet, runāju, kuri, tiks, jüs, ceļā, nauda, nevienam, māja, vienīgais, īsti,
+ sapratu, gluži, svarīgi, atvainojos, i, sen, iespēja, tavā, pavisam, nāves, māte, citi,
+ viegli, zem, notiks, darba, nepatīk, daži, galvu, dienā, hallo, bērnu, neesam, kungi, beidzot,
+ nedrīkst, vajadzēs, māju, sieva, kādam, puika, kļūst, prieks, esot, iesim, daļa, pasaule,
+ pietiek, visā, saviem, rīta, pagaidiet, tētis, mājā, mieru, vīru, palīdzību, dzirdēju,
+ tādas, dzīvs, strādā, tām, vēlas, nakts, īpaši, jūtos, nolādēts, meitenes, pusi, mammu, mees,
+ aizveries, vispār, dzīvību, kurā, kādā, vārdā, mašīna, būsim, vispirms, vinji, nevienu, šos,
+ tiksimies, džeik, vinjsh, vaina, turpini, kādi, jaunu, tuvu, atradu, vēlu, varēja, citādi, šim,
+ satikt, neuztraucies, pārliecināts, liec, diez, liela, doktor, nevaram, palīdzi, uzmanīgi, dažas,
+ šiem, atgriezies, gribēja, priecājos, parasti, valsts, asinis, tēti, you, mierā, piemēram,
+ jautājums, atā, bijām, zemē, pasauli, spēlē, blakus, izskaties, pirmā, nomira, paši, šobrīd,
+ daru, gaida, tādi, iešu, labākais, jauks, maz, pieder, jauns, nezināju, uzmanību, skaista,
+ prātā, brālis, patiesību, mierīgi, šai, dr, patiesi, jēzus, mārtij, zināju, suns, juus, sievu,
+ dzirdi, tepat, mamm, tēvu, tēva, frodo, sasodīts, desmit, stundas, tavi, mazā, džon, cita,
+ vajadzīga, forši, minūtes, mīlestība, nebiju, saprast, izbeidz, šoreiz, labā, dāmas, kurienes,
+ problēma, šādi, spēj, gadījumā, tiesa, kuģi, pēdējā, tici, esiet, atceros, katrs, nee, palīgā,
+ mister, liek, likās, domāt, vīri, pēdējo, traks, reizes, vienīgā, tiesības, skolā, turies, beigas,
+ karš, pīter, uguni, pietiks, vienam, vienā, pakaļ, jauna, zemi, puisis, ziniet, negribi, labrīt,
+ ap, cilvēka, draugu, atver, nezini, sāra, vēlaties, gadi, dažreiz, rokās, dabūt, nomierinies,
+ istabā, agrāk, ieroci, savām, meiteni, paņem, meklē, pār, seju, ziņu, dzirdējis, zinām, gatavi,
+ braukt, sāka, sāk, dievam, neesat, dzirdēt, spēle, bērniem, izdarīja, muļķības, doma, pēdējais,
+ dīvaini, atdod, ziņas, bankas, darāt, vakar, ceļš, neviena, brāli, otrā, atgriezties, galvas,
+ pietiekami, gulēt, uzreiz, iespēju, bijusi, karalis, bobij, šrek, tikpat, palīdziet, durvīm,
+ vecāki, atrodas, smieklīgi, kuģa, bail, godīgi, pēkšņi, nedēļas, māsa, skrien, ceļa, džeims, gars,
+ lielu, mašīnā, bojā, kurieni, ļaudis, dārgais, vecs, ūdeni, kūper, eju, mašīnas, ideja, kājas,
+ spēles, galvenais, citiem, jātiek, skaisti, nāvi, vinju, problēmas, vērts, drīkstu, domājat, visur,
+ bieži, manai, citas, apsolu, zelta, strādāju, dzimšanas, jūtu, naktī, dārgā, atbildi, noticēt,
+ klājas, izdevās, dok, redzat, gana, divus, ģimene, runa, stāsts, braucam, brīnišķīgi, ģimenes,
+ kuģis, čārlij, hey, kä, sheit, ved, atrada, mirusi, meita, paklau, nevēlos, bērnus, boss, kaptein,
+ nekāda, roze, nespēj, vīrietis, brīdi, īsts, dzīvē, tādā, manī, jūras, jaunkundz, iemesls, sakot,
+ manam, daudzi, varēsi, pateicos, jaunais, policija, pilnībā, nekur, jauka, nedari, kurus, zināms,
+ jautājumu, seko, re, padomā, pusē, visām, mīļais, dolāru, gadžet, katram, izdarīji, šīm, vienīgi,
+ mirt, apmēram, spēku, jauno, mr, celies, iepriekš, prātu, vēlētos, četri, lietām, redzēji, nevajadzētu,
+ donna, jaa, ticu, minūtēm, sievieti, nāve, jūties, nezina, parādi, malā, redz, uh, gredzenu, uzmanies,
+ kara, drošībā, sapnis, bijāt, grāmatu, slepkava, vinja, paga, pieci, pilsētā, drošs, pateikšu, gāja,
+ spēli, beigās, hanna, princese, jebkad, dakter, veids, palīdzība, stāstu, izmantot, spēlēt, gaisā,
+ darīšu, došos, dodas, kreisi, negribēju, mazāk, pastāsti, tak, devās, sirdi, misis, vis, patiesība,
+ veidā, harijs, cenšos, tuvāk, kurp, klausieties, sāp, ļaujiet, neticami, kungu, sīkais, iedomāties,
+ daļu, mazs, iedod, mazo, meklēju, parunāt, jādodas, sevis, pārējie, veicas, otra, mīlestību, zēns,
+ dodies, galam, sem, bīstami, zvēru, iespējas, maza, ellē, virs, nekādas, maniem, skatieties, šonakt,
+ svēto, kapteinis, iepazīties, pazīstu, turp, gredzens, nepareizi, lieliska, īstais, pagaidām, kājām,
+ mirklīti, pašlaik, d, poter, saprati, aprunāties, paša, šejieni, interesanti, nevarētu, pašā, paskat,
+ bailes, skolas, vārdus, aizmirsti, gaismas, kāp, zēni, darīsim, pašam, beidzies, sauca, māti, akmens,
grāmatas, diemžēl, tevī, kļūt, endij, patika, nabaga, tuvojas, tēvoci, dienām, plāns
"""
# Source: https://www.101languages.net/polish/most-common-polish-words/
alias words_pl = """
-nie, to, się, w, na, i, z, co, jest, że, do, tak, jak, o, mnie, a, ale, mi, za, ja, ci, tu, ty, czy,
-tym, go, tego, tylko, jestem, po, cię, ma, już, mam, jesteś, może, pan, dla, coś, dobrze, wiem, jeśli,
-teraz, proszę, od, wszystko, tam, więc, masz, nic, on, być, gdzie, będzie, są, ten, mogę, ciebie,
-bardzo, sobie, kiedy, ze, wiesz, no, jej, jeszcze, pani, był, mój, chcę, było, dlaczego, by, przez,
-nas, tutaj, chcesz, jego, ją, ich, nigdy, żeby, też, kto, naprawdę, przepraszam, bo, mamy, porządku,
-możesz, dobra, mu, dziękuję, ona, domu, panie, muszę, nawet, chyba, hej, właśnie, prawda, zrobić, te,
-zawsze, będę, moja, gdy, je, trochę, nam, moje, cześć, bez, nim, była, tej, jesteśmy, dalej, pana,
-dzięki, wszyscy, musisz, twój, lat, tobą, więcej, ktoś, czas, ta, który, chce, powiedzieć, chodź, dobry,
-mną, niech, sam, razem, chodzi, czego, boże, stało, musimy, raz, albo, prostu, będziesz, dzień, możemy,
-was, myślę, czym, daj, lepiej, czemu, ludzie, ok, przed, życie, ludzi, robisz, my, niż, tych, kim, rzeczy,
-myślisz, powiedz, przy, twoja, oni, oczywiście, nikt, siebie, stąd, niego, twoje, miał, jeden, mówi,
-powiedział, moim, czasu, u, dziś, im, które, musi, wtedy, taki, aby, pod, dwa, temu, pewnie, takie, cóż,
-wszystkie, mojego, dużo, cholera, kurwa, wie, znaczy, wygląda, dzieje, mieć, ile, iść, potem, będziemy,
-dzieci, dlatego, cały, byłem, moją, skąd, szybko, jako, kochanie, stary, trzeba, miejsce, myśli, można,
-sie, jasne, mojej, wam, swoje, zaraz, wiele, nią, rozumiem, nich, wszystkich, jakieś, jakiś, kocham, idź,
-tę, mają, mówię, mówisz, dzisiaj, nad, pomóc, takiego, przestań, tobie, jutro, robić, jaki, mamo, kilka,
-przykro, wiedzieć, ojciec, widzisz, zbyt, zobaczyć, która, ani, tyle, trzy, tą, sposób, miałem, tato, niej,
-później, pieniądze, robi, kogoś, kiedyś, zanim, widzę, pracy, świetnie, pewno, myślałem, będą, bardziej,
-życia, długo, och, sir, ponieważ, aż, dni, nocy, każdy, dnia, znowu, oh, chciałem, taka, swoją, twoim,
-widziałem, stanie, powiem, imię, wy, żebyś, nadzieję, twojej, panu, spokój, słuchaj, rację, spójrz, razie,
-znam, pierwszy, koniec, chciałbym, we, nami, jakie, posłuchaj, problem, przecież, dobre, nasz, dziecko, drzwi,
-nasze, miło, czuję, mógł, żyje, jeżeli, człowiek, powiedziałem, gdyby, roku, dom, sama, potrzebuję,
-wszystkim, zostać, wciąż, dokładnie, mama, którzy, mówić, zamknij, mów, twoją, chwilę, zrobił, samo, idziemy,
-nadal, jesteście, zabić, były, sobą, kogo, lub, lubię, the, podoba, minut, bym, chciał, bądź, czegoś, gdzieś,
-mówiłem, chodźmy, znaleźć, poza, spokojnie, wcześniej, został, rozumiesz, mogą, prawie, wydaje, miała, mały,
-byłeś, facet, zrobię, macie, żadnych, razy, noc, ciągle, broń, moich, twojego, końcu, pomocy, czekaj, znasz,
-oczy, weź, idę, halo, dość, innego, pomysł, jakby, trzymaj, jedno, ojca, porozmawiać, pamiętasz, lata,
-powinieneś, którą, powodu, takim, niczego, powinniśmy, oto, napisy, jednak, świat, pokoju, żebym, sprawy,
-dwie, samochód, swój, wystarczy, pewien, źle, pozwól, numer, jedną, miejscu, you, drogi, byłam, dokąd, miłość,
-panowie, pieniędzy, którego, matka, rano, dwóch, całe, patrz, rzecz, nowy, idzie, wyglądasz, bóg, byś, życiu,
-nimi, nikogo, całą, swojego, świecie, sprawa, dziewczyna, prawo, byli, zostaw, wiedziałem, jedna, widzieć,
-swoim, kobiety, uważaj, najpierw, właściwie, dam, również, diabła, chcą, którym, zrób, da, jednego, dać,
-musiał, ręce, powinienem, których, znów, powiedziała, wczoraj, czujesz, zaczekaj, sądzę, śmierć, mówił,
-podczas, której, całkiem, pracę, żona, pójdę, pamiętam, powiedziałeś, mówią, wiemy, jezu, witam, cholery,
-swoich, telefon, wielu, także, poważnie, skoro, miejsca, robię, śmierci, słyszałem, wina, zrobiłem, dobranoc,
-parę, prawdę, swojej, serce, inaczej, dziewczyny, kobieta, powiesz, martw, rób, pytanie, pięć, innych, one,
-gra, natychmiast, wrócić, szybciej, jednym, cokolwiek, wierzę, wcale, wieczór, ważne, człowieka, wielki, nowa,
-dopiero, ziemi, gdybym, tata, poznać, stać, jack, myślałam, witaj, słowa, zrobiłeś, gówno, john, dolarów,
-sprawę, inne, idziesz, miałam, wiecie, chciałam, zobaczenia, widziałeś, żyć, każdym, nasza, panią, wspaniale,
-chwili, każdego, nowego, nieźle, takich, między, dostać, powinien, dawaj, dopóki, naszych, naszej, świata,
-chłopaki, chcemy, poczekaj, jaką, człowieku, czasem, żadnego, inny, przynajmniej, nazywa, super, naszego,
-szczęście, potrzebuje, godziny, zabrać, powrotem, syn, lecz, słucham, twoich, udało, boga, pokój, działa,
-ogóle, naszym, szkoły, możliwe, wiedział, wyjść, wszystkiego, byłoby, daleko, wieczorem, skarbie, jaka,
-mógłbym, ostatni, możecie, cztery, doktorze, zrobimy, mąż, przeciwko, zgadza, zrobisz, czasie, czasami,
-brzmi, raczej, ciało, należy, miasta, miałeś, taką, brat, cieszę, rozmawiać, cała, czymś, wybacz, twarz,
-mała, chcecie, dr, pojęcia, lubisz, głowę, najbardziej, dziwne, głowy, wody, pół, wiadomość, policja,
-strony, l, pl, mogłem, mieli, widzenia, pewna, ruszaj, wracaj, ode, popatrz, końca, plan, kiedykolwiek,
-wejść, została, rok, syna, uda, wrócę, zewnątrz, droga, uwierzyć, późno, zostało, zostanie, zły, kapitanie,
-potrzebujemy, byliśmy, zobaczymy, gotowy, obchodzi, jechać, rodziny, widziałam, drodze, czeka, środku, film,
-spać, człowiekiem, zupełnie, taa, pomóż, mieliśmy, pomoc, słowo, innym, ostatnio, and, zna, mogła, pójść,
-chłopcy, wziąć, mógłbyś, tłumaczenie, potrzebujesz, słyszysz, blisko, godzin, miłości, góry, zabił, piękna,
-napisów, pokaż, moi, lubi, robota, prawa, ciężko, kimś, dół, rękę, nazywam, wielkie, część, wkrótce, naszą,
-jedziemy, zapomnij, prosto, radę, robimy, powinnaś, gdybyś, chociaż, zależy, stronie, wypadek, tydzień, byłaś,
-nowe, małe, praca, drogę, chłopak, zrobi, widział, mieście, synu, oznacza, krew, mógłby, krwi, górę, joe, wasza,
-robią, tędy, wszędzie, temat, pierwsze, zobacz, ponad, kraju, mało, racja, tymi, cicho, chciała, powiedziałam,
-leci, powinno, mówiąc, serca, chciałabym, miasto, george, spotkać, mniej, e, przyjaciel, mówiłeś, kłopoty,
-miesięcy, jakąś, żaden, zostań, roboty, zatrzymać, frank, nieważne, głupi, pa, koleś, sprawie, spotkanie, ojcze,
-pewnego, spróbuj, drugi, znalazłem, pracować, całym, zostały, złe, niemożliwe, jakoś, zdjęcia, stronę, wiedzą, it,
-dziewczynę, zaczyna, mogli, samego, sądzisz, rodzina, razu, trudno, samochodu, okay, boję, szkoda, wami, charlie,
-dał, środka, ojcem, piękne, dawno, choć, panem, przykład, nagle, bracie, żadnej, drugiej, przyjaciół, otwórz,
-myśleć, doktor, chwileczkę, pracuje, najlepszy, brata, czyż, często, http, powinnam, odejść, trzech, chodźcie,
-nazwisko, szansę, ciała, policji, szkole, prawdopodobnie, serio, matki, org, wolno, sami, muszą, zabierz,
-słyszałeś, siostra, uspokój, wystarczająco, początku, faceta, problemy, szefie, broni, me, zostawić, czuje,
-będziecie, przyszedł, wiedziałam, kilku, inni, b, głowie, historia, według, www, wezmę, nowym, czekać, stój,
-mężczyzna, mówiłam, pokazać, około, wracam, wieku, jakaś, pierwsza, niczym, zabiję, zdjęcie, zabawne, rodzice,
-musiałem, całkowicie, sprawdzić, mike, przyjdzie, sześć, kupić, dobrym, żonę, dasz, pomoże, nogi, obok, ruszać,
-trzymać, zadzwonić, panno, godzinę, boli, oraz, spokoju, walczyć, wróci, tom, wspólnego, zmienić, ostatnie, uwagę,
-znać, jednej, dłużej, powie, pogadać, łatwo, większość, nikomu, michael, córka, niedługo, powodzenia, tygodniu,
-włosy, niestety, górze, kochasz, prawdziwy, historii, ulicy, musicie, gotowi, chwila, samym, grać, zadzwonię,
-strasznie, mieszka, kocha, rady, tyłu, jakim, obiecuję, tysięcy, pomyślałem, pracuję, jedynie, pozwolić, uwaga,
+nie, to, się, w, na, i, z, co, jest, że, do, tak, jak, o, mnie, a, ale, mi, za, ja, ci, tu, ty, czy,
+tym, go, tego, tylko, jestem, po, cię, ma, już, mam, jesteś, może, pan, dla, coś, dobrze, wiem, jeśli,
+teraz, proszę, od, wszystko, tam, więc, masz, nic, on, być, gdzie, będzie, są, ten, mogę, ciebie,
+bardzo, sobie, kiedy, ze, wiesz, no, jej, jeszcze, pani, był, mój, chcę, było, dlaczego, by, przez,
+nas, tutaj, chcesz, jego, ją, ich, nigdy, żeby, też, kto, naprawdę, przepraszam, bo, mamy, porządku,
+możesz, dobra, mu, dziękuję, ona, domu, panie, muszę, nawet, chyba, hej, właśnie, prawda, zrobić, te,
+zawsze, będę, moja, gdy, je, trochę, nam, moje, cześć, bez, nim, była, tej, jesteśmy, dalej, pana,
+dzięki, wszyscy, musisz, twój, lat, tobą, więcej, ktoś, czas, ta, który, chce, powiedzieć, chodź, dobry,
+mną, niech, sam, razem, chodzi, czego, boże, stało, musimy, raz, albo, prostu, będziesz, dzień, możemy,
+was, myślę, czym, daj, lepiej, czemu, ludzie, ok, przed, życie, ludzi, robisz, my, niż, tych, kim, rzeczy,
+myślisz, powiedz, przy, twoja, oni, oczywiście, nikt, siebie, stąd, niego, twoje, miał, jeden, mówi,
+powiedział, moim, czasu, u, dziś, im, które, musi, wtedy, taki, aby, pod, dwa, temu, pewnie, takie, cóż,
+wszystkie, mojego, dużo, cholera, kurwa, wie, znaczy, wygląda, dzieje, mieć, ile, iść, potem, będziemy,
+dzieci, dlatego, cały, byłem, moją, skąd, szybko, jako, kochanie, stary, trzeba, miejsce, myśli, można,
+sie, jasne, mojej, wam, swoje, zaraz, wiele, nią, rozumiem, nich, wszystkich, jakieś, jakiś, kocham, idź,
+tę, mają, mówię, mówisz, dzisiaj, nad, pomóc, takiego, przestań, tobie, jutro, robić, jaki, mamo, kilka,
+przykro, wiedzieć, ojciec, widzisz, zbyt, zobaczyć, która, ani, tyle, trzy, tą, sposób, miałem, tato, niej,
+później, pieniądze, robi, kogoś, kiedyś, zanim, widzę, pracy, świetnie, pewno, myślałem, będą, bardziej,
+życia, długo, och, sir, ponieważ, aż, dni, nocy, każdy, dnia, znowu, oh, chciałem, taka, swoją, twoim,
+widziałem, stanie, powiem, imię, wy, żebyś, nadzieję, twojej, panu, spokój, słuchaj, rację, spójrz, razie,
+znam, pierwszy, koniec, chciałbym, we, nami, jakie, posłuchaj, problem, przecież, dobre, nasz, dziecko, drzwi,
+nasze, miło, czuję, mógł, żyje, jeżeli, człowiek, powiedziałem, gdyby, roku, dom, sama, potrzebuję,
+wszystkim, zostać, wciąż, dokładnie, mama, którzy, mówić, zamknij, mów, twoją, chwilę, zrobił, samo, idziemy,
+nadal, jesteście, zabić, były, sobą, kogo, lub, lubię, the, podoba, minut, bym, chciał, bądź, czegoś, gdzieś,
+mówiłem, chodźmy, znaleźć, poza, spokojnie, wcześniej, został, rozumiesz, mogą, prawie, wydaje, miała, mały,
+byłeś, facet, zrobię, macie, żadnych, razy, noc, ciągle, broń, moich, twojego, końcu, pomocy, czekaj, znasz,
+oczy, weź, idę, halo, dość, innego, pomysł, jakby, trzymaj, jedno, ojca, porozmawiać, pamiętasz, lata,
+powinieneś, którą, powodu, takim, niczego, powinniśmy, oto, napisy, jednak, świat, pokoju, żebym, sprawy,
+dwie, samochód, swój, wystarczy, pewien, źle, pozwól, numer, jedną, miejscu, you, drogi, byłam, dokąd, miłość,
+panowie, pieniędzy, którego, matka, rano, dwóch, całe, patrz, rzecz, nowy, idzie, wyglądasz, bóg, byś, życiu,
+nimi, nikogo, całą, swojego, świecie, sprawa, dziewczyna, prawo, byli, zostaw, wiedziałem, jedna, widzieć,
+swoim, kobiety, uważaj, najpierw, właściwie, dam, również, diabła, chcą, którym, zrób, da, jednego, dać,
+musiał, ręce, powinienem, których, znów, powiedziała, wczoraj, czujesz, zaczekaj, sądzę, śmierć, mówił,
+podczas, której, całkiem, pracę, żona, pójdę, pamiętam, powiedziałeś, mówią, wiemy, jezu, witam, cholery,
+swoich, telefon, wielu, także, poważnie, skoro, miejsca, robię, śmierci, słyszałem, wina, zrobiłem, dobranoc,
+parę, prawdę, swojej, serce, inaczej, dziewczyny, kobieta, powiesz, martw, rób, pytanie, pięć, innych, one,
+gra, natychmiast, wrócić, szybciej, jednym, cokolwiek, wierzę, wcale, wieczór, ważne, człowieka, wielki, nowa,
+dopiero, ziemi, gdybym, tata, poznać, stać, jack, myślałam, witaj, słowa, zrobiłeś, gówno, john, dolarów,
+sprawę, inne, idziesz, miałam, wiecie, chciałam, zobaczenia, widziałeś, żyć, każdym, nasza, panią, wspaniale,
+chwili, każdego, nowego, nieźle, takich, między, dostać, powinien, dawaj, dopóki, naszych, naszej, świata,
+chłopaki, chcemy, poczekaj, jaką, człowieku, czasem, żadnego, inny, przynajmniej, nazywa, super, naszego,
+szczęście, potrzebuje, godziny, zabrać, powrotem, syn, lecz, słucham, twoich, udało, boga, pokój, działa,
+ogóle, naszym, szkoły, możliwe, wiedział, wyjść, wszystkiego, byłoby, daleko, wieczorem, skarbie, jaka,
+mógłbym, ostatni, możecie, cztery, doktorze, zrobimy, mąż, przeciwko, zgadza, zrobisz, czasie, czasami,
+brzmi, raczej, ciało, należy, miasta, miałeś, taką, brat, cieszę, rozmawiać, cała, czymś, wybacz, twarz,
+mała, chcecie, dr, pojęcia, lubisz, głowę, najbardziej, dziwne, głowy, wody, pół, wiadomość, policja,
+strony, l, pl, mogłem, mieli, widzenia, pewna, ruszaj, wracaj, ode, popatrz, końca, plan, kiedykolwiek,
+wejść, została, rok, syna, uda, wrócę, zewnątrz, droga, uwierzyć, późno, zostało, zostanie, zły, kapitanie,
+potrzebujemy, byliśmy, zobaczymy, gotowy, obchodzi, jechać, rodziny, widziałam, drodze, czeka, środku, film,
+spać, człowiekiem, zupełnie, taa, pomóż, mieliśmy, pomoc, słowo, innym, ostatnio, and, zna, mogła, pójść,
+chłopcy, wziąć, mógłbyś, tłumaczenie, potrzebujesz, słyszysz, blisko, godzin, miłości, góry, zabił, piękna,
+napisów, pokaż, moi, lubi, robota, prawa, ciężko, kimś, dół, rękę, nazywam, wielkie, część, wkrótce, naszą,
+jedziemy, zapomnij, prosto, radę, robimy, powinnaś, gdybyś, chociaż, zależy, stronie, wypadek, tydzień, byłaś,
+nowe, małe, praca, drogę, chłopak, zrobi, widział, mieście, synu, oznacza, krew, mógłby, krwi, górę, joe, wasza,
+robią, tędy, wszędzie, temat, pierwsze, zobacz, ponad, kraju, mało, racja, tymi, cicho, chciała, powiedziałam,
+leci, powinno, mówiąc, serca, chciałabym, miasto, george, spotkać, mniej, e, przyjaciel, mówiłeś, kłopoty,
+miesięcy, jakąś, żaden, zostań, roboty, zatrzymać, frank, nieważne, głupi, pa, koleś, sprawie, spotkanie, ojcze,
+pewnego, spróbuj, drugi, znalazłem, pracować, całym, zostały, złe, niemożliwe, jakoś, zdjęcia, stronę, wiedzą, it,
+dziewczynę, zaczyna, mogli, samego, sądzisz, rodzina, razu, trudno, samochodu, okay, boję, szkoda, wami, charlie,
+dał, środka, ojcem, piękne, dawno, choć, panem, przykład, nagle, bracie, żadnej, drugiej, przyjaciół, otwórz,
+myśleć, doktor, chwileczkę, pracuje, najlepszy, brata, czyż, często, http, powinnam, odejść, trzech, chodźcie,
+nazwisko, szansę, ciała, policji, szkole, prawdopodobnie, serio, matki, org, wolno, sami, muszą, zabierz,
+słyszałeś, siostra, uspokój, wystarczająco, początku, faceta, problemy, szefie, broni, me, zostawić, czuje,
+będziecie, przyszedł, wiedziałam, kilku, inni, b, głowie, historia, według, www, wezmę, nowym, czekać, stój,
+mężczyzna, mówiłam, pokazać, około, wracam, wieku, jakaś, pierwsza, niczym, zabiję, zdjęcie, zabawne, rodzice,
+musiałem, całkowicie, sprawdzić, mike, przyjdzie, sześć, kupić, dobrym, żonę, dasz, pomoże, nogi, obok, ruszać,
+trzymać, zadzwonić, panno, godzinę, boli, oraz, spokoju, walczyć, wróci, tom, wspólnego, zmienić, ostatnie, uwagę,
+znać, jednej, dłużej, powie, pogadać, łatwo, większość, nikomu, michael, córka, niedługo, powodzenia, tygodniu,
+włosy, niestety, górze, kochasz, prawdziwy, historii, ulicy, musicie, gotowi, chwila, samym, grać, zadzwonię,
+strasznie, mieszka, kocha, rady, tyłu, jakim, obiecuję, tysięcy, pomyślałem, pracuję, jedynie, pozwolić, uwaga,
proste, zacząć, myśl, wstawaj, rany, prawdziwe, takiej, jakiegoś, umrzeć, złego, okazji
"""
# Source: https://www.101languages.net/greek/most-common-greek-words/
alias words_el = """
- να, το, δεν, θα, είναι, και, μου, με, ο, για, την, σου, τα, τον, η, τι, σε, που, του, αυτό, στο, ότι,
- από, τη, της, ναι, σας, ένα, εδώ, τους, αν, όχι, μια, μας, είσαι, αλλά, κι, οι, πρέπει, είμαι, ήταν,
- πολύ, στην, δε, γιατί, εγώ, τώρα, πως, εντάξει, τις, κάτι, ξέρω, μην, έχει, έχω, εσύ, θέλω, καλά,
- έτσι, στη, στον, αυτή, ξέρεις, κάνεις, εκεί, σαν, μόνο, μπορώ, όταν, έχεις, μαζί, πώς, τίποτα,
- ευχαριστώ, όλα, κάνω, πάμε, ή, ποτέ, τόσο, πού, αυτά, έλα, στα, μέσα, κάνει, των, μπορεί, κύριε, πιο,
- σπίτι, παρακαλώ, λοιπόν, μπορείς, αυτός, υπάρχει, ακόμα, πίσω, λίγο, πάντα, είμαστε, γεια, τότε,
- ειναι, μετά, πω, έχουμε, μη, ένας, ποιος, νομίζω, πριν, απλά, δω, δουλειά, παιδιά, οχι, αλήθεια,
- όλοι, ίσως, λες, όπως, ας, θέλεις, μα, άλλο, είπε, ζωή, πάω, δύο, ωραία, έναν, καλό, απο, κάνουμε,
- έξω, κοίτα, είχε, στις, πάνω, είπα, πες, χρόνια, ούτε, κάτω, είστε, ώρα, θες, σένα, έχουν, γυναίκα,
- μένα, μέρα, καλή, φορά, όμως, κανείς, κάθε, ε, οτι, αρέσει, ήμουν, μέχρι, δυο, είχα, μαμά, χωρίς,
- καλύτερα, πας, πράγματα, πάει, σήμερα, κάποιος, ήθελα, θέλει, θεέ, έπρεπε, λέει, μία, σωστά, αυτόν,
- μπορούμε, συμβαίνει, ακριβώς, έγινε, πόσο, επειδή, λεφτά, πολλά, μόλις, εμένα, λένε, πεις, συγγνώμη,
- γρήγορα, ω, έκανε, λυπάμαι, γίνει, παιδί, περίμενε, έκανα, φίλε, βλέπω, μέρος, στιγμή, φαίνεται,
+ να, το, δεν, θα, είναι, και, μου, με, ο, για, την, σου, τα, τον, η, τι, σε, που, του, αυτό, στο, ότι,
+ από, τη, της, ναι, σας, ένα, εδώ, τους, αν, όχι, μια, μας, είσαι, αλλά, κι, οι, πρέπει, είμαι, ήταν,
+ πολύ, στην, δε, γιατί, εγώ, τώρα, πως, εντάξει, τις, κάτι, ξέρω, μην, έχει, έχω, εσύ, θέλω, καλά,
+ έτσι, στη, στον, αυτή, ξέρεις, κάνεις, εκεί, σαν, μόνο, μπορώ, όταν, έχεις, μαζί, πώς, τίποτα,
+ ευχαριστώ, όλα, κάνω, πάμε, ή, ποτέ, τόσο, πού, αυτά, έλα, στα, μέσα, κάνει, των, μπορεί, κύριε, πιο,
+ σπίτι, παρακαλώ, λοιπόν, μπορείς, αυτός, υπάρχει, ακόμα, πίσω, λίγο, πάντα, είμαστε, γεια, τότε,
+ ειναι, μετά, πω, έχουμε, μη, ένας, ποιος, νομίζω, πριν, απλά, δω, δουλειά, παιδιά, οχι, αλήθεια,
+ όλοι, ίσως, λες, όπως, ας, θέλεις, μα, άλλο, είπε, ζωή, πάω, δύο, ωραία, έναν, καλό, απο, κάνουμε,
+ έξω, κοίτα, είχε, στις, πάνω, είπα, πες, χρόνια, ούτε, κάτω, είστε, ώρα, θες, σένα, έχουν, γυναίκα,
+ μένα, μέρα, καλή, φορά, όμως, κανείς, κάθε, ε, οτι, αρέσει, ήμουν, μέχρι, δυο, είχα, μαμά, χωρίς,
+ καλύτερα, πας, πράγματα, πάει, σήμερα, κάποιος, ήθελα, θέλει, θεέ, έπρεπε, λέει, μία, σωστά, αυτόν,
+ μπορούμε, συμβαίνει, ακριβώς, έγινε, πόσο, επειδή, λεφτά, πολλά, μόλις, εμένα, λένε, πεις, συγγνώμη,
+ γρήγορα, ω, έκανε, λυπάμαι, γίνει, παιδί, περίμενε, έκανα, φίλε, βλέπω, μέρος, στιγμή, φαίνεται,
πρόβλημα, άλλη, είπες, φυσικά, κάποιον, όσο, πήγαινε, πάλι, λάθος, ως, έχετε, εσένα, πράγμα, κυρία,
- χρόνο, στους, πάρω, μπαμπά, δικό, απ, γίνεται, εσείς, λέω, συγνώμη, όλο, μητέρα, έκανες, πιστεύω,
- ήσουν, κάποια, σίγουρα, υπάρχουν, όλη, ενα, αυτο, ξέρει, μωρό, ιδέα, δει, μάλλον, ίδιο, πάρε, είδα,
- αύριο, βλέπεις, νέα, κόσμο, νομίζεις, τί, εμείς, σταμάτα, πάρει, αγάπη, πατέρας, όλους, αρκετά,
- χρειάζεται, καιρό, φορές, κάνουν, ακόμη, α, πατέρα, προς, αμέσως, πια, ηταν, χαρά, απόψε, όνομα,
- μάλιστα, μόνος, μεγάλη, κανένα, ελα, πραγματικά, αυτοί, πει, πότε, εχω, βράδυ, αυτές, θέλετε, κάνετε,
- σημαίνει, πρώτη, ποιο, πόλη, μπορούσα, ποια, γαμώτο, ήδη, τελευταία, άνθρωποι, τέλος, απλώς, νόμιζα,
- ξέρετε, μέρες, δεις, θέση, αυτούς, καταλαβαίνω, φύγε, χέρια, εκτός, ήξερα, οπότε, λεπτά, μακριά,
- κάνε, αμάξι, δική, λεπτό, μεγάλο, μήπως, κορίτσι, μάτια, ελάτε, πρόκειται, πόρτα, δίκιο, βοήθεια,
- ήρθε, μιλήσω, δρόμο, εαυτό, καθόλου, ορίστε, βρω, πειράζει, μπορείτε, καλός, πέρα, κοντά, εννοώ,
- τέτοιο, μπροστά, έρθει, χρειάζομαι, χέρι, ελπίζω, δώσε, διάολο, φύγω, ιστορία, όπλο, αφού, πρωί,
- νύχτα, ωραίο, τύπος, ξανά, θυμάσαι, δούμε, κατά, εννοείς, αγαπώ, κακό, θέμα, εδω, αυτήν, τρόπο,
- κεφάλι, είχες, μερικές, μιλάς, φίλος, άνθρωπος, φύγουμε, όλες, σκατά, ανθρώπους, βέβαια, άντρας,
- κάποιο, πάνε, αστυνομία, αλλιώς, συνέβη, χαίρομαι, άλλα, περισσότερο, καλύτερο, εκείνη, πάρεις, τo,
- νερό, ώρες, σίγουρος, vα, τρεις, εχεις, πρώτα, μπορούσε, σ, οταν, δρ, πιστεύεις, μόνη, ποιός, καμιά,
- κανέναν, πέθανε, εχει, ετσι, αγόρι, ανησυχείς, άντρες, δωμάτιο, ομάδα, ίδια, εμπρός, βρούμε, βοηθήσω,
- τέτοια, πήρε, τρία, λόγο, μικρό, αντίο, o, πέντε, πήγε, καν, ευκαιρία, είδες, έρχεται, δηλαδή,
- αργότερα, ήθελε, πούμε, λέμε, όπου, αλλα, κόρη, κόσμος, γυναίκες, τηλέφωνο, εάν, δώσω, καρδιά, βρήκα,
- γραφείο, επίσης, νιώθω, σχέση, θέλουν, ισως, τέλεια, είχαμε, κάπου, μυαλό, ώστε, καλημέρα, σχολείο,
- θεός, μικρή, τρέχει, ψέματα, ξέρουμε, οικογένεια, εισαι, θυμάμαι, κ, ενός, φίλοι, πρόσεχε,
- καταλαβαίνεις, αργά, ντε, θέλουμε, σύντομα, πήρα, σχεδόν, παιχνίδι, κύριοι, γειά, μήνες, μπαμπάς,
- σοβαρά, δολάρια, τουλάχιστον, χρήματα, πείτε, πόδια, αίμα, κοπέλα, φαγητό, ειμαι, ποιον, μερικά,
- δύσκολο, μπορούν, βρεις, όμορφη, φύγεις, τύχη, πλάκα, έρθεις, άντρα, κορίτσια, μείνε, αστείο, καμία,
- είχαν, χάρη, άλλος, πρεπει, σημασία, φυλακή, νεκρός, συγχωρείτε, φοβάμαι, μπράβο, γύρω, κανένας, μεταξύ,
- τ, χθες, πολλές, όνομά, τζακ, ρε, καληνύχτα, πολυ, φύγει, αφήσω, ήθελες, tι, ήρθες, ακούς, πρώτο, γιατι,
- ηρέμησε, γι, πάρουμε, πάρα, άλλους, κατάλαβα, έρθω, συνέχεια, έλεγα, γλυκιά, νοιάζει, χριστέ, βιβλίο,
- κύριος, μ, χώρα, αρχή, ήρθα, πεθάνει, γη, έτοιμος, εγω, άσχημα, συμβεί, αυτοκίνητο, ζωής, τελικά, φέρω,
- τρόπος, κατάσταση, www, περιμένω, σημαντικό, όσα, σκέφτηκα, μιλήσουμε, αφήστε, τωρα, ακούω, γιος, σκοτώσω,
- δύναμη, κα, κε, εκείνο, γονείς, μιλάω, σκοτώσει, ολα, μείνει, μείνω, αρέσουν, δεv, υπόθεση, φίλους, όπλα,
- υποθέτω, εμάς, ενώ, έξι, σχέδιο, άρεσε, καφέ, σκότωσε, χρειαζόμαστε, φίλο, σωστό, προσπαθώ, κάναμε,
- κοιτάξτε, μoυ, κου, ποτό, εσάς, έι, έφυγε, ταινία, μοιάζει, κρεβάτι, εχουμε, περιμένει, νέο, μπορούσες,
- μάθω, αφήσεις, περιμένετε, χρειάζεσαι, υπήρχε, μισό, δέκα, αφεντικό, περίπου, άλλοι, λόγος, ξέρουν, κάποτε,
- βρήκες, καλύτερη, υπέροχο, τζον, δίπλα, σκάσε, θεού, άκουσα, φύγετε, λέξη, παρά, επόμενη, λέτε, περάσει,
- πόσα, γίνεις, σώμα, ν, πήρες, τελείωσε, γιο, ρούχα, σκέφτομαι, εσυ, άλλες, γυρίσω, βάλω, μουσική, ραντεβού,
- φωτιά, έδωσε, πάτε, φοβάσαι, βρει, δείξω, γίνω, βοηθήσει, τύπο, σειρά, αξίζει, μείνεις, είπαν, άλλον,
- κυρίες, λίγη, πέρασε, κάτσε, πήγα, δείτε, μιας, βδομάδα, έρχομαι, προσοχή, εύκολο, ερώτηση, υπέροχα,
- σίγουρη, νοσοκομείο, τρελός, ενας, βάλε, πόλεμο, φέρε, δικά, τιμή, κατάλαβες, ταξίδι, οποίο, δουλεύει, θεό,
- μικρέ, μάθεις, βρίσκεται, πολλοί, δες, πάρτε, παντού, πρόσωπο, μήνυμα, αδερφή, μιλάει, παλιά, πουθενά,
- κράτα, περίπτωση, φως, επάνω, έλεγε, συμφωνία, οπως, ολοι, πρώτος, δεσποινίς, γιατρός, γνωρίζω, σαμ,
- σκέφτεσαι, ει, φίλη, σεξ, έκαναν, προβλήματα, κάπως, ό, τελευταίο, ακούσει, τζο, καλώς, επιλογή,
- σταματήστε, τόσα, οτιδήποτε, περισσότερα, άδεια, πάρτι, περίμενα, ακούγεται, gmteam, ήξερες, καιρός,
- μαλλιά, καλύτερος, κανεις, φρανκ, μέση, συνέχισε, τίποτε, φωτογραφία, κατι, μεγάλος, περιοχή, άσε, καθώς,
- είδε, λόγια, μήνα, μαλακίες, όμορφο, δώρο, στόμα, χάλια, εντελώς, μακάρι, τελειώσει, γνώμη, γιατρέ, ξερω,
- πλευρά, μέλλον, θάνατο, νιώθεις, έτοιμοι, κομμάτι, μάθει, μιλάμε, ψηλά, αέρα, ερωτήσεις, αυτού, δώσει,
- φεύγω, σημείο, τηλεόραση, κυριε, πραγματικότητα, ανάγκη, βοηθήσεις, προσπάθησε, γύρνα, άφησε, λίγα, κάντε,
- είvαι, βλέπετε, αυτη, δείπνο, επιτέλους, κέντρο, περίεργο, ακούστε, πλοίο, κάποιες, δικός, σoυ, οικογένειά,
- μιλήσει, πλέον, υπόσχομαι, περιμένεις, ήξερε, σκοτώσεις, ενταξει, δώσεις, εκει, ήμασταν, έρχονται, κώλο,
- ρωτήσω, παίρνει, σιγά, σήκω, στοιχεία, αδελφή, βασικά, μένει, άκρη, πηγαίνετε, παίρνεις, tο, περιμένουμε,
- συγχωρείς, μικρός, πόδι, δίνει, εκατομμύρια, ξενοδοχείο, αποστολή, ενδιαφέρον, χάρηκα, αεροπλάνο, γάμο,
- χιλιάδες, υόρκη, οκ, ευχαριστούμε, καλα, κοιτάς, σα, π, χρόνος, ησυχία, ασφάλεια, εκείνος, a, βρήκε,
- τέσσερα, βγάλω, μπες, συχνά, ημέρα, μάνα, εν, αγαπάς, άνθρωπο, γραμμή, φωτογραφίες, προσέχεις, ύπνο,
- μυστικό, σχετικά, είδους, σκέψου, χριστούγεννα, κόσμου, τομ, μισώ, σύστημα, δουλειές, τελείως, πεθάνω,
- αλλάξει, δεξιά, συνήθως, δουλεύω, μάικλ, εβδομάδα, νούμερο, λείπει, έτοιμη, τμήμα, βγει, ψυχή, έπεσε,
- κάθαρμα, ματιά, οποία, πληροφορίες, μονο, κρίμα, τραγούδι, μαγαζί, δουλεύεις, μαζι, τέλειο, κύριο,
- λέγεται, τσάρλι, πεθάνεις, σκεφτόμουν, καλησπέρα, συγχαρητήρια, φωνή, εκ, άτομο, παίζεις, σκάφος,
- φαίνεσαι, ξαφνικά, παραπάνω, ατύχημα, θελω, ξέχνα, ήρθατε, εναντίον, τραπέζι, γράμμα, μείνετε, αμερική,
- βασιλιάς, υπό, μπάνιο, ποτε, ίδιος, προφανώς, μαλάκα, αδερφός, άνδρες, nαι, χρονών, ναί, κλειδί, δις,
- γιαγιά, παράξενο, πτώμα, βρήκαμε, μιλήσεις, υποτίθεται, ορκίζομαι, δυνατά, ποιό, θάλασσα, παίρνω, άκουσες,
- παρέα, αριστερά, έμαθα, μάχη, μηχανή, σάρα, ζωντανός, όνειρο, παλιό, μπορούσαμε, πάντως, ανάμεσα, έχασα,
- νωρίς, κάποιοι, άκου, παίζει, φτάνει, δίνω, βγες, υπέροχη, νόημα, έλεγχο, μέτρα, ξερεις, ζει, δείχνει,
+ χρόνο, στους, πάρω, μπαμπά, δικό, απ, γίνεται, εσείς, λέω, συγνώμη, όλο, μητέρα, έκανες, πιστεύω,
+ ήσουν, κάποια, σίγουρα, υπάρχουν, όλη, ενα, αυτο, ξέρει, μωρό, ιδέα, δει, μάλλον, ίδιο, πάρε, είδα,
+ αύριο, βλέπεις, νέα, κόσμο, νομίζεις, τί, εμείς, σταμάτα, πάρει, αγάπη, πατέρας, όλους, αρκετά,
+ χρειάζεται, καιρό, φορές, κάνουν, ακόμη, α, πατέρα, προς, αμέσως, πια, ηταν, χαρά, απόψε, όνομα,
+ μάλιστα, μόνος, μεγάλη, κανένα, ελα, πραγματικά, αυτοί, πει, πότε, εχω, βράδυ, αυτές, θέλετε, κάνετε,
+ σημαίνει, πρώτη, ποιο, πόλη, μπορούσα, ποια, γαμώτο, ήδη, τελευταία, άνθρωποι, τέλος, απλώς, νόμιζα,
+ ξέρετε, μέρες, δεις, θέση, αυτούς, καταλαβαίνω, φύγε, χέρια, εκτός, ήξερα, οπότε, λεπτά, μακριά,
+ κάνε, αμάξι, δική, λεπτό, μεγάλο, μήπως, κορίτσι, μάτια, ελάτε, πρόκειται, πόρτα, δίκιο, βοήθεια,
+ ήρθε, μιλήσω, δρόμο, εαυτό, καθόλου, ορίστε, βρω, πειράζει, μπορείτε, καλός, πέρα, κοντά, εννοώ,
+ τέτοιο, μπροστά, έρθει, χρειάζομαι, χέρι, ελπίζω, δώσε, διάολο, φύγω, ιστορία, όπλο, αφού, πρωί,
+ νύχτα, ωραίο, τύπος, ξανά, θυμάσαι, δούμε, κατά, εννοείς, αγαπώ, κακό, θέμα, εδω, αυτήν, τρόπο,
+ κεφάλι, είχες, μερικές, μιλάς, φίλος, άνθρωπος, φύγουμε, όλες, σκατά, ανθρώπους, βέβαια, άντρας,
+ κάποιο, πάνε, αστυνομία, αλλιώς, συνέβη, χαίρομαι, άλλα, περισσότερο, καλύτερο, εκείνη, πάρεις, τo,
+ νερό, ώρες, σίγουρος, vα, τρεις, εχεις, πρώτα, μπορούσε, σ, οταν, δρ, πιστεύεις, μόνη, ποιός, καμιά,
+ κανέναν, πέθανε, εχει, ετσι, αγόρι, ανησυχείς, άντρες, δωμάτιο, ομάδα, ίδια, εμπρός, βρούμε, βοηθήσω,
+ τέτοια, πήρε, τρία, λόγο, μικρό, αντίο, o, πέντε, πήγε, καν, ευκαιρία, είδες, έρχεται, δηλαδή,
+ αργότερα, ήθελε, πούμε, λέμε, όπου, αλλα, κόρη, κόσμος, γυναίκες, τηλέφωνο, εάν, δώσω, καρδιά, βρήκα,
+ γραφείο, επίσης, νιώθω, σχέση, θέλουν, ισως, τέλεια, είχαμε, κάπου, μυαλό, ώστε, καλημέρα, σχολείο,
+ θεός, μικρή, τρέχει, ψέματα, ξέρουμε, οικογένεια, εισαι, θυμάμαι, κ, ενός, φίλοι, πρόσεχε,
+ καταλαβαίνεις, αργά, ντε, θέλουμε, σύντομα, πήρα, σχεδόν, παιχνίδι, κύριοι, γειά, μήνες, μπαμπάς,
+ σοβαρά, δολάρια, τουλάχιστον, χρήματα, πείτε, πόδια, αίμα, κοπέλα, φαγητό, ειμαι, ποιον, μερικά,
+ δύσκολο, μπορούν, βρεις, όμορφη, φύγεις, τύχη, πλάκα, έρθεις, άντρα, κορίτσια, μείνε, αστείο, καμία,
+ είχαν, χάρη, άλλος, πρεπει, σημασία, φυλακή, νεκρός, συγχωρείτε, φοβάμαι, μπράβο, γύρω, κανένας, μεταξύ,
+ τ, χθες, πολλές, όνομά, τζακ, ρε, καληνύχτα, πολυ, φύγει, αφήσω, ήθελες, tι, ήρθες, ακούς, πρώτο, γιατι,
+ ηρέμησε, γι, πάρουμε, πάρα, άλλους, κατάλαβα, έρθω, συνέχεια, έλεγα, γλυκιά, νοιάζει, χριστέ, βιβλίο,
+ κύριος, μ, χώρα, αρχή, ήρθα, πεθάνει, γη, έτοιμος, εγω, άσχημα, συμβεί, αυτοκίνητο, ζωής, τελικά, φέρω,
+ τρόπος, κατάσταση, www, περιμένω, σημαντικό, όσα, σκέφτηκα, μιλήσουμε, αφήστε, τωρα, ακούω, γιος, σκοτώσω,
+ δύναμη, κα, κε, εκείνο, γονείς, μιλάω, σκοτώσει, ολα, μείνει, μείνω, αρέσουν, δεv, υπόθεση, φίλους, όπλα,
+ υποθέτω, εμάς, ενώ, έξι, σχέδιο, άρεσε, καφέ, σκότωσε, χρειαζόμαστε, φίλο, σωστό, προσπαθώ, κάναμε,
+ κοιτάξτε, μoυ, κου, ποτό, εσάς, έι, έφυγε, ταινία, μοιάζει, κρεβάτι, εχουμε, περιμένει, νέο, μπορούσες,
+ μάθω, αφήσεις, περιμένετε, χρειάζεσαι, υπήρχε, μισό, δέκα, αφεντικό, περίπου, άλλοι, λόγος, ξέρουν, κάποτε,
+ βρήκες, καλύτερη, υπέροχο, τζον, δίπλα, σκάσε, θεού, άκουσα, φύγετε, λέξη, παρά, επόμενη, λέτε, περάσει,
+ πόσα, γίνεις, σώμα, ν, πήρες, τελείωσε, γιο, ρούχα, σκέφτομαι, εσυ, άλλες, γυρίσω, βάλω, μουσική, ραντεβού,
+ φωτιά, έδωσε, πάτε, φοβάσαι, βρει, δείξω, γίνω, βοηθήσει, τύπο, σειρά, αξίζει, μείνεις, είπαν, άλλον,
+ κυρίες, λίγη, πέρασε, κάτσε, πήγα, δείτε, μιας, βδομάδα, έρχομαι, προσοχή, εύκολο, ερώτηση, υπέροχα,
+ σίγουρη, νοσοκομείο, τρελός, ενας, βάλε, πόλεμο, φέρε, δικά, τιμή, κατάλαβες, ταξίδι, οποίο, δουλεύει, θεό,
+ μικρέ, μάθεις, βρίσκεται, πολλοί, δες, πάρτε, παντού, πρόσωπο, μήνυμα, αδερφή, μιλάει, παλιά, πουθενά,
+ κράτα, περίπτωση, φως, επάνω, έλεγε, συμφωνία, οπως, ολοι, πρώτος, δεσποινίς, γιατρός, γνωρίζω, σαμ,
+ σκέφτεσαι, ει, φίλη, σεξ, έκαναν, προβλήματα, κάπως, ό, τελευταίο, ακούσει, τζο, καλώς, επιλογή,
+ σταματήστε, τόσα, οτιδήποτε, περισσότερα, άδεια, πάρτι, περίμενα, ακούγεται, gmteam, ήξερες, καιρός,
+ μαλλιά, καλύτερος, κανεις, φρανκ, μέση, συνέχισε, τίποτε, φωτογραφία, κατι, μεγάλος, περιοχή, άσε, καθώς,
+ είδε, λόγια, μήνα, μαλακίες, όμορφο, δώρο, στόμα, χάλια, εντελώς, μακάρι, τελειώσει, γνώμη, γιατρέ, ξερω,
+ πλευρά, μέλλον, θάνατο, νιώθεις, έτοιμοι, κομμάτι, μάθει, μιλάμε, ψηλά, αέρα, ερωτήσεις, αυτού, δώσει,
+ φεύγω, σημείο, τηλεόραση, κυριε, πραγματικότητα, ανάγκη, βοηθήσεις, προσπάθησε, γύρνα, άφησε, λίγα, κάντε,
+ είvαι, βλέπετε, αυτη, δείπνο, επιτέλους, κέντρο, περίεργο, ακούστε, πλοίο, κάποιες, δικός, σoυ, οικογένειά,
+ μιλήσει, πλέον, υπόσχομαι, περιμένεις, ήξερε, σκοτώσεις, ενταξει, δώσεις, εκει, ήμασταν, έρχονται, κώλο,
+ ρωτήσω, παίρνει, σιγά, σήκω, στοιχεία, αδελφή, βασικά, μένει, άκρη, πηγαίνετε, παίρνεις, tο, περιμένουμε,
+ συγχωρείς, μικρός, πόδι, δίνει, εκατομμύρια, ξενοδοχείο, αποστολή, ενδιαφέρον, χάρηκα, αεροπλάνο, γάμο,
+ χιλιάδες, υόρκη, οκ, ευχαριστούμε, καλα, κοιτάς, σα, π, χρόνος, ησυχία, ασφάλεια, εκείνος, a, βρήκε,
+ τέσσερα, βγάλω, μπες, συχνά, ημέρα, μάνα, εν, αγαπάς, άνθρωπο, γραμμή, φωτογραφίες, προσέχεις, ύπνο,
+ μυστικό, σχετικά, είδους, σκέψου, χριστούγεννα, κόσμου, τομ, μισώ, σύστημα, δουλειές, τελείως, πεθάνω,
+ αλλάξει, δεξιά, συνήθως, δουλεύω, μάικλ, εβδομάδα, νούμερο, λείπει, έτοιμη, τμήμα, βγει, ψυχή, έπεσε,
+ κάθαρμα, ματιά, οποία, πληροφορίες, μονο, κρίμα, τραγούδι, μαγαζί, δουλεύεις, μαζι, τέλειο, κύριο,
+ λέγεται, τσάρλι, πεθάνεις, σκεφτόμουν, καλησπέρα, συγχαρητήρια, φωνή, εκ, άτομο, παίζεις, σκάφος,
+ φαίνεσαι, ξαφνικά, παραπάνω, ατύχημα, θελω, ξέχνα, ήρθατε, εναντίον, τραπέζι, γράμμα, μείνετε, αμερική,
+ βασιλιάς, υπό, μπάνιο, ποτε, ίδιος, προφανώς, μαλάκα, αδερφός, άνδρες, nαι, χρονών, ναί, κλειδί, δις,
+ γιαγιά, παράξενο, πτώμα, βρήκαμε, μιλήσεις, υποτίθεται, ορκίζομαι, δυνατά, ποιό, θάλασσα, παίρνω, άκουσες,
+ παρέα, αριστερά, έμαθα, μάχη, μηχανή, σάρα, ζωντανός, όνειρο, παλιό, μπορούσαμε, πάντως, ανάμεσα, έχασα,
+ νωρίς, κάποιοι, άκου, παίζει, φτάνει, δίνω, βγες, υπέροχη, νόημα, έλεγχο, μέτρα, ξερεις, ζει, δείχνει,
βρες, τού
"""
# Source: https://www.101languages.net/russian/most-common-russian-words/
alias words_ru = """
-я, не, что, в, и, ты, это, на, с, он, вы, как, мы, да, а, мне, меня, у, нет, так, но, то, все, тебя, его,
-за, о, она, тебе, если, они, бы, же, ну, здесь, к, из, есть, чтобы, для, хорошо, когда, вас, только, по,
-вот, просто, был, знаю, нас, всё, было, от, может, кто, вам, очень, их, там, будет, уже, почему, еще,
-быть, где, спасибо, ничего, сейчас, или, могу, хочу, нам, чем, мой, до, надо, этого, ее, теперь, давай,
-знаешь, нужно, больше, этом, нибудь, раз, со, была, этот, ему, ладно, эй, время, тоже, даже, хочешь,
-сказал, ли, себя, думаю, пока, должен, потому, никогда, ни, тут, ещё, её, пожалуйста, сюда, привет,
-тогда, конечно, моя, него, сегодня, один, тобой, правда, лучше, об, были, того, можно, мной, всегда,
-сказать, день, сэр, без, можешь, чего, эти, дело, значит, лет, много, во, делать, буду, порядке, должны,
-такой, ведь, ним, всего, сделать, хотел, твой, жизнь, ей, мистер, потом, через, себе, них, всех, такое,
-им, куда, том, мама, после, человек, люди, слишком, иди, зачем, этим, немного, сколько, этой, знаете,
-боже, ней, эту, который, отец, свою, деньги, два, под, твоя, мои, никто, моей, думаешь, друг, жизни,
-эта, назад, видел, кажется, точно, вместе, люблю, мог, случилось, сам, нравится, черт, какой, людей,
-папа, домой, тот, скажи, которые, должна, три, всем, сделал, возможно, прошу, будем, дома, парень,
-снова, говорит, место, отсюда, можем, будешь, пошли, делаешь, совсем, говорил, понимаю, завтра, хочет,
-простите, разве, давайте, хотите, отлично, сказала, туда, прямо, времени, вами, лишь, своей, хватит,
-думал, можете, дом, дела, знать, дай, понял, помочь, говорить, слушай, свои, поэтому, прости, знает,
-именно, знал, тем, кого, смотри, каждый, ваш, похоже, найти, моего, наш, мать, одна, имя, про, говорю,
-будут, оно, свой, нельзя, извините, стоит, действительно, зовут, поговорить, доктор, перед, несколько,
-нужен, происходит, ко, господи, возьми, мою, тех, нами, вижу, должно, наверное, откуда, понимаешь, верно,
-скоро, уж, деле, твои, пусть, всю, хотела, при, более, ребята, нее, быстро, подожди, идти, надеюсь, чём,
-работу, видеть, такая, этих, уверен, нужна, года, раньше, такие, руки, видишь, какая, посмотри, сын,
-самом, ваша, послушай, равно, наши, другой, ага, мир, извини, минут, против, твоей, пор, жить, ж, жаль,
-вообще, могли, хотя, человека, пора, ради, говорят, почти, твою, могут, над, весь, первый, чёрт, слышал,
-собой, брат, вещи, дня, скажу, говоришь, нормально, своего, мое, ваше, итак, будь, ночь, хоть, ясно,
-плохо, дверь, вопрос, господин, давно, денег, ваши, ка, мисс, одну, глаза, пять, будто, между, пойду,
-опять, работа, самое, иногда, детей, этому, рад, здорово, бог, одного, ночи, готов, номер, которая,
-машину, любовь, дорогая, виду, одно, прекрасно, вон, своих, быстрее, отца, женщина, достаточно, рядом,
-убить, таким, пойдем, смерти, дети, такого, правильно, месте, никаких, сказали, здравствуйте, пару, две,
-видела, долго, хороший, ах, кроме, алло, нашей, прав, вчера, вечером, жена, миссис, чтоб, друга, нужны,
-кем, какие, те, увидеть, утро, смогу, неё, сама, моему, большой, сразу, работать, сердце, стал, своим,
-сначала, могла, вроде, ними, говори, голову, дальше, помнишь, либо, ума, одной, вечер, случае, взять,
-проблемы, помощь, добрый, год, думала, делает, скорее, слова, капитан, последний, важно, дней, помню,
-ночью, утром, моих, произошло, которую, боюсь, также, вашей, ой, стой, твоего, никого, дорогой, убил,
-насчет, друзья, самый, проблема, видели, вперед, дерьмо, понятно, чувствую, наша, будете, тому, имею,
-вернуться, придется, пришел, спать, стать, столько, говорила, пойти, иначе, работает, девушка, час,
-момент, моим, умер, думаете, доброе, слово, новый, часов, мире, знаем, твое, мальчик, однажды, интересно,
-конец, играть, a, заткнись, сделали, посмотреть, идет, узнать, свое, права, хорошая, город, джон,
-долларов, парни, идем, говорите, уйти, понять, знала, поздно, нашли, работы, скажите, сделаю, увидимся,
-какого, другие, идея, пошел, доме, дочь, имеет, приятно, лицо, наших, обо, понимаете, руку, часть,
-смотрите, вся, собираюсь, четыре, прежде, хотят, скажешь, чувак, дайте, сделала, кофе, джек, верю,
-ждать, затем, большое, сами, неужели, моё, любит, мужчина, дать, господа, таких, осталось, которой,
-далеко, вернусь, сильно, ох, сможешь, кому, вашего, посмотрим, машина, подождите, свет, чуть, серьезно,
-пришли, оружие, решил, смысле, видите, тихо, нашел, свидания, путь, той, совершенно, следующий, которого,
-места, парня, вдруг, пути, мадам, какое, шанс, сестра, нашего, ужасно, минуту, вокруг, другом, иду,
-других, хотели, нем, смерть, подумал, фильм, оставь, делаете, уверена, кровь, говорили, внимание,
-помогите, идите, держи, получить, оба, взял, спокойно, обычно, мало, забыл, странно, смотреть, поехали,
-дал, часа, прекрати, посмотрите, готовы, вернулся, поверить, позже, милая, женщины, любишь, довольно,
-обратно, остаться, думать, та, стороны, полиция, тело, тысяч, делал, машины, угодно, муж, году, неплохо,
-бога, некоторые, конце, милый, the, рождения, трудно, добро, любви, больно, невозможно, спокойной,
-слышишь, типа, получил, которое, приятель, хуже, никому, честь, успокойся, вашу, маленький, выглядит,
-чарли, сына, неделю, i, девочка, делаю, шесть, ноги, история, рассказать, послушайте, часто, кстати,
-двух, забудь, которых, следует, знают, пришла, семья, станет, матери, ребенок, план, проблем, например,
-сделай, воды, немедленно, мира, сэм, телефон, перестань, правду, второй, прощения, ту, наше, уходи, твоих,
-помоги, пол, внутри, нему, смог, десять, нашу, около, бывает, самого, большая, леди, сможем, вниз, легко,
-делай, единственный, рада, меньше, волнуйся, хотим, полагаю, мам, иметь, своими, мере, наконец, начала,
-минутку, работе, пожаловать, другого, двое, никакого, честно, школе, лучший, умереть, дам, насколько,
-всей, малыш, оставить, безопасности, ненавижу, школу, осторожно, сынок, джо, таки, пытался, другое, б,
-клянусь, машине, недели, стало, истории, пришлось, выглядишь, чему, сможет, купить, слышала, знали,
-настоящий, сих, выйти, людям, замечательно, полиции, огонь, пойдём, спросить, дядя, детка, среди, особенно,
-твоим, комнате, шоу, выпить, постоянно, делают, позвольте, родители, письмо, городе, случай, месяцев, мужик,
-благодарю, o, ребенка, смешно, ответ, города, образом, любой, полностью, увидел, еду, имени, вместо,
-абсолютно, обязательно, улице, твоё, убили, ваших, ехать, крови, решение, вина, поможет, своё, секунду,
-обещаю, начать, голос, вещь, друзей, показать, нечего, э, месяц, подарок, приехал, самая, молодец, сделаем,
-крайней, женщин, собираешься, конца, страшно, новости, идиот, потерял, спасти, вернуть, узнал, слушайте,
-хотелось, сон, поняла, прошло, комнату, семь, погоди, главное, рано, корабль, пытаюсь, игра, умерла,
-повезло, всему, возьму, таком, моем, глаз, настолько, идём, удачи, готова, семьи, садись, гарри, держись,
-звучит, мило, война, человеком, право, такую, вопросы, представить, работаю, имеешь, красивая, идёт, никакой,
-профессор, думает, войны, стала, стали, оттуда, известно, слышу, начал, подумать, позвонить, старый, придётся,
-историю, вести, твоему, последнее, хочется, миллионов, нашла, способ, отношения, земле, фрэнк, получится,
-говоря, связи, многие, пошёл, пистолет, убью, руках, получилось, президент, остановить, тьi, оставил, одним,
-you, утра, боль, хорошие, пришёл, открой, брось, вставай, находится, поговорим, кино, людьми, полицию, покажу,
+я, не, что, в, и, ты, это, на, с, он, вы, как, мы, да, а, мне, меня, у, нет, так, но, то, все, тебя, его,
+за, о, она, тебе, если, они, бы, же, ну, здесь, к, из, есть, чтобы, для, хорошо, когда, вас, только, по,
+вот, просто, был, знаю, нас, всё, было, от, может, кто, вам, очень, их, там, будет, уже, почему, еще,
+быть, где, спасибо, ничего, сейчас, или, могу, хочу, нам, чем, мой, до, надо, этого, ее, теперь, давай,
+знаешь, нужно, больше, этом, нибудь, раз, со, была, этот, ему, ладно, эй, время, тоже, даже, хочешь,
+сказал, ли, себя, думаю, пока, должен, потому, никогда, ни, тут, ещё, её, пожалуйста, сюда, привет,
+тогда, конечно, моя, него, сегодня, один, тобой, правда, лучше, об, были, того, можно, мной, всегда,
+сказать, день, сэр, без, можешь, чего, эти, дело, значит, лет, много, во, делать, буду, порядке, должны,
+такой, ведь, ним, всего, сделать, хотел, твой, жизнь, ей, мистер, потом, через, себе, них, всех, такое,
+им, куда, том, мама, после, человек, люди, слишком, иди, зачем, этим, немного, сколько, этой, знаете,
+боже, ней, эту, который, отец, свою, деньги, два, под, твоя, мои, никто, моей, думаешь, друг, жизни,
+эта, назад, видел, кажется, точно, вместе, люблю, мог, случилось, сам, нравится, черт, какой, людей,
+папа, домой, тот, скажи, которые, должна, три, всем, сделал, возможно, прошу, будем, дома, парень,
+снова, говорит, место, отсюда, можем, будешь, пошли, делаешь, совсем, говорил, понимаю, завтра, хочет,
+простите, разве, давайте, хотите, отлично, сказала, туда, прямо, времени, вами, лишь, своей, хватит,
+думал, можете, дом, дела, знать, дай, понял, помочь, говорить, слушай, свои, поэтому, прости, знает,
+именно, знал, тем, кого, смотри, каждый, ваш, похоже, найти, моего, наш, мать, одна, имя, про, говорю,
+будут, оно, свой, нельзя, извините, стоит, действительно, зовут, поговорить, доктор, перед, несколько,
+нужен, происходит, ко, господи, возьми, мою, тех, нами, вижу, должно, наверное, откуда, понимаешь, верно,
+скоро, уж, деле, твои, пусть, всю, хотела, при, более, ребята, нее, быстро, подожди, идти, надеюсь, чём,
+работу, видеть, такая, этих, уверен, нужна, года, раньше, такие, руки, видишь, какая, посмотри, сын,
+самом, ваша, послушай, равно, наши, другой, ага, мир, извини, минут, против, твоей, пор, жить, ж, жаль,
+вообще, могли, хотя, человека, пора, ради, говорят, почти, твою, могут, над, весь, первый, чёрт, слышал,
+собой, брат, вещи, дня, скажу, говоришь, нормально, своего, мое, ваше, итак, будь, ночь, хоть, ясно,
+плохо, дверь, вопрос, господин, давно, денег, ваши, ка, мисс, одну, глаза, пять, будто, между, пойду,
+опять, работа, самое, иногда, детей, этому, рад, здорово, бог, одного, ночи, готов, номер, которая,
+машину, любовь, дорогая, виду, одно, прекрасно, вон, своих, быстрее, отца, женщина, достаточно, рядом,
+убить, таким, пойдем, смерти, дети, такого, правильно, месте, никаких, сказали, здравствуйте, пару, две,
+видела, долго, хороший, ах, кроме, алло, нашей, прав, вчера, вечером, жена, миссис, чтоб, друга, нужны,
+кем, какие, те, увидеть, утро, смогу, неё, сама, моему, большой, сразу, работать, сердце, стал, своим,
+сначала, могла, вроде, ними, говори, голову, дальше, помнишь, либо, ума, одной, вечер, случае, взять,
+проблемы, помощь, добрый, год, думала, делает, скорее, слова, капитан, последний, важно, дней, помню,
+ночью, утром, моих, произошло, которую, боюсь, также, вашей, ой, стой, твоего, никого, дорогой, убил,
+насчет, друзья, самый, проблема, видели, вперед, дерьмо, понятно, чувствую, наша, будете, тому, имею,
+вернуться, придется, пришел, спать, стать, столько, говорила, пойти, иначе, работает, девушка, час,
+момент, моим, умер, думаете, доброе, слово, новый, часов, мире, знаем, твое, мальчик, однажды, интересно,
+конец, играть, a, заткнись, сделали, посмотреть, идет, узнать, свое, права, хорошая, город, джон,
+долларов, парни, идем, говорите, уйти, понять, знала, поздно, нашли, работы, скажите, сделаю, увидимся,
+какого, другие, идея, пошел, доме, дочь, имеет, приятно, лицо, наших, обо, понимаете, руку, часть,
+смотрите, вся, собираюсь, четыре, прежде, хотят, скажешь, чувак, дайте, сделала, кофе, джек, верю,
+ждать, затем, большое, сами, неужели, моё, любит, мужчина, дать, господа, таких, осталось, которой,
+далеко, вернусь, сильно, ох, сможешь, кому, вашего, посмотрим, машина, подождите, свет, чуть, серьезно,
+пришли, оружие, решил, смысле, видите, тихо, нашел, свидания, путь, той, совершенно, следующий, которого,
+места, парня, вдруг, пути, мадам, какое, шанс, сестра, нашего, ужасно, минуту, вокруг, другом, иду,
+других, хотели, нем, смерть, подумал, фильм, оставь, делаете, уверена, кровь, говорили, внимание,
+помогите, идите, держи, получить, оба, взял, спокойно, обычно, мало, забыл, странно, смотреть, поехали,
+дал, часа, прекрати, посмотрите, готовы, вернулся, поверить, позже, милая, женщины, любишь, довольно,
+обратно, остаться, думать, та, стороны, полиция, тело, тысяч, делал, машины, угодно, муж, году, неплохо,
+бога, некоторые, конце, милый, the, рождения, трудно, добро, любви, больно, невозможно, спокойной,
+слышишь, типа, получил, которое, приятель, хуже, никому, честь, успокойся, вашу, маленький, выглядит,
+чарли, сына, неделю, i, девочка, делаю, шесть, ноги, история, рассказать, послушайте, часто, кстати,
+двух, забудь, которых, следует, знают, пришла, семья, станет, матери, ребенок, план, проблем, например,
+сделай, воды, немедленно, мира, сэм, телефон, перестань, правду, второй, прощения, ту, наше, уходи, твоих,
+помоги, пол, внутри, нему, смог, десять, нашу, около, бывает, самого, большая, леди, сможем, вниз, легко,
+делай, единственный, рада, меньше, волнуйся, хотим, полагаю, мам, иметь, своими, мере, наконец, начала,
+минутку, работе, пожаловать, другого, двое, никакого, честно, школе, лучший, умереть, дам, насколько,
+всей, малыш, оставить, безопасности, ненавижу, школу, осторожно, сынок, джо, таки, пытался, другое, б,
+клянусь, машине, недели, стало, истории, пришлось, выглядишь, чему, сможет, купить, слышала, знали,
+настоящий, сих, выйти, людям, замечательно, полиции, огонь, пойдём, спросить, дядя, детка, среди, особенно,
+твоим, комнате, шоу, выпить, постоянно, делают, позвольте, родители, письмо, городе, случай, месяцев, мужик,
+благодарю, o, ребенка, смешно, ответ, города, образом, любой, полностью, увидел, еду, имени, вместо,
+абсолютно, обязательно, улице, твоё, убили, ваших, ехать, крови, решение, вина, поможет, своё, секунду,
+обещаю, начать, голос, вещь, друзей, показать, нечего, э, месяц, подарок, приехал, самая, молодец, сделаем,
+крайней, женщин, собираешься, конца, страшно, новости, идиот, потерял, спасти, вернуть, узнал, слушайте,
+хотелось, сон, поняла, прошло, комнату, семь, погоди, главное, рано, корабль, пытаюсь, игра, умерла,
+повезло, всему, возьму, таком, моем, глаз, настолько, идём, удачи, готова, семьи, садись, гарри, держись,
+звучит, мило, война, человеком, право, такую, вопросы, представить, работаю, имеешь, красивая, идёт, никакой,
+профессор, думает, войны, стала, стали, оттуда, известно, слышу, начал, подумать, позвонить, старый, придётся,
+историю, вести, твоему, последнее, хочется, миллионов, нашла, способ, отношения, земле, фрэнк, получится,
+говоря, связи, многие, пошёл, пистолет, убью, руках, получилось, президент, остановить, тьi, оставил, одним,
+you, утра, боль, хорошие, пришёл, открой, брось, вставай, находится, поговорим, кино, людьми, полицию, покажу,
волосы, последние, брата, месяца
"""
@@ -585,7 +586,7 @@ fn gen_word_pairs[words: String = words_en]() -> List[String]:
try:
var list = words.split(",")
for w in list:
- var w1 = w[].strip()
+ var w1 = str(w[].strip())
for w in list:
var w2 = w[].strip()
result.append(w1 + " " + w2)
@@ -594,11 +595,11 @@ fn gen_word_pairs[words: String = words_en]() -> List[String]:
return result
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmarks
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
-fn bench_small_keys[s: String](inout b: Bencher) raises:
+fn bench_small_keys[s: String](mut b: Bencher) raises:
var words = gen_word_pairs[s]()
@always_inline
@@ -612,7 +613,7 @@ fn bench_small_keys[s: String](inout b: Bencher) raises:
@parameter
-fn bench_small_keys_new_hash_function[s: String](inout b: Bencher) raises:
+fn bench_small_keys_new_hash_function[s: String](mut b: Bencher) raises:
var words = gen_word_pairs[s]()
@always_inline
@@ -626,7 +627,7 @@ fn bench_small_keys_new_hash_function[s: String](inout b: Bencher) raises:
@parameter
-fn bench_long_key[s: String](inout b: Bencher) raises:
+fn bench_long_key[s: String](mut b: Bencher) raises:
@always_inline
@parameter
fn call_fn():
@@ -637,7 +638,7 @@ fn bench_long_key[s: String](inout b: Bencher) raises:
@parameter
-fn bench_long_key_new_hash_function[s: String](inout b: Bencher) raises:
+fn bench_long_key_new_hash_function[s: String](mut b: Bencher) raises:
@always_inline
@parameter
fn call_fn():
@@ -647,9 +648,9 @@ fn bench_long_key_new_hash_function[s: String](inout b: Bencher) raises:
b.iter[call_fn]()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Main
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
def main():
var m = Bench(BenchConfig(num_repetitions=1))
m.bench_function[bench_small_keys[words_ar]](BenchId("bench_small_keys_ar"))
diff --git a/stdlib/benchmarks/math/bench_math.mojo b/stdlib/benchmarks/math/bench_math.mojo
index 1ba4175a74..3e17eaf282 100644
--- a/stdlib/benchmarks/math/bench_math.mojo
+++ b/stdlib/benchmarks/math/bench_math.mojo
@@ -19,9 +19,9 @@ from random import *
from benchmark import Bench, BenchConfig, Bencher, BenchId, Unit, keep, run
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Data
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
alias input_type = Float32
@@ -54,15 +54,15 @@ fn make_int_inputs(begin: Int, end: Int, num: Int) -> List[Int]:
var inputs = make_inputs(0, 10_000, 1_000_000)
var int_inputs = make_int_inputs(0, 10_000_000, 1_000_000)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark math_func
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
fn bench_math[
math_f1p: fn[type: DType, size: Int] (SIMD[type, size]) -> SIMD[type, size]
-](inout b: Bencher) raises:
+](mut b: Bencher) raises:
@always_inline
@parameter
fn call_fn() raises:
@@ -73,15 +73,15 @@ fn bench_math[
b.iter[call_fn]()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark fma
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
fn bench_math3[
math_f3p: fn[type: DType, size: Int] (
SIMD[type, size], SIMD[type, size], SIMD[type, size]
) -> SIMD[type, size]
-](inout b: Bencher) raises:
+](mut b: Bencher) raises:
@always_inline
@parameter
fn call_fn() raises:
@@ -92,11 +92,11 @@ fn bench_math3[
b.iter[call_fn]()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark lcm/gcd
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
-fn bench_math2[math_f2p: fn (Int, Int, /) -> Int](inout b: Bencher) raises:
+fn bench_math2[math_f2p: fn (Int, Int, /) -> Int](mut b: Bencher) raises:
@always_inline
@parameter
fn call_fn() raises:
@@ -107,9 +107,9 @@ fn bench_math2[math_f2p: fn (Int, Int, /) -> Int](inout b: Bencher) raises:
b.iter[call_fn]()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Main
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
def main():
seed()
var m = Bench(BenchConfig(num_repetitions=1))
diff --git a/stdlib/benchmarks/utils/bench_formatter.mojo b/stdlib/benchmarks/utils/bench_formatter.mojo
index 83c4c44e82..12896f3c91 100644
--- a/stdlib/benchmarks/utils/bench_formatter.mojo
+++ b/stdlib/benchmarks/utils/bench_formatter.mojo
@@ -15,22 +15,23 @@
# the -t flag. Remember to replace it again before pushing any code.
from sys import simdwidthof
+
from benchmark import Bench, BenchConfig, Bencher, BenchId, Unit, keep, run
from bit import count_trailing_zeros
from builtin.dtype import _uint_type_of_width
from utils.stringref import _align_down, _memchr, _memmem
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Data
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmarks
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
-fn bench_writer_int[n: Int](inout b: Bencher) raises:
+fn bench_writer_int[n: Int](mut b: Bencher) raises:
@always_inline
@parameter
fn call_fn():
@@ -42,7 +43,7 @@ fn bench_writer_int[n: Int](inout b: Bencher) raises:
@parameter
-fn bench_writer_simd[n: Int](inout b: Bencher) raises:
+fn bench_writer_simd[n: Int](mut b: Bencher) raises:
@always_inline
@parameter
fn call_fn():
@@ -53,9 +54,9 @@ fn bench_writer_simd[n: Int](inout b: Bencher) raises:
b.iter[call_fn]()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Main
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
def main():
var m = Bench(BenchConfig(num_repetitions=1))
m.bench_function[bench_writer_int[42]](BenchId("bench_writer_int_42"))
diff --git a/stdlib/benchmarks/utils/bench_memmem.mojo b/stdlib/benchmarks/utils/bench_memmem.mojo
index 6fd0b16a89..777557784e 100644
--- a/stdlib/benchmarks/utils/bench_memmem.mojo
+++ b/stdlib/benchmarks/utils/bench_memmem.mojo
@@ -15,16 +15,17 @@
# the -t flag. Remember to replace it again before pushing any code.
from sys import simdwidthof
+
from benchmark import Bench, BenchConfig, Bencher, BenchId, Unit, keep, run
from bit import count_trailing_zeros
from builtin.dtype import _uint_type_of_width
-from memory import memcmp, bitcast, UnsafePointer, pack_bits
+from memory import UnsafePointer, bitcast, memcmp, pack_bits
from utils.stringref import _align_down, _memchr, _memmem
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Data
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
var haystack = """Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer sed dictum est, et finibus ipsum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam tincidunt vel lacus vitae pulvinar. Donec ac ligula elementum, mollis purus a, lacinia quam. Maecenas vulputate mauris quis sem euismod sollicitudin. Proin accumsan nulla vel nisl congue varius. Morbi a erat dui. Aliquam maximus interdum orci, vitae pretium lorem bibendum non. Vestibulum eu lacus ullamcorper, egestas dui vel, pharetra ipsum. Pellentesque sagittis, urna a tincidunt sodales, leo sem placerat eros, vitae molestie felis diam at dolor.
Donec viverra sem sit amet facilisis laoreet. Morbi semper convallis nisi, vitae congue velit tincidunt vel. Fusce ultrices, libero vel venenatis placerat, justo tellus porttitor massa, at volutpat tortor nunc id dui. Morbi eu ex quis odio porttitor ultricies vel eget massa. Aenean quis luctus nulla. Fusce sit amet leo at quam hendrerit mattis. Morbi sed quam nisl. Quisque purus enim, iaculis sed laoreet vel, pellentesque ut orci. Vivamus risus orci, varius eu pharetra quis, tincidunt non enim. Suspendisse bibendum lacus ex, quis blandit lectus malesuada a. Maecenas iaculis porta lacus, sit amet tristique ante scelerisque non. Proin auctor elit in lacus dictum egestas. Pellentesque tincidunt justo sed vehicula blandit. Pellentesque vehicula facilisis tellus in viverra.
@@ -142,9 +143,9 @@ Curabitur auctor volutpat diam vitae vehicula. Vivamus est arcu, efficitur nec i
var needle = "school" # a word intentionally not in the test data
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Baseline `_memmem` implementation
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
fn _memmem_baseline[
type: DType
@@ -184,11 +185,11 @@ fn _memmem_baseline[
return UnsafePointer[Scalar[type]]()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmarks
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@parameter
-fn bench_find_baseline(inout b: Bencher) raises:
+fn bench_find_baseline(mut b: Bencher) raises:
@always_inline
@parameter
fn call_fn():
@@ -203,7 +204,7 @@ fn bench_find_baseline(inout b: Bencher) raises:
@parameter
-fn bench_find_optimized(inout b: Bencher) raises:
+fn bench_find_optimized(mut b: Bencher) raises:
@always_inline
@parameter
fn call_fn():
@@ -217,9 +218,9 @@ fn bench_find_optimized(inout b: Bencher) raises:
b.iter[call_fn]()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Benchmark Main
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
def main():
var m = Bench(BenchConfig(num_repetitions=1))
m.bench_function[bench_find_baseline](BenchId("find_baseline"))
diff --git a/stdlib/docs/bencher/Bench.md b/stdlib/docs/bencher/Bench.md
index 1e71a29c53..19133b572f 100644
--- a/stdlib/docs/bencher/Bench.md
+++ b/stdlib/docs/bencher/Bench.md
@@ -33,7 +33,7 @@ Defines the main Benchmark struct which executes a Benchmark and print result.
```mojo
-__init__(inout self: Self, config: Optional[BenchConfig] = #kgen.none, mode: Mode = 0)
+__init__(out self: Self, config: Optional[BenchConfig] = #kgen.none, mode: Mode = 0)
```
@@ -56,7 +56,7 @@ Constructs a Benchmark object based on specific configuration and mode.
```mojo
-bench_with_input[T: AnyType, bench_fn: fn(inout Bencher, $0) capturing -> None](inout self: Self, bench_id: BenchId, input: T, throughput_elems: Optional[Int] = #kgen.none)
+bench_with_input[T: AnyType, bench_fn: fn(mut Bencher, $0) capturing -> None](mut self: Self, bench_id: BenchId, input: T, throughput_elems: Optional[Int] = #kgen.none)
```
@@ -66,7 +66,7 @@ Benchmarks an input function with input args of type AnyType.
**Parameters:**
- T (`AnyType`): Benchmark function input type.
-- bench_fn (`fn(inout Bencher, $0) capturing -> None`): The function to
+- bench_fn (`fn(mut Bencher, $0) capturing -> None`): The function to
be benchmarked.
**Args:**
@@ -83,7 +83,7 @@ Benchmarks an input function with input args of type AnyType.
```mojo
-bench_with_input[T: AnyTrivialRegType, bench_fn: fn(inout Bencher, $0) capturing -> None](inout self: Self, bench_id: BenchId, input: T, throughput_elems: Optional[Int] = #kgen.none)
+bench_with_input[T: AnyTrivialRegType, bench_fn: fn(mut Bencher, $0) capturing -> None](mut self: Self, bench_id: BenchId, input: T, throughput_elems: Optional[Int] = #kgen.none)
```
@@ -93,7 +93,7 @@ Benchmarks an input function with input args of type AnyTrivialRegType.
**Parameters:**
- T (`AnyTrivialRegType`): Benchmark function input type.
-- bench_fn (`fn(inout Bencher, $0) capturing -> None`): The function to
+- bench_fn (`fn(mut Bencher, $0) capturing -> None`): The function to
be benchmarked.
**Args:**
@@ -112,7 +112,7 @@ Benchmarks an input function with input args of type AnyTrivialRegType.
```mojo
-bench_function[bench_fn: fn(inout Bencher) capturing -> None](inout self: Self, bench_id: BenchId, throughput_elems: Optional[Int] = #kgen.none)
+bench_function[bench_fn: fn(mut Bencher) capturing -> None](mut self: Self, bench_id: BenchId, throughput_elems: Optional[Int] = #kgen.none)
```
@@ -121,7 +121,7 @@ Benchmarks or Tests an input function.
**Parameters:**
-- bench_fn (`fn(inout Bencher) capturing -> None`): The function to be
+- bench_fn (`fn(mut Bencher) capturing -> None`): The function to be
benchmarked.
**Args:**
@@ -137,7 +137,7 @@ Benchmarks or Tests an input function.
```mojo
-bench_function[bench_fn: fn(inout Bencher) raises capturing -> None](inout self: Self, bench_id: BenchId, throughput_elems: Optional[Int] = #kgen.none)
+bench_function[bench_fn: fn(mut Bencher) raises capturing -> None](mut self: Self, bench_id: BenchId, throughput_elems: Optional[Int] = #kgen.none)
```
@@ -146,7 +146,7 @@ Benchmarks or Tests an input function.
**Parameters:**
-- bench_fn (`fn(inout Bencher) raises capturing -> None`): The function
+- bench_fn (`fn(mut Bencher) raises capturing -> None`): The function
to be benchmarked.
**Args:**
diff --git a/stdlib/docs/bencher/BenchConfig.md b/stdlib/docs/bencher/BenchConfig.md
index cebb46f13f..8a83984d5e 100644
--- a/stdlib/docs/bencher/BenchConfig.md
+++ b/stdlib/docs/bencher/BenchConfig.md
@@ -48,7 +48,7 @@ frequency.
```mojo
-__init__(inout self: out_file: Optional[Path] = None, min_runtime_secs: SIMD[float64, 1] = 1.0, max_runtime_secs: SIMD[float64, 1] = 2.0, min_warmuptime_secs: SIMD[float64, 1] = 1.0, max_batch_size: Int = 0, max_iters: Int = 1000000000, num_repetitions: Int = 1, flush_denormals: Bool = True)
+__init__(out self: out_file: Optional[Path] = None, min_runtime_secs: SIMD[float64, 1] = 1.0, max_runtime_secs: SIMD[float64, 1] = 2.0, min_warmuptime_secs: SIMD[float64, 1] = 1.0, max_batch_size: Int = 0, max_iters: Int = 1000000000, num_repetitions: Int = 1, flush_denormals: Bool = True)
```
diff --git a/stdlib/docs/bencher/BenchId.md b/stdlib/docs/bencher/BenchId.md
index e305f890fe..0d215bd972 100644
--- a/stdlib/docs/bencher/BenchId.md
+++ b/stdlib/docs/bencher/BenchId.md
@@ -30,7 +30,7 @@ execution.
-`__init__(inout self: Self, func_name: String, input_id: String)`
+`__init__(out self: Self, func_name: String, input_id: String)`
@@ -47,7 +47,7 @@ Constructs a Benchmark Id object from input function name and Id phrase.
-`__init__(inout self: Self, func_name: String)`
+`__init__(out self: Self, func_name: String)`
diff --git a/stdlib/docs/bencher/Bencher.md b/stdlib/docs/bencher/Bencher.md
index 4270a7a714..91d68e80d8 100644
--- a/stdlib/docs/bencher/Bencher.md
+++ b/stdlib/docs/bencher/Bencher.md
@@ -30,7 +30,7 @@ Defines a Bencher struct which facilitates the timing of a target function.
-`__init__(inout self: Self, num_iters: Int)`
+`__init__(out self: Self, num_iters: Int)`
@@ -48,7 +48,7 @@ Constructs a Bencher object to run and time a function.
-`iter[iter_fn: fn() capturing -> None](inout self: Self)`
+`iter[iter_fn: fn() capturing -> None](mut self: Self)`
@@ -65,7 +65,7 @@ of times.
-`iter[iter_fn: fn() raises capturing -> None](inout self: Self)`
+`iter[iter_fn: fn() raises capturing -> None](mut self: Self)`
@@ -85,7 +85,7 @@ of times.
-`iter_custom[iter_fn: fn(Int) capturing -> Int](inout self: Self)`
+`iter_custom[iter_fn: fn(Int) capturing -> Int](mut self: Self)`
@@ -101,7 +101,7 @@ Times a target function with custom number of iterations.
-`iter_custom[iter_fn: fn(Int) raises capturing -> Int](inout self: Self)`
+`iter_custom[iter_fn: fn(Int) raises capturing -> Int](mut self: Self)`
diff --git a/stdlib/docs/bencher/BenchmarkInfo.md b/stdlib/docs/bencher/BenchmarkInfo.md
index 88eafec487..52b2922fa0 100644
--- a/stdlib/docs/bencher/BenchmarkInfo.md
+++ b/stdlib/docs/bencher/BenchmarkInfo.md
@@ -33,7 +33,7 @@ Defines a Benchmark Info struct to record execution Statistics.
-`__init__(inout self: Self, name: String, result: Report, elems: Optional[Int])`
+`__init__(out self: Self, name: String, result: Report, elems: Optional[Int])`
diff --git a/stdlib/docs/internal/README.md b/stdlib/docs/internal/README.md
new file mode 100644
index 0000000000..b80fd03dca
--- /dev/null
+++ b/stdlib/docs/internal/README.md
@@ -0,0 +1,16 @@
+## WARNING
+
+Everything in this file/directory is subject to revision on any bugfix or security
+update. We (the stdlib team and contributors), reserve the right to remove,
+change the API contracts of, rename, or cause to instantly crash the program,
+any operation described in here. These are **PRIVATE** APIs and implementation
+details for the Mojo stdlib and for MAX to use. **WE WILL CHANGE IT WHENEVER
+WE FIND IT CONVENIENT TO DO SO WITHOUT WARNING OR NOTICE**.
+
+## Purpose
+
+This directory contains internal documentation for the implementation details
+of the Mojo compiler, runtime, and stdlib. You must always reference the
+current version of this documentation on the branch nightly before using the
+operations or behavior documented within. Any new files should contain the
+above warning.
diff --git a/stdlib/docs/internal/mlir.md b/stdlib/docs/internal/mlir.md
new file mode 100644
index 0000000000..ca0c174c4b
--- /dev/null
+++ b/stdlib/docs/internal/mlir.md
@@ -0,0 +1,10 @@
+## WARNING
+
+Everything in this file is subject to revision on any bugfix or security
+update. We (the stdlib team and contributors), reserve the right to remove,
+change the API contracts of, rename, or cause to instantly crash the program,
+any operation described in here. These are **PRIVATE** APIs and implementation
+details for the Mojo stdlib and for MAX to use. **WE WILL CHANGE IT WHENEVER
+WE FIND IT CONVENIENT TO DO SO WITHOUT WARNING OR NOTICE**.
+
+## MLIR Documentation
diff --git a/stdlib/docs/internal/runtime.md b/stdlib/docs/internal/runtime.md
new file mode 100644
index 0000000000..6d4921138b
--- /dev/null
+++ b/stdlib/docs/internal/runtime.md
@@ -0,0 +1,10 @@
+## WARNING
+
+Everything in this file is subject to revision on any bugfix or security
+update. We (the stdlib team and contributors), reserve the right to remove,
+change the API contracts of, rename, or cause to instantly crash the program,
+any operation described in here. These are **PRIVATE** APIs and implementation
+details for the Mojo stdlib and for MAX to use. **WE WILL CHANGE IT WHENEVER
+WE FIND IT CONVENIENT TO DO SO WITHOUT WARNING OR NOTICE**.
+
+## Runtime Documentation
diff --git a/stdlib/docs/style-guide.md b/stdlib/docs/style-guide.md
index f1c135cf4f..82002c152c 100644
--- a/stdlib/docs/style-guide.md
+++ b/stdlib/docs/style-guide.md
@@ -111,9 +111,9 @@ structure of header comments separating the various kinds of methods that can be
defined on structs.
```mojo
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# MyStruct
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
struct MyStruct(Sized, Stringable):
@@ -283,7 +283,7 @@ the same type:
```mojo
struct MyStruct:
# Invoked as `MyStruct(other)`
- fn __init__(inout self, other: Self):
+ fn __init__(out self, other: Self):
# do a deep copy of MyStruct
```
diff --git a/stdlib/scripts/check-docstrings.py b/stdlib/scripts/check-docstrings.py
index eb4b180125..cdd5b02f98 100644
--- a/stdlib/scripts/check-docstrings.py
+++ b/stdlib/scripts/check-docstrings.py
@@ -31,7 +31,7 @@ def main():
]
result = subprocess.run(command, capture_output=True)
if result.stderr or result.returncode != 0:
- print(f"Docstring issue found in the stdlib: ")
+ print("Docstring issue found in the stdlib: ")
print(result.stderr.decode())
sys.exit(1)
diff --git a/stdlib/src/base64/_b64encode.mojo b/stdlib/src/base64/_b64encode.mojo
index d867a91be5..74b8c31501 100644
--- a/stdlib/src/base64/_b64encode.mojo
+++ b/stdlib/src/base64/_b64encode.mojo
@@ -24,10 +24,12 @@ Instructions, ACM Transactions on the Web 12 (3), 2018.
https://arxiv.org/abs/1704.00605
"""
-from builtin.simd import _sub_with_saturation
from collections import InlineArray
from math.math import _compile_time_iota
-from memory import memcpy, bitcast, UnsafePointer
+from sys import llvm_intrinsic
+
+from memory import UnsafePointer, bitcast, memcpy
+
from utils import IndexList
alias Bytes = SIMD[DType.uint8, _]
@@ -211,7 +213,7 @@ fn store_incomplete_simd[
# TODO: Use Span instead of List as input when Span is easier to use
@no_inline
fn b64encode_with_buffers(
- input_bytes: List[UInt8, _], inout result: List[UInt8, _]
+ input_bytes: List[UInt8, _], mut result: List[UInt8, _]
):
alias simd_width = sys.simdbytewidth()
alias input_simd_width = simd_width * 3 // 4
@@ -291,3 +293,13 @@ fn _rshift_bits_in_u16[shift: Int](input: Bytes) -> __type_of(input):
var u16 = bitcast[DType.uint16, input.size // 2](input)
var res = bit.rotate_bits_right[shift](u16)
return bitcast[DType.uint8, input.size](res)
+
+
+@always_inline
+fn _sub_with_saturation[
+ width: Int, //
+](a: SIMD[DType.uint8, width], b: SIMD[DType.uint8, width]) -> SIMD[
+ DType.uint8, width
+]:
+ # generates a single `vpsubusb` on x86 with AVX
+ return llvm_intrinsic["llvm.usub.sat", __type_of(a)](a, b)
diff --git a/stdlib/src/base64/base64.mojo b/stdlib/src/base64/base64.mojo
index 0bf4f2a3b9..6a9d585fb5 100644
--- a/stdlib/src/base64/base64.mojo
+++ b/stdlib/src/base64/base64.mojo
@@ -21,12 +21,14 @@ from base64 import b64encode
from collections import List
from sys import simdwidthof
+
import bit
+
from ._b64encode import b64encode_with_buffers as _b64encode_with_buffers
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Utilities
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -57,13 +59,13 @@ fn _ascii_to_value(char: String) -> Int:
return -1
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# b64encode
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# TODO: Use Span instead of List as input when Span is easier to use
-fn b64encode(input_bytes: List[UInt8, _], inout result: List[UInt8, _]):
+fn b64encode(input_bytes: List[UInt8, _], mut result: List[UInt8, _]):
"""Performs base64 encoding on the input string.
Args:
@@ -104,9 +106,9 @@ fn b64encode(input_bytes: List[UInt8, _]) -> String:
return String(result^)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# b64decode
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -151,9 +153,9 @@ fn b64decode(str: String) -> String:
return p
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# b16encode
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
fn b16encode(str: String) -> String:
@@ -188,9 +190,9 @@ fn b16encode(str: String) -> String:
return String(out^)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# b16decode
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
diff --git a/stdlib/src/bit/__init__.mojo b/stdlib/src/bit/__init__.mojo
index e41c3ca52c..75004d3618 100644
--- a/stdlib/src/bit/__init__.mojo
+++ b/stdlib/src/bit/__init__.mojo
@@ -21,6 +21,7 @@ from .bit import (
byte_swap,
count_leading_zeros,
count_trailing_zeros,
+ log2_floor,
is_power_of_two,
pop_count,
rotate_bits_left,
diff --git a/stdlib/src/bit/bit.mojo b/stdlib/src/bit/bit.mojo
index 5405411ab1..fb4170f825 100644
--- a/stdlib/src/bit/bit.mojo
+++ b/stdlib/src/bit/bit.mojo
@@ -22,9 +22,9 @@ from bit import count_leading_zeros
from sys import llvm_intrinsic, sizeof
from sys.info import bitwidthof
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# count_leading_zeros
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
@@ -66,9 +66,9 @@ fn count_leading_zeros[
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# count_trailing_zeros
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
@@ -110,9 +110,9 @@ fn count_trailing_zeros[
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# bit_reverse
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
@@ -154,9 +154,9 @@ fn bit_reverse[
](val)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# byte_swap
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
@@ -212,9 +212,9 @@ fn byte_swap[
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# pop_count
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
@@ -256,9 +256,9 @@ fn pop_count[
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# bit_not
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -286,9 +286,9 @@ fn bit_not[
return __mlir_op.`pop.simd.xor`(val.value, neg_one.value)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# bit_width
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -343,10 +343,30 @@ fn bit_width[
return bitwidth - leading_zero
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
+# log2_floor
+# ===-----------------------------------------------------------------------===#
+
+
+@always_inline
+fn log2_floor(val: Int) -> Int:
+ """Returns the floor of the base-2 logarithm of an integer value.
+
+ Args:
+ val: The input value.
+
+ Returns:
+ The floor of the base-2 logarithm of the input value, which is equal to
+ the position of the highest set bit. Returns -1 if val is 0.
+ """
+ if val <= 1:
+ return 0
+ return bitwidthof[Int]() - count_leading_zeros(val) - 1
+
+
+# ===-----------------------------------------------------------------------===#
# is_power_of_two
-# ===----------------------------------------------------------------------===#
-# reference: https://en.cppreference.com/w/cpp/numeric/has_single_bit
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -391,9 +411,9 @@ fn is_power_of_two[
return (val > 0) & (val & (val - 1) == 0)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# bit_ceil
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# reference: https://en.cppreference.com/w/cpp/numeric/bit_ceil
@@ -447,9 +467,9 @@ fn bit_ceil[
return (val > 1).select(1 << bit_width(val - ones), ones)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# bit_floor
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# reference: https://en.cppreference.com/w/cpp/numeric/bit_floor
@@ -500,9 +520,9 @@ fn bit_floor[
return (val > 0).select(1 << (bit_width(val) - 1), zeros)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# rotate_bits_left
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -578,9 +598,9 @@ fn rotate_bits_left[
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# rotate_bits_right
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
diff --git a/stdlib/src/builtin/_format_float.mojo b/stdlib/src/builtin/_format_float.mojo
index 2686917119..95d7e8a30e 100644
--- a/stdlib/src/builtin/_format_float.mojo
+++ b/stdlib/src/builtin/_format_float.mojo
@@ -25,10 +25,12 @@
# ===----------------------------------------------------------------------=== #
from collections import InlineArray
from math import log2
-from memory import bitcast
from sys.info import sizeof
-from utils import StaticTuple, Span
+
from builtin.io import _printf
+from memory import bitcast, Span
+
+from utils import StaticTuple
from utils.numerics import FPUtils, isinf, isnan
@@ -38,7 +40,7 @@ struct _UInt128:
var high: UInt64
var low: UInt64
- fn __iadd__(inout self, n: UInt64):
+ fn __iadd__(mut self, n: UInt64):
var sum = (self.low + n) & UInt64.MAX
self.high += 1 if sum < self.low else 0
self.low = sum
@@ -69,9 +71,8 @@ struct FP[type: DType, CarrierDType: DType = FPUtils[type].uint_type]:
alias carrier_bits = sizeof[Self.CarrierDType]() * 8
alias sig_bits = FPUtils[type].mantissa_width()
alias exp_bits = FPUtils[type].exponent_width()
- alias min_exponent = FPUtils[type].min_exponent()
- alias max_exponent = FPUtils[type].max_exponent()
- alias exp_bias = -Self.max_exponent
+ alias neg_exp_bias = -FPUtils[type].exponent_bias()
+ alias min_normal_exp = Self.neg_exp_bias + 1
alias cache_bits = 64 if Self.CarrierDType == DType.uint32 else 128
alias min_k = -31 if Self.CarrierDType == DType.uint32 else -292
alias max_k = 46 if Self.CarrierDType == DType.uint32 else 326
@@ -87,9 +88,7 @@ struct FP[type: DType, CarrierDType: DType = FPUtils[type].uint_type]:
alias small_divisor = pow(10, Self.kappa)
-fn _write_float[
- W: Writer, type: DType, //
-](inout writer: W, value: Scalar[type]):
+fn _write_float[W: Writer, type: DType, //](mut writer: W, value: Scalar[type]):
"""Write a SIMD float type into a Writer, using the dragonbox algorithm for
perfect roundtrip, shortest representable format, and high performance.
Paper: https://github.com/jk-jeon/dragonbox/blob/master/other_files/Dragonbox.pdf
@@ -105,117 +104,128 @@ fn _write_float[
"""
constrained[type.is_floating_point()]()
- # Currently only specialized for float32 and float64, upcast anything else
- # to float32
- casted = value.cast[
- DType.float64 if type == DType.float64 else DType.float32
- ]()
+ @parameter
+ if type is DType.float8e5m2:
+ return writer.write(float8e5m2_to_str[int(bitcast[DType.uint8](value))])
+ elif type is DType.float8e4m3:
+ return writer.write(float8e4m3_to_str[int(bitcast[DType.uint8](value))])
+ elif type is DType.float8e5m2fnuz:
+ return writer.write(
+ float8e5m2fnuz_to_str[int(bitcast[DType.uint8](value))]
+ )
+ elif type is DType.float8e4m3fnuz:
+ return writer.write(
+ float8e4m3fnuz_to_str[int(bitcast[DType.uint8](value))]
+ )
+ else:
+ # Upcast the float16 types to float32
+ casted = value.cast[
+ DType.float64 if type == DType.float64 else DType.float32
+ ]()
+
+ # Bitcast the float and separate the sig and exp, to enable manipulating
+ # bits as a UInt64 and Int:
+ # - The significand (sig) is the raw binary fraction
+ # - The exponent (exp) is still in biased form
+ var sig = FPUtils.get_mantissa_uint(casted)
+ var exp = FPUtils.get_exponent_biased(casted)
+ var sign = FPUtils.get_sign(casted)
- # Bitcast the float and separate the sig and exp, to enable manipulating
- # bits as a UInt64 and Int:
- # - The significand (sig) is the raw binary fraction
- # - The exponent (exp) is still in biased form
- var sig = FPUtils.get_mantissa_uint(casted)
- var exp = FPUtils.get_exponent_without_bias(casted)
- var sign = FPUtils.get_sign(casted)
+ if isinf(value):
+ if sign:
+ return writer.write("-inf")
+ return writer.write("inf")
+
+ if isnan(value):
+ return writer.write("nan")
- if isinf(value):
if sign:
writer.write("-")
- writer.write("inf")
- return
-
- if isnan(value):
- writer.write("nan")
- return
-
- if sign:
- writer.write("-")
-
- if not sig and not exp:
- writer.write("0.0")
- return
-
- # Convert the binary components to a decimal representation:
- # - The raw binary sig into a decimal sig
- # - The biased binary exp into a decimal power of 10 exp
- # This does all the heavy lifting for perfect roundtrip, shortest
- # representable format, bankers rounding etc.
- _to_decimal[casted.type](sig, exp)
-
- # This is a custom routine for writing the decimal following python behavior.
- # it can be further optimized with a lookup table, there is overhead here
- # compared to snprintf.
- var orig_sig = sig
- var abs_exp = abs(exp)
- var digits = StaticTuple[Byte, 21]()
- var idx = 0
- while sig > 0:
- digits[idx] = (sig % 10).cast[DType.uint8]()
- sig //= 10
- idx += 1
- if sig > 0:
- exp += 1
- var leading_zeroes = abs_exp - idx
-
- # Write in scientific notation if < 0.0001 or exp > 15
- if (exp < 0 and leading_zeroes > 3) or exp > 15:
- # Handle single digit case
- if orig_sig < 10:
- writer.write(orig_sig)
- else:
- # Write digit before decimal point
- writer.write(digits[idx - 1])
- writer.write(".")
- # Write digits after decimal point
- for i in reversed(range(idx - 1)):
- writer.write(digits[i])
- # Write exponent
- if exp < 0:
- writer.write("e-")
- exp = -exp
- else:
- writer.write("e+")
- # Pad exponent with a 0 if less than two digits
- if exp < 10:
- writer.write("0")
- var exp_digits = StaticTuple[Byte, 10]()
- var exp_idx = 0
- while exp > 0:
- exp_digits[exp_idx] = exp % 10
- exp //= 10
- exp_idx += 1
- for i in reversed(range(exp_idx)):
- writer.write(exp_digits[i])
- # If between 0 and 0.0001
- elif exp < 0 and leading_zeroes > 0:
- writer.write("0.")
- for _ in range(leading_zeroes):
- writer.write("0")
- for i in reversed(range(idx)):
- writer.write(digits[i])
- # All other floats > 0.0001 with an exponent <= 15
- else:
- var point_written = False
- for i in reversed(range(idx)):
- if leading_zeroes < 1 and exp == idx - i - 2:
- # No integer part so write leading 0
- if i == idx - 1:
- writer.write("0")
- writer.write(".")
- point_written = True
- writer.write(digits[i])
- # If exp - idx + 1 > 0 it's a positive number with more 0's than the sig
- for _ in range(exp - idx + 1):
- writer.write("0")
- if not point_written:
- writer.write(".0")
+ if not sig and not exp:
+ return writer.write("0.0")
+
+ # Convert the binary components to a decimal representation:
+ # - The raw binary sig into a decimal sig
+ # - The biased binary exp into a decimal power of 10 exp
+ # This does all the heavy lifting for perfect roundtrip, shortest
+ # representable format, bankers rounding etc.
+ _to_decimal[casted.type](sig, exp)
+
+ # This is a custom routine for writing the decimal following python
+ # behavior. it can be further optimized with a lookup table, there is
+ # overhead here compared to snprintf.
+ var orig_sig = sig
+ var abs_exp = abs(exp)
+ var digits = StaticTuple[Byte, 21]()
+ var idx = 0
+ while sig > 0:
+ digits[idx] = (sig % 10).cast[DType.uint8]()
+ sig //= 10
+ idx += 1
+ if sig > 0:
+ exp += 1
+ var leading_zeroes = abs_exp - idx
+
+ # Write in scientific notation if < 0.0001 or exp > 15
+ if (exp < 0 and leading_zeroes > 3) or exp > 15:
+ # Handle single digit case
+ if orig_sig < 10:
+ writer.write(orig_sig)
+ else:
+ # Write digit before decimal point
+ writer.write(digits[idx - 1])
+ writer.write(".")
+ # Write digits after decimal point
+ for i in reversed(range(idx - 1)):
+ writer.write(digits[i])
+ # Write exponent
+ if exp < 0:
+ writer.write("e-")
+ exp = -exp
+ else:
+ writer.write("e+")
+ # Pad exponent with a 0 if less than two digits
+ if exp < 10:
+ writer.write("0")
+ var exp_digits = StaticTuple[Byte, 10]()
+ var exp_idx = 0
+ while exp > 0:
+ exp_digits[exp_idx] = exp % 10
+ exp //= 10
+ exp_idx += 1
+ for i in reversed(range(exp_idx)):
+ writer.write(exp_digits[i])
+ # If between 0 and 0.0001
+ elif exp < 0 and leading_zeroes > 0:
+ writer.write("0.")
+ for _ in range(leading_zeroes):
+ writer.write("0")
+ for i in reversed(range(idx)):
+ writer.write(digits[i])
+ # All other floats > 0.0001 with an exponent <= 15
+ else:
+ var point_written = False
+ for i in reversed(range(idx)):
+ if leading_zeroes < 1 and exp == idx - i - 2:
+ # No integer part so write leading 0
+ if i == idx - 1:
+ writer.write("0")
+ writer.write(".")
+ point_written = True
+ writer.write(digits[i])
+
+ # If exp - idx + 1 > 0 it's a positive number with more 0's than the
+ # sig
+ for _ in range(exp - idx + 1):
+ writer.write("0")
+ if not point_written:
+ writer.write(".0")
fn _to_decimal[
CarrierDType: DType, //, type: DType
-](inout sig: Scalar[CarrierDType], inout exp: Int):
+](mut sig: Scalar[CarrierDType], mut exp: Int):
"""Transform the raw binary significand to decimal significand,
and biased binary exponent into a decimal power of 10 exponent.
"""
@@ -224,7 +234,7 @@ fn _to_decimal[
# For normal numbers
if binary_exp != 0:
- binary_exp += FP[type].exp_bias - FP[type].sig_bits
+ binary_exp += FP[type].neg_exp_bias - FP[type].sig_bits
if two_fc == 0:
var minus_k = (binary_exp * 631305 - 261663) >> 21
var beta = binary_exp + _floor_log2_pow10(-minus_k)
@@ -282,7 +292,7 @@ fn _to_decimal[
two_fc |= Scalar[CarrierDType](1) << (FP[type].sig_bits + 1)
else:
# For subnormal numbers
- binary_exp = FP[type].min_exponent - FP[type].sig_bits
+ binary_exp = FP[type].min_normal_exp - FP[type].sig_bits
##########################################
# Step 1: Schubfach multiplier calculation
@@ -368,7 +378,7 @@ fn _compute_endpoint[
CarrierDType: DType, sig_bits: Int, total_bits: Int, cache_bits: Int
](cache_index: Int, beta: Int, left_endpoint: Bool) -> Scalar[CarrierDType]:
@parameter
- if CarrierDType == DType.uint64:
+ if CarrierDType is DType.uint64:
var cache = cache_f64[cache_index]
if left_endpoint:
return (
@@ -405,9 +415,9 @@ fn _print_bits[type: DType](x: Scalar[type]) -> String:
if i % 8 == 0:
output.write(" ")
else:
- alias sig_bits = 23 if type == DType.float32 else 52
- alias exp_bits = 8 if type == DType.float32 else 11
- alias cast_type = DType.uint32 if type == DType.float32 else DType.uint64
+ alias sig_bits = 23 if type is DType.float32 else 52
+ alias exp_bits = 8 if type is DType.float32 else 11
+ alias cast_type = DType.uint32 if type is DType.float32 else DType.uint64
var casted = bitcast[cast_type](x)
for i in reversed(range(total_bits)):
output.write((casted >> i) & 1)
@@ -433,7 +443,7 @@ fn _rotr[
CarrierDType: DType
](n: Scalar[CarrierDType], r: Scalar[CarrierDType]) -> Scalar[CarrierDType]:
@parameter
- if CarrierDType == DType.uint32:
+ if CarrierDType is DType.uint32:
var r_masked = r & 31
return (n >> r_masked) | (n << ((32 - r_masked) & 31))
else:
@@ -487,13 +497,13 @@ fn _umul128[
fn _remove_trailing_zeros[
CarrierDType: DType
-](inout sig: Scalar[CarrierDType], inout exp: Int):
+](mut sig: Scalar[CarrierDType], mut exp: Int):
"""Fastest alg for removing trailing zeroes:
https://github.com/jk-jeon/rtz_benchmark.
"""
@parameter
- if CarrierDType == DType.uint64:
+ if CarrierDType is DType.uint64:
var r = _rotr(sig * 28999941890838049, 8)
var b = r < 184467440738
var s = int(b)
@@ -545,7 +555,7 @@ fn _divide_by_pow10[
CarrierDType: DType, //, N: Int, n_max: Scalar[CarrierDType]
](n: Scalar[CarrierDType]) -> Scalar[CarrierDType]:
@parameter
- if CarrierDType == DType.uint64:
+ if CarrierDType is DType.uint64:
@parameter
if N == 1 and bool(n_max <= 4611686018427387908):
@@ -581,7 +591,7 @@ fn _umul192_lower128(x: UInt64, y: _UInt128) -> _UInt128:
fn _compute_mul_parity[
CarrierDType: DType
](two_f: Scalar[CarrierDType], cache_index: Int, beta: Int) -> _MulParity:
- if CarrierDType == DType.uint64:
+ if CarrierDType is DType.uint64:
debug_assert(1 <= beta < 64, "beta must be between 1 and 64")
var r = _umul192_lower128(
two_f.cast[DType.uint64](), cache_f64[cache_index]
@@ -616,7 +626,7 @@ fn _check_divisibility_and_divide_by_pow10[
CarrierDType: DType, //,
carrier_bits: Int,
divide_magic_number: StaticTuple[UInt32, 2],
-](inout n: Scalar[CarrierDType], N: Int) -> Bool:
+](mut n: Scalar[CarrierDType], N: Int) -> Bool:
# Make sure the computation for max_n does not overflow.
debug_assert(N + 1 <= _floor_log10_pow2(carrier_bits))
@@ -653,7 +663,7 @@ fn _umul96_upper64[
fn _compute_mul[
CarrierDType: DType
](u: Scalar[CarrierDType], cache_index: Int) -> _MulResult[CarrierDType]:
- if CarrierDType == DType.uint64:
+ if CarrierDType is DType.uint64:
var r = _umul192_upper128(u, cache_f64[cache_index])
return _MulResult[CarrierDType](r.high.cast[CarrierDType](), r.low == 0)
else:
@@ -667,7 +677,7 @@ fn _compute_mul[
fn _compute_delta[
CarrierDType: DType, total_bits: Int, cache_bits: Int
](cache_index: Int, beta: Int) -> Scalar[CarrierDType]:
- if CarrierDType == DType.uint64:
+ if CarrierDType is DType.uint64:
var cache = cache_f64[cache_index]
return (cache.high >> (total_bits - 1 - beta)).cast[CarrierDType]()
else:
@@ -722,7 +732,7 @@ fn _count_factors[
fn _compute_round_up_for_shorter_interval_case[
CarrierDType: DType, total_bits: Int, sig_bits: Int, cache_bits: Int
](cache_index: Int, beta: Int) -> Scalar[CarrierDType]:
- if CarrierDType == DType.uint64:
+ if CarrierDType is DType.uint64:
var cache = cache_f64[cache_index]
return (
(
@@ -1426,3 +1436,1039 @@ alias cache_f64 = StaticTuple[_UInt128, 619](
_UInt128(0xC5A05277621BE293, 0xC7098B7305241886),
_UInt128(0xF70867153AA2DB38, 0xB8CBEE4FC66D1EA8),
)
+
+alias float8e5m2_to_str = StaticTuple[StringLiteral, 256](
+ "0.0",
+ "1.52587890625e-05",
+ "3.0517578125e-05",
+ "4.57763671875e-05",
+ "6.103515625e-05",
+ "7.62939453125e-05",
+ "9.1552734375e-05",
+ "0.0001068115234375",
+ "0.0001220703125",
+ "0.000152587890625",
+ "0.00018310546875",
+ "0.000213623046875",
+ "0.000244140625",
+ "0.00030517578125",
+ "0.0003662109375",
+ "0.00042724609375",
+ "0.00048828125",
+ "0.0006103515625",
+ "0.000732421875",
+ "0.0008544921875",
+ "0.0009765625",
+ "0.001220703125",
+ "0.00146484375",
+ "0.001708984375",
+ "0.001953125",
+ "0.00244140625",
+ "0.0029296875",
+ "0.00341796875",
+ "0.00390625",
+ "0.0048828125",
+ "0.005859375",
+ "0.0068359375",
+ "0.0078125",
+ "0.009765625",
+ "0.01171875",
+ "0.013671875",
+ "0.015625",
+ "0.01953125",
+ "0.0234375",
+ "0.02734375",
+ "0.03125",
+ "0.0390625",
+ "0.046875",
+ "0.0546875",
+ "0.0625",
+ "0.078125",
+ "0.09375",
+ "0.109375",
+ "0.125",
+ "0.15625",
+ "0.1875",
+ "0.21875",
+ "0.25",
+ "0.3125",
+ "0.375",
+ "0.4375",
+ "0.5",
+ "0.625",
+ "0.75",
+ "0.875",
+ "1.0",
+ "1.25",
+ "1.5",
+ "1.75",
+ "2.0",
+ "2.5",
+ "3.0",
+ "3.5",
+ "4.0",
+ "5.0",
+ "6.0",
+ "7.0",
+ "8.0",
+ "10.0",
+ "12.0",
+ "14.0",
+ "16.0",
+ "20.0",
+ "24.0",
+ "28.0",
+ "32.0",
+ "40.0",
+ "48.0",
+ "56.0",
+ "64.0",
+ "80.0",
+ "96.0",
+ "112.0",
+ "128.0",
+ "160.0",
+ "192.0",
+ "224.0",
+ "256.0",
+ "320.0",
+ "384.0",
+ "448.0",
+ "512.0",
+ "640.0",
+ "768.0",
+ "896.0",
+ "1024.0",
+ "1280.0",
+ "1536.0",
+ "1792.0",
+ "2048.0",
+ "2560.0",
+ "3072.0",
+ "3584.0",
+ "4096.0",
+ "5120.0",
+ "6144.0",
+ "7168.0",
+ "8192.0",
+ "10240.0",
+ "12288.0",
+ "14336.0",
+ "16384.0",
+ "20480.0",
+ "24576.0",
+ "28672.0",
+ "32768.0",
+ "40960.0",
+ "49152.0",
+ "57344.0",
+ "inf",
+ "nan",
+ "nan",
+ "nan",
+ "-0.0",
+ "-1.52587890625e-05",
+ "-3.0517578125e-05",
+ "-4.57763671875e-05",
+ "-6.103515625e-05",
+ "-7.62939453125e-05",
+ "-9.1552734375e-05",
+ "-0.0001068115234375",
+ "-0.0001220703125",
+ "-0.000152587890625",
+ "-0.00018310546875",
+ "-0.000213623046875",
+ "-0.000244140625",
+ "-0.00030517578125",
+ "-0.0003662109375",
+ "-0.00042724609375",
+ "-0.00048828125",
+ "-0.0006103515625",
+ "-0.000732421875",
+ "-0.0008544921875",
+ "-0.0009765625",
+ "-0.001220703125",
+ "-0.00146484375",
+ "-0.001708984375",
+ "-0.001953125",
+ "-0.00244140625",
+ "-0.0029296875",
+ "-0.00341796875",
+ "-0.00390625",
+ "-0.0048828125",
+ "-0.005859375",
+ "-0.0068359375",
+ "-0.0078125",
+ "-0.009765625",
+ "-0.01171875",
+ "-0.013671875",
+ "-0.015625",
+ "-0.01953125",
+ "-0.0234375",
+ "-0.02734375",
+ "-0.03125",
+ "-0.0390625",
+ "-0.046875",
+ "-0.0546875",
+ "-0.0625",
+ "-0.078125",
+ "-0.09375",
+ "-0.109375",
+ "-0.125",
+ "-0.15625",
+ "-0.1875",
+ "-0.21875",
+ "-0.25",
+ "-0.3125",
+ "-0.375",
+ "-0.4375",
+ "-0.5",
+ "-0.625",
+ "-0.75",
+ "-0.875",
+ "-1.0",
+ "-1.25",
+ "-1.5",
+ "-1.75",
+ "-2.0",
+ "-2.5",
+ "-3.0",
+ "-3.5",
+ "-4.0",
+ "-5.0",
+ "-6.0",
+ "-7.0",
+ "-8.0",
+ "-10.0",
+ "-12.0",
+ "-14.0",
+ "-16.0",
+ "-20.0",
+ "-24.0",
+ "-28.0",
+ "-32.0",
+ "-40.0",
+ "-48.0",
+ "-56.0",
+ "-64.0",
+ "-80.0",
+ "-96.0",
+ "-112.0",
+ "-128.0",
+ "-160.0",
+ "-192.0",
+ "-224.0",
+ "-256.0",
+ "-320.0",
+ "-384.0",
+ "-448.0",
+ "-512.0",
+ "-640.0",
+ "-768.0",
+ "-896.0",
+ "-1024.0",
+ "-1280.0",
+ "-1536.0",
+ "-1792.0",
+ "-2048.0",
+ "-2560.0",
+ "-3072.0",
+ "-3584.0",
+ "-4096.0",
+ "-5120.0",
+ "-6144.0",
+ "-7168.0",
+ "-8192.0",
+ "-10240.0",
+ "-12288.0",
+ "-14336.0",
+ "-16384.0",
+ "-20480.0",
+ "-24576.0",
+ "-28672.0",
+ "-32768.0",
+ "-40960.0",
+ "-49152.0",
+ "-57344.0",
+ "-inf",
+ "nan",
+ "nan",
+ "nan",
+)
+
+alias float8e4m3_to_str = StaticTuple[StringLiteral, 256](
+ "0.0",
+ "0.001953125",
+ "0.00390625",
+ "0.005859375",
+ "0.0078125",
+ "0.009765625",
+ "0.01171875",
+ "0.013671875",
+ "0.015625",
+ "0.017578125",
+ "0.01953125",
+ "0.021484375",
+ "0.0234375",
+ "0.025390625",
+ "0.02734375",
+ "0.029296875",
+ "0.03125",
+ "0.03515625",
+ "0.0390625",
+ "0.04296875",
+ "0.046875",
+ "0.05078125",
+ "0.0546875",
+ "0.05859375",
+ "0.0625",
+ "0.0703125",
+ "0.078125",
+ "0.0859375",
+ "0.09375",
+ "0.1015625",
+ "0.109375",
+ "0.1171875",
+ "0.125",
+ "0.140625",
+ "0.15625",
+ "0.171875",
+ "0.1875",
+ "0.203125",
+ "0.21875",
+ "0.234375",
+ "0.25",
+ "0.28125",
+ "0.3125",
+ "0.34375",
+ "0.375",
+ "0.40625",
+ "0.4375",
+ "0.46875",
+ "0.5",
+ "0.5625",
+ "0.625",
+ "0.6875",
+ "0.75",
+ "0.8125",
+ "0.875",
+ "0.9375",
+ "1.0",
+ "1.125",
+ "1.25",
+ "1.375",
+ "1.5",
+ "1.625",
+ "1.75",
+ "1.875",
+ "2.0",
+ "2.25",
+ "2.5",
+ "2.75",
+ "3.0",
+ "3.25",
+ "3.5",
+ "3.75",
+ "4.0",
+ "4.5",
+ "5.0",
+ "5.5",
+ "6.0",
+ "6.5",
+ "7.0",
+ "7.5",
+ "8.0",
+ "9.0",
+ "10.0",
+ "11.0",
+ "12.0",
+ "13.0",
+ "14.0",
+ "15.0",
+ "16.0",
+ "18.0",
+ "20.0",
+ "22.0",
+ "24.0",
+ "26.0",
+ "28.0",
+ "30.0",
+ "32.0",
+ "36.0",
+ "40.0",
+ "44.0",
+ "48.0",
+ "52.0",
+ "56.0",
+ "60.0",
+ "64.0",
+ "72.0",
+ "80.0",
+ "88.0",
+ "96.0",
+ "104.0",
+ "112.0",
+ "120.0",
+ "128.0",
+ "144.0",
+ "160.0",
+ "176.0",
+ "192.0",
+ "208.0",
+ "224.0",
+ "240.0",
+ "256.0",
+ "288.0",
+ "320.0",
+ "352.0",
+ "384.0",
+ "416.0",
+ "448.0",
+ "nan",
+ "-0.0",
+ "-0.001953125",
+ "-0.00390625",
+ "-0.005859375",
+ "-0.0078125",
+ "-0.009765625",
+ "-0.01171875",
+ "-0.013671875",
+ "-0.015625",
+ "-0.017578125",
+ "-0.01953125",
+ "-0.021484375",
+ "-0.0234375",
+ "-0.025390625",
+ "-0.02734375",
+ "-0.029296875",
+ "-0.03125",
+ "-0.03515625",
+ "-0.0390625",
+ "-0.04296875",
+ "-0.046875",
+ "-0.05078125",
+ "-0.0546875",
+ "-0.05859375",
+ "-0.0625",
+ "-0.0703125",
+ "-0.078125",
+ "-0.0859375",
+ "-0.09375",
+ "-0.1015625",
+ "-0.109375",
+ "-0.1171875",
+ "-0.125",
+ "-0.140625",
+ "-0.15625",
+ "-0.171875",
+ "-0.1875",
+ "-0.203125",
+ "-0.21875",
+ "-0.234375",
+ "-0.25",
+ "-0.28125",
+ "-0.3125",
+ "-0.34375",
+ "-0.375",
+ "-0.40625",
+ "-0.4375",
+ "-0.46875",
+ "-0.5",
+ "-0.5625",
+ "-0.625",
+ "-0.6875",
+ "-0.75",
+ "-0.8125",
+ "-0.875",
+ "-0.9375",
+ "-1.0",
+ "-1.125",
+ "-1.25",
+ "-1.375",
+ "-1.5",
+ "-1.625",
+ "-1.75",
+ "-1.875",
+ "-2.0",
+ "-2.25",
+ "-2.5",
+ "-2.75",
+ "-3.0",
+ "-3.25",
+ "-3.5",
+ "-3.75",
+ "-4.0",
+ "-4.5",
+ "-5.0",
+ "-5.5",
+ "-6.0",
+ "-6.5",
+ "-7.0",
+ "-7.5",
+ "-8.0",
+ "-9.0",
+ "-10.0",
+ "-11.0",
+ "-12.0",
+ "-13.0",
+ "-14.0",
+ "-15.0",
+ "-16.0",
+ "-18.0",
+ "-20.0",
+ "-22.0",
+ "-24.0",
+ "-26.0",
+ "-28.0",
+ "-30.0",
+ "-32.0",
+ "-36.0",
+ "-40.0",
+ "-44.0",
+ "-48.0",
+ "-52.0",
+ "-56.0",
+ "-60.0",
+ "-64.0",
+ "-72.0",
+ "-80.0",
+ "-88.0",
+ "-96.0",
+ "-104.0",
+ "-112.0",
+ "-120.0",
+ "-128.0",
+ "-144.0",
+ "-160.0",
+ "-176.0",
+ "-192.0",
+ "-208.0",
+ "-224.0",
+ "-240.0",
+ "-256.0",
+ "-288.0",
+ "-320.0",
+ "-352.0",
+ "-384.0",
+ "-416.0",
+ "-448.0",
+ "nan",
+)
+
+alias float8e5m2fnuz_to_str = StaticTuple[StringLiteral, 256](
+ "0.0",
+ "7.62939453125e-06",
+ "1.52587890625e-05",
+ "2.288818359375e-05",
+ "3.0517578125e-05",
+ "3.814697265625e-05",
+ "4.57763671875e-05",
+ "5.340576171875e-05",
+ "6.103515625e-05",
+ "7.62939453125e-05",
+ "9.1552734375e-05",
+ "0.0001068115234375",
+ "0.0001220703125",
+ "0.000152587890625",
+ "0.00018310546875",
+ "0.000213623046875",
+ "0.000244140625",
+ "0.00030517578125",
+ "0.0003662109375",
+ "0.00042724609375",
+ "0.00048828125",
+ "0.0006103515625",
+ "0.000732421875",
+ "0.0008544921875",
+ "0.0009765625",
+ "0.001220703125",
+ "0.00146484375",
+ "0.001708984375",
+ "0.001953125",
+ "0.00244140625",
+ "0.0029296875",
+ "0.00341796875",
+ "0.00390625",
+ "0.0048828125",
+ "0.005859375",
+ "0.0068359375",
+ "0.0078125",
+ "0.009765625",
+ "0.01171875",
+ "0.013671875",
+ "0.015625",
+ "0.01953125",
+ "0.0234375",
+ "0.02734375",
+ "0.03125",
+ "0.0390625",
+ "0.046875",
+ "0.0546875",
+ "0.0625",
+ "0.078125",
+ "0.09375",
+ "0.109375",
+ "0.125",
+ "0.15625",
+ "0.1875",
+ "0.21875",
+ "0.25",
+ "0.3125",
+ "0.375",
+ "0.4375",
+ "0.5",
+ "0.625",
+ "0.75",
+ "0.875",
+ "1.0",
+ "1.25",
+ "1.5",
+ "1.75",
+ "2.0",
+ "2.5",
+ "3.0",
+ "3.5",
+ "4.0",
+ "5.0",
+ "6.0",
+ "7.0",
+ "8.0",
+ "10.0",
+ "12.0",
+ "14.0",
+ "16.0",
+ "20.0",
+ "24.0",
+ "28.0",
+ "32.0",
+ "40.0",
+ "48.0",
+ "56.0",
+ "64.0",
+ "80.0",
+ "96.0",
+ "112.0",
+ "128.0",
+ "160.0",
+ "192.0",
+ "224.0",
+ "256.0",
+ "320.0",
+ "384.0",
+ "448.0",
+ "512.0",
+ "640.0",
+ "768.0",
+ "896.0",
+ "1024.0",
+ "1280.0",
+ "1536.0",
+ "1792.0",
+ "2048.0",
+ "2560.0",
+ "3072.0",
+ "3584.0",
+ "4096.0",
+ "5120.0",
+ "6144.0",
+ "7168.0",
+ "8192.0",
+ "10240.0",
+ "12288.0",
+ "14336.0",
+ "16384.0",
+ "20480.0",
+ "24576.0",
+ "28672.0",
+ "32768.0",
+ "40960.0",
+ "49152.0",
+ "57344.0",
+ "nan",
+ "-7.62939453125e-06",
+ "-1.52587890625e-05",
+ "-2.288818359375e-05",
+ "-3.0517578125e-05",
+ "-3.814697265625e-05",
+ "-4.57763671875e-05",
+ "-5.340576171875e-05",
+ "-6.103515625e-05",
+ "-7.62939453125e-05",
+ "-9.1552734375e-05",
+ "-0.0001068115234375",
+ "-0.0001220703125",
+ "-0.000152587890625",
+ "-0.00018310546875",
+ "-0.000213623046875",
+ "-0.000244140625",
+ "-0.00030517578125",
+ "-0.0003662109375",
+ "-0.00042724609375",
+ "-0.00048828125",
+ "-0.0006103515625",
+ "-0.000732421875",
+ "-0.0008544921875",
+ "-0.0009765625",
+ "-0.001220703125",
+ "-0.00146484375",
+ "-0.001708984375",
+ "-0.001953125",
+ "-0.00244140625",
+ "-0.0029296875",
+ "-0.00341796875",
+ "-0.00390625",
+ "-0.0048828125",
+ "-0.005859375",
+ "-0.0068359375",
+ "-0.0078125",
+ "-0.009765625",
+ "-0.01171875",
+ "-0.013671875",
+ "-0.015625",
+ "-0.01953125",
+ "-0.0234375",
+ "-0.02734375",
+ "-0.03125",
+ "-0.0390625",
+ "-0.046875",
+ "-0.0546875",
+ "-0.0625",
+ "-0.078125",
+ "-0.09375",
+ "-0.109375",
+ "-0.125",
+ "-0.15625",
+ "-0.1875",
+ "-0.21875",
+ "-0.25",
+ "-0.3125",
+ "-0.375",
+ "-0.4375",
+ "-0.5",
+ "-0.625",
+ "-0.75",
+ "-0.875",
+ "-1.0",
+ "-1.25",
+ "-1.5",
+ "-1.75",
+ "-2.0",
+ "-2.5",
+ "-3.0",
+ "-3.5",
+ "-4.0",
+ "-5.0",
+ "-6.0",
+ "-7.0",
+ "-8.0",
+ "-10.0",
+ "-12.0",
+ "-14.0",
+ "-16.0",
+ "-20.0",
+ "-24.0",
+ "-28.0",
+ "-32.0",
+ "-40.0",
+ "-48.0",
+ "-56.0",
+ "-64.0",
+ "-80.0",
+ "-96.0",
+ "-112.0",
+ "-128.0",
+ "-160.0",
+ "-192.0",
+ "-224.0",
+ "-256.0",
+ "-320.0",
+ "-384.0",
+ "-448.0",
+ "-512.0",
+ "-640.0",
+ "-768.0",
+ "-896.0",
+ "-1024.0",
+ "-1280.0",
+ "-1536.0",
+ "-1792.0",
+ "-2048.0",
+ "-2560.0",
+ "-3072.0",
+ "-3584.0",
+ "-4096.0",
+ "-5120.0",
+ "-6144.0",
+ "-7168.0",
+ "-8192.0",
+ "-10240.0",
+ "-12288.0",
+ "-14336.0",
+ "-16384.0",
+ "-20480.0",
+ "-24576.0",
+ "-28672.0",
+ "-32768.0",
+ "-40960.0",
+ "-49152.0",
+ "-57344.0",
+)
+
+alias float8e4m3fnuz_to_str = StaticTuple[StringLiteral, 256](
+ "0.0",
+ "0.0009765625",
+ "0.001953125",
+ "0.0029296875",
+ "0.00390625",
+ "0.0048828125",
+ "0.005859375",
+ "0.0068359375",
+ "0.0078125",
+ "0.0087890625",
+ "0.009765625",
+ "0.0107421875",
+ "0.01171875",
+ "0.0126953125",
+ "0.013671875",
+ "0.0146484375",
+ "0.015625",
+ "0.017578125",
+ "0.01953125",
+ "0.021484375",
+ "0.0234375",
+ "0.025390625",
+ "0.02734375",
+ "0.029296875",
+ "0.03125",
+ "0.03515625",
+ "0.0390625",
+ "0.04296875",
+ "0.046875",
+ "0.05078125",
+ "0.0546875",
+ "0.05859375",
+ "0.0625",
+ "0.0703125",
+ "0.078125",
+ "0.0859375",
+ "0.09375",
+ "0.1015625",
+ "0.109375",
+ "0.1171875",
+ "0.125",
+ "0.140625",
+ "0.15625",
+ "0.171875",
+ "0.1875",
+ "0.203125",
+ "0.21875",
+ "0.234375",
+ "0.25",
+ "0.28125",
+ "0.3125",
+ "0.34375",
+ "0.375",
+ "0.40625",
+ "0.4375",
+ "0.46875",
+ "0.5",
+ "0.5625",
+ "0.625",
+ "0.6875",
+ "0.75",
+ "0.8125",
+ "0.875",
+ "0.9375",
+ "1.0",
+ "1.125",
+ "1.25",
+ "1.375",
+ "1.5",
+ "1.625",
+ "1.75",
+ "1.875",
+ "2.0",
+ "2.25",
+ "2.5",
+ "2.75",
+ "3.0",
+ "3.25",
+ "3.5",
+ "3.75",
+ "4.0",
+ "4.5",
+ "5.0",
+ "5.5",
+ "6.0",
+ "6.5",
+ "7.0",
+ "7.5",
+ "8.0",
+ "9.0",
+ "10.0",
+ "11.0",
+ "12.0",
+ "13.0",
+ "14.0",
+ "15.0",
+ "16.0",
+ "18.0",
+ "20.0",
+ "22.0",
+ "24.0",
+ "26.0",
+ "28.0",
+ "30.0",
+ "32.0",
+ "36.0",
+ "40.0",
+ "44.0",
+ "48.0",
+ "52.0",
+ "56.0",
+ "60.0",
+ "64.0",
+ "72.0",
+ "80.0",
+ "88.0",
+ "96.0",
+ "104.0",
+ "112.0",
+ "120.0",
+ "128.0",
+ "144.0",
+ "160.0",
+ "176.0",
+ "192.0",
+ "208.0",
+ "224.0",
+ "240.0",
+ "nan",
+ "-0.0009765625",
+ "-0.001953125",
+ "-0.0029296875",
+ "-0.00390625",
+ "-0.0048828125",
+ "-0.005859375",
+ "-0.0068359375",
+ "-0.0078125",
+ "-0.0087890625",
+ "-0.009765625",
+ "-0.0107421875",
+ "-0.01171875",
+ "-0.0126953125",
+ "-0.013671875",
+ "-0.0146484375",
+ "-0.015625",
+ "-0.017578125",
+ "-0.01953125",
+ "-0.021484375",
+ "-0.0234375",
+ "-0.025390625",
+ "-0.02734375",
+ "-0.029296875",
+ "-0.03125",
+ "-0.03515625",
+ "-0.0390625",
+ "-0.04296875",
+ "-0.046875",
+ "-0.05078125",
+ "-0.0546875",
+ "-0.05859375",
+ "-0.0625",
+ "-0.0703125",
+ "-0.078125",
+ "-0.0859375",
+ "-0.09375",
+ "-0.1015625",
+ "-0.109375",
+ "-0.1171875",
+ "-0.125",
+ "-0.140625",
+ "-0.15625",
+ "-0.171875",
+ "-0.1875",
+ "-0.203125",
+ "-0.21875",
+ "-0.234375",
+ "-0.25",
+ "-0.28125",
+ "-0.3125",
+ "-0.34375",
+ "-0.375",
+ "-0.40625",
+ "-0.4375",
+ "-0.46875",
+ "-0.5",
+ "-0.5625",
+ "-0.625",
+ "-0.6875",
+ "-0.75",
+ "-0.8125",
+ "-0.875",
+ "-0.9375",
+ "-1.0",
+ "-1.125",
+ "-1.25",
+ "-1.375",
+ "-1.5",
+ "-1.625",
+ "-1.75",
+ "-1.875",
+ "-2.0",
+ "-2.25",
+ "-2.5",
+ "-2.75",
+ "-3.0",
+ "-3.25",
+ "-3.5",
+ "-3.75",
+ "-4.0",
+ "-4.5",
+ "-5.0",
+ "-5.5",
+ "-6.0",
+ "-6.5",
+ "-7.0",
+ "-7.5",
+ "-8.0",
+ "-9.0",
+ "-10.0",
+ "-11.0",
+ "-12.0",
+ "-13.0",
+ "-14.0",
+ "-15.0",
+ "-16.0",
+ "-18.0",
+ "-20.0",
+ "-22.0",
+ "-24.0",
+ "-26.0",
+ "-28.0",
+ "-30.0",
+ "-32.0",
+ "-36.0",
+ "-40.0",
+ "-44.0",
+ "-48.0",
+ "-52.0",
+ "-56.0",
+ "-60.0",
+ "-64.0",
+ "-72.0",
+ "-80.0",
+ "-88.0",
+ "-96.0",
+ "-104.0",
+ "-112.0",
+ "-120.0",
+ "-128.0",
+ "-144.0",
+ "-160.0",
+ "-176.0",
+ "-192.0",
+ "-208.0",
+ "-224.0",
+ "-240.0",
+)
diff --git a/stdlib/src/builtin/_location.mojo b/stdlib/src/builtin/_location.mojo
index 0940e49f8e..463cba7b08 100644
--- a/stdlib/src/builtin/_location.mojo
+++ b/stdlib/src/builtin/_location.mojo
@@ -42,7 +42,7 @@ struct _SourceLocation(Writable, Stringable):
"""
return "At " + str(self) + ": " + str(msg)
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""
Formats the source location to the provided Writer.
@@ -57,7 +57,7 @@ struct _SourceLocation(Writable, Stringable):
@always_inline("nodebug")
fn __source_location() -> _SourceLocation:
- """Returns the location where it's called.
+ """Returns the location for where this function is called.
This currently doesn't work when called in a parameter expression.
@@ -68,7 +68,7 @@ fn __source_location() -> _SourceLocation:
var col: __mlir_type.index
var file_name: __mlir_type.`!kgen.string`
line, col, file_name = __mlir_op.`kgen.source_loc`[
- _properties = __mlir_attr.`{inlineCount = 0 : i64}`,
+ inlineCount = Int(0).value,
_type = (
__mlir_type.index,
__mlir_type.index,
@@ -80,26 +80,35 @@ fn __source_location() -> _SourceLocation:
@always_inline("nodebug")
-fn __call_location() -> _SourceLocation:
- """Returns the location where the enclosing function is called.
+fn __call_location[inline_count: Int = 1]() -> _SourceLocation:
+ """Returns the location for where the caller of this function is called. An
+ optional `inline_count` parameter can be specified to skip over that many
+ levels of calling functions.
- This should only be used in `@always_inline` or `@always_inline("nodebug")`
- functions so that it returns the source location of where the enclosing
- function is called at (even if inside another `@always_inline("nodebug")`
- function).
+ This should only be used when enclosed in a series of `@always_inline` or
+ `@always_inline("nodebug")` function calls, where the layers of calling
+ functions is no fewer than `inline_count`.
- This currently doesn't work when this or the enclosing function is called in
- a parameter expression.
+ For example, when `inline_count = 1`, only the caller of this function needs
+ to be `@always_inline` or `@always_inline("nodebug")`. This function will
+ return the source location of the caller's invocation.
+
+ When `inline_count = 2`, the caller of the caller of this function also
+ needs to be inlined. This function will return the source location of the
+ caller's caller's invocation.
+
+ This currently doesn't work when the `inline_count`-th wrapping caller is
+ called in a parameter expression.
Returns:
- The location information of where the enclosing function (i.e. the
+ The location information of where the caller of this function (i.e. the
function whose body __call_location() is used in) is called.
"""
var line: __mlir_type.index
var col: __mlir_type.index
var file_name: __mlir_type.`!kgen.string`
line, col, file_name = __mlir_op.`kgen.source_loc`[
- _properties = __mlir_attr.`{inlineCount = 1 : i64}`,
+ inlineCount = inline_count.value,
_type = (
__mlir_type.index,
__mlir_type.index,
diff --git a/stdlib/src/builtin/_pybind.mojo b/stdlib/src/builtin/_pybind.mojo
index 2644bceba2..5e1d8c874c 100644
--- a/stdlib/src/builtin/_pybind.mojo
+++ b/stdlib/src/builtin/_pybind.mojo
@@ -11,32 +11,29 @@
# limitations under the License.
# ===----------------------------------------------------------------------=== #
-from memory import UnsafePointer, stack_allocation
-
-from sys import sizeof, alignof
+from collections import Optional
+from sys import alignof, sizeof
import python._cpython as cp
-from python import TypedPythonObject, Python, PythonObject
-from python.python import _get_global_python_itf
-from python._cpython import (
- PyObjectPtr,
- PyMethodDef,
- PyType_Slot,
- PyType_Spec,
- CPython,
-)
-from python._bindings import (
- Pythonable,
+from memory import UnsafePointer, stack_allocation
+from python import Python, PythonObject, TypedPythonObject
+from python._bindings import ( # Imported for use by the compiler
ConvertibleFromPython,
PyMojoObject,
- python_type_object,
- py_c_function_wrapper,
+ Pythonable,
check_argument_type,
- # Imported for use by the compiler
check_arguments_arity,
+ py_c_function_wrapper,
+ python_type_object,
)
-
-from collections import Optional
+from python._cpython import (
+ CPython,
+ PyMethodDef,
+ PyObjectPtr,
+ PyType_Slot,
+ PyType_Spec,
+)
+from python.python import _get_global_python_itf
alias PyModule = TypedPythonObject["Module"]
@@ -64,10 +61,13 @@ fn fail_initialization(owned err: Error) -> PythonObject:
fn pointer_bitcast[
To: AnyType
-](ptr: Pointer) -> Pointer[To, ptr.origin, ptr.address_space, *_, **_] as out:
- return __type_of(out)(
+](
+ ptr: Pointer,
+ out result: Pointer[To, ptr.origin, ptr.address_space, *_, **_],
+):
+ return __type_of(result)(
_mlir_value=__mlir_op.`lit.ref.from_pointer`[
- _type = __type_of(out)._mlir_type
+ _type = __type_of(result)._mlir_type
](
UnsafePointer(__mlir_op.`lit.ref.to_pointer`(ptr._value))
.bitcast[To]()
@@ -79,7 +79,7 @@ fn pointer_bitcast[
fn gen_pytype_wrapper[
T: Pythonable,
name: StringLiteral,
-](inout module: PythonObject) raises:
+](mut module: PythonObject) raises:
# TODO(MOCO-1301): Add support for member method generation.
# TODO(MOCO-1302): Add support for generating member field as computed properties.
# TODO(MOCO-1307): Add support for constructor generation.
@@ -102,7 +102,7 @@ fn add_wrapper_to_module[
PythonObject, TypedPythonObject["Tuple"]
) raises -> PythonObject,
func_name: StringLiteral,
-](inout module_obj: PythonObject) raises:
+](mut module_obj: PythonObject) raises:
var module = TypedPythonObject["Module"](unsafe_unchecked_from=module_obj)
Python.add_functions(
module,
@@ -165,7 +165,8 @@ fn _try_convert_arg[
type_name_id: StringLiteral,
py_args: TypedPythonObject["Tuple"],
argidx: Int,
-) raises -> T as result:
+ out result: T,
+) raises:
try:
result = T.try_from_python(py_args[argidx])
except convert_err:
diff --git a/stdlib/src/builtin/_startup.mojo b/stdlib/src/builtin/_startup.mojo
index 97a815742f..e6efe691e0 100644
--- a/stdlib/src/builtin/_startup.mojo
+++ b/stdlib/src/builtin/_startup.mojo
@@ -12,9 +12,10 @@
# ===----------------------------------------------------------------------=== #
"""Implements functionality to start a mojo execution."""
-from memory import UnsafePointer
from sys import external_call
-from sys.ffi import _get_global, OpaquePointer
+from sys.ffi import OpaquePointer, _get_global
+
+from memory import UnsafePointer
fn _init_global_runtime(ignored: OpaquePointer) -> OpaquePointer:
diff --git a/stdlib/src/builtin/_stubs.mojo b/stdlib/src/builtin/_stubs.mojo
index 92e661dc00..3b5a12fdac 100644
--- a/stdlib/src/builtin/_stubs.mojo
+++ b/stdlib/src/builtin/_stubs.mojo
@@ -13,9 +13,9 @@
from builtin.range import _StridedRangeIterator, _UIntStridedRangeIterator
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# __MLIRType
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@register_passable("trivial")
@@ -23,18 +23,18 @@ struct __MLIRType[T: AnyTrivialRegType](Movable, Copyable):
var value: T
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# parameter_for
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
trait _IntNext(Copyable):
- fn __next__(inout self) -> Int:
+ fn __next__(mut self) -> Int:
...
trait _UIntNext(Copyable):
- fn __next__(inout self) -> UInt:
+ fn __next__(mut self) -> UInt:
...
diff --git a/stdlib/src/builtin/anytype.mojo b/stdlib/src/builtin/anytype.mojo
index 8c7a061ba5..c76235fc9c 100644
--- a/stdlib/src/builtin/anytype.mojo
+++ b/stdlib/src/builtin/anytype.mojo
@@ -20,6 +20,20 @@ These are Mojo built-ins, so you don't need to import them.
# ===----------------------------------------------------------------------=== #
+# TODO(MOCO-1468): Add @explicit_destroy here so we get an error message,
+# preferably one that mentions a link the user can go to to learn about
+# linear types.
+trait UnknownDestructibility:
+ """The UnknownDestructibility trait is the most basic trait, that all other
+ types extend.
+
+ This has no __del__ method. For types that should have the __del__ method,
+ use ImplicitlyDestructible instead.
+ """
+
+ pass
+
+
trait AnyType:
"""The AnyType trait describes a type that has a destructor.
@@ -32,10 +46,9 @@ trait AnyType:
lifetime, and the resultant type receives a destructor regardless of whether
the user explicitly defines one.
- All types pessimistically require a destructor when used in generic
- functions. Hence, all Mojo traits are considered to inherit from
- AnyType, providing a default no-op destructor implementation for types
- that may need them.
+ Unless they specify @explicit_destroy, all Mojo structs and traits are
+ considered to inherit from AnyType, providing a default no-op destructor
+ implementation for types that may need them.
Example implementing the `AnyType` trait on `Foo` that frees the
allocated memory:
@@ -66,3 +79,8 @@ trait AnyType:
end of this function.
"""
...
+
+
+# A temporary alias to help with the linear types transition, see
+# https://www.notion.so/modularai/Linear-Types-14a1044d37bb809ab074c990fe1a84e3.
+alias ImplicitlyDestructible = AnyType
diff --git a/stdlib/src/builtin/bool.mojo b/stdlib/src/builtin/bool.mojo
index c9073c3558..e48f1c9f5a 100644
--- a/stdlib/src/builtin/bool.mojo
+++ b/stdlib/src/builtin/bool.mojo
@@ -15,10 +15,10 @@
These are Mojo built-ins, so you don't need to import them.
"""
-from collections import Set, List
+from collections import List, Set
-from utils._visualizers import lldb_formatter_wrapping_type
from utils._select import _select_register_value
+from utils._visualizers import lldb_formatter_wrapping_type
# ===----------------------------------------------------------------------=== #
# Boolable
@@ -155,7 +155,7 @@ struct Bool(
@always_inline("nodebug")
@implicit
- fn __init__[T: ImplicitlyBoolable, //](inout self, value: T):
+ fn __init__[T: ImplicitlyBoolable, //](mut self, value: T):
"""Convert an ImplicitlyBoolable value to a Bool.
Parameters:
@@ -226,7 +226,7 @@ struct Bool(
return String.write(self)
@no_inline
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""
Formats this boolean to the provided Writer.
@@ -404,7 +404,7 @@ struct Bool(
return __mlir_op.`pop.and`(self.value, rhs.value)
@always_inline("nodebug")
- fn __iand__(inout self, rhs: Bool):
+ fn __iand__(mut self, rhs: Bool):
"""Computes `self & rhs` and store the result in `self`.
Args:
@@ -440,7 +440,7 @@ struct Bool(
return __mlir_op.`pop.or`(self.value, rhs.value)
@always_inline("nodebug")
- fn __ior__(inout self, rhs: Bool):
+ fn __ior__(mut self, rhs: Bool):
"""Computes `self | rhs` and store the result in `self`.
Args:
@@ -476,7 +476,7 @@ struct Bool(
return __mlir_op.`pop.xor`(self.value, rhs.value)
@always_inline("nodebug")
- fn __ixor__(inout self, rhs: Bool):
+ fn __ixor__(mut self, rhs: Bool):
"""Computes `self ^ rhs` and stores the result in `self`.
Args:
diff --git a/stdlib/src/builtin/builtin_list.mojo b/stdlib/src/builtin/builtin_list.mojo
index 80e4b61185..e74b93cad3 100644
--- a/stdlib/src/builtin/builtin_list.mojo
+++ b/stdlib/src/builtin/builtin_list.mojo
@@ -17,10 +17,9 @@ These are Mojo built-ins, so you don't need to import them.
from memory import Pointer, UnsafePointer
-
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# ListLiteral
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
struct ListLiteral[*Ts: CollectionElement](Sized, CollectionElement):
@@ -120,9 +119,9 @@ struct ListLiteral[*Ts: CollectionElement](Sized, CollectionElement):
return value in self.storage
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# VariadicList / VariadicListMem
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@value
@@ -136,7 +135,7 @@ struct _VariadicListIter[type: AnyTrivialRegType]:
var index: Int
var src: VariadicList[type]
- fn __next__(inout self) -> type:
+ fn __next__(mut self) -> type:
self.index += 1
return self.src[self.index - 1]
@@ -222,7 +221,7 @@ struct VariadicList[type: AnyTrivialRegType](Sized):
struct _VariadicListMemIter[
elt_is_mutable: Bool, //,
elt_type: AnyType,
- elt_origin: Origin[elt_is_mutable].type,
+ elt_origin: Origin[elt_is_mutable],
list_origin: ImmutableOrigin,
]:
"""Iterator for VariadicListMem.
@@ -234,18 +233,23 @@ struct _VariadicListMemIter[
list_origin: The origin of the VariadicListMem.
"""
- alias variadic_list_type = VariadicListMem[elt_type, elt_origin]
+ alias variadic_list_type = VariadicListMem[
+ elt_type, elt_origin._mlir_origin
+ ]
var index: Int
- var src: Pointer[Self.variadic_list_type, list_origin]
+ var src: Pointer[
+ Self.variadic_list_type,
+ list_origin,
+ ]
fn __init__(
- inout self, index: Int, ref [list_origin]list: Self.variadic_list_type
+ mut self, index: Int, ref [list_origin]list: Self.variadic_list_type
):
self.index = index
self.src = Pointer.address_of(list)
- fn __next__(inout self) -> Self.variadic_list_type.reference_type:
+ fn __next__(mut self) -> Self.variadic_list_type.reference_type:
self.index += 1
# TODO: Need to make this return a dereferenced reference, not a
# reference that must be deref'd by the user.
@@ -261,42 +265,10 @@ struct _VariadicListMemIter[
return len(self.src[]) - self.index
-# Helper to compute the union of two origins:
-# TODO: parametric aliases would be nice.
-struct _lit_origin_union[
- is_mutable: Bool, //,
- a: Origin[is_mutable].type,
- b: Origin[is_mutable].type,
-]:
- alias result = __mlir_attr[
- `#lit.origin.union<`,
- a,
- `,`,
- b,
- `> : !lit.origin<`,
- is_mutable.value,
- `>`,
- ]
-
-
-struct _lit_mut_cast[
- is_mutable: Bool, //,
- operand: Origin[is_mutable].type,
- result_mutable: Bool,
-]:
- alias result = __mlir_attr[
- `#lit.origin.mutcast<`,
- operand,
- `> : !lit.origin<`,
- +result_mutable.value,
- `>`,
- ]
-
-
struct VariadicListMem[
elt_is_mutable: Bool, //,
element_type: AnyType,
- origin: Origin[elt_is_mutable].type,
+ origin: Origin[elt_is_mutable]._mlir_type,
](Sized):
"""A utility class to access variadic function arguments of memory-only
types that may have ownership. It exposes references to the elements in a
@@ -304,7 +276,7 @@ struct VariadicListMem[
Parameters:
elt_is_mutable: True if the elements of the list are mutable for an
- inout or owned argument.
+ mut or owned argument.
element_type: The type of the elements in the list.
origin: The reference origin of the underlying elements.
"""
@@ -312,7 +284,7 @@ struct VariadicListMem[
alias reference_type = Pointer[element_type, origin]
alias _mlir_ref_type = Self.reference_type._mlir_type
alias _mlir_type = __mlir_type[
- `!kgen.variadic<`, Self._mlir_ref_type, `, borrow_in_mem>`
+ `!kgen.variadic<`, Self._mlir_ref_type, `, read_mem>`
]
var value: Self._mlir_type
@@ -327,7 +299,7 @@ struct VariadicListMem[
# Life cycle methods
# ===-------------------------------------------------------------------===#
- # Provide support for borrowed variadic arguments.
+ # Provide support for read-only variadic arguments.
@doc_private
@always_inline
@implicit
@@ -340,11 +312,11 @@ struct VariadicListMem[
self.value = value
self._is_owned = False
- # Provide support for variadics of *inout* arguments. The reference will
+ # Provide support for variadics of *mut* arguments. The reference will
# automatically be inferred to be mutable, and the !kgen.variadic will have
- # convention=inout.
+ # convention=mut.
alias _inout_variadic_type = __mlir_type[
- `!kgen.variadic<`, Self._mlir_ref_type, `, inout>`
+ `!kgen.variadic<`, Self._mlir_ref_type, `, mut>`
]
@always_inline
@@ -434,13 +406,12 @@ struct VariadicListMem[
fn __getitem__(
self, idx: Int
) -> ref [
- _lit_origin_union[
- origin,
- # cast mutability of self to match the mutability of the element,
- # since that is what we want to use in the ultimate reference and
- # the union overall doesn't matter.
- _lit_mut_cast[__origin_of(self), elt_is_mutable].result,
- ].result
+ # cast mutability of self to match the mutability of the element,
+ # since that is what we want to use in the ultimate reference and
+ # the union overall doesn't matter.
+ Origin[elt_is_mutable]
+ .cast_from[__origin_of(origin, self)]
+ .result
] element_type:
"""Gets a single element on the variadic list.
@@ -470,9 +441,9 @@ struct VariadicListMem[
](0, self)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# VariadicPack
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
alias _AnyTypeMetaType = __mlir_type[`!lit.anytrait<`, AnyType, `>`]
@@ -481,7 +452,7 @@ alias _AnyTypeMetaType = __mlir_type[`!lit.anytrait<`, AnyType, `>`]
@register_passable
struct VariadicPack[
elt_is_mutable: Bool, //,
- origin: Origin[elt_is_mutable].type,
+ origin: Origin[elt_is_mutable]._mlir_type,
element_trait: _AnyTypeMetaType,
*element_types: element_trait,
](Sized):
@@ -490,7 +461,7 @@ struct VariadicPack[
Parameters:
elt_is_mutable: True if the elements of the list are mutable for an
- inout or owned argument pack.
+ mut or owned argument pack.
origin: The reference origin of the underlying elements.
element_trait: The trait that each element of the pack conforms to.
element_types: The list of types held by the argument pack.
@@ -520,7 +491,7 @@ struct VariadicPack[
Args:
value: The argument to construct the pack with.
- is_owned: Whether this is an 'owned' pack or 'inout'/'borrowed'.
+ is_owned: Whether this is an 'owned' pack or 'mut'/'read-only'.
"""
self._value = value
self._is_owned = is_owned
@@ -603,7 +574,7 @@ struct VariadicPack[
"""Apply a function to each element of the pack in order. This applies
the specified function (which must be parametric on the element type) to
each element of the pack, from the first element to the last, passing
- in each element as a borrowed argument.
+ in each element as a read-only argument.
Parameters:
func: The function to apply to each element.
@@ -620,7 +591,7 @@ struct VariadicPack[
"""Apply a function to each element of the pack in order. This applies
the specified function (which must be parametric on the element type) to
each element of the pack, from the first element to the last, passing
- in each element as a borrowed argument.
+ in each element as a read-only argument.
Parameters:
func: The function to apply to each element.
diff --git a/stdlib/src/builtin/builtin_slice.mojo b/stdlib/src/builtin/builtin_slice.mojo
index cc5a6d2f1a..0d0fe96750 100644
--- a/stdlib/src/builtin/builtin_slice.mojo
+++ b/stdlib/src/builtin/builtin_slice.mojo
@@ -66,7 +66,7 @@ struct Slice(
@always_inline
fn __init__(
- inout self,
+ mut self,
start: Optional[Int],
end: Optional[Int],
step: Optional[Int],
@@ -115,7 +115,7 @@ struct Slice(
return self.__str__()
@no_inline
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""Write Slice string representation to a `Writer`.
Parameters:
diff --git a/stdlib/src/builtin/constrained.mojo b/stdlib/src/builtin/constrained.mojo
index c7cbb756b4..b50ca11e71 100644
--- a/stdlib/src/builtin/constrained.mojo
+++ b/stdlib/src/builtin/constrained.mojo
@@ -54,4 +54,38 @@ fn constrained[cond: Bool, msg: StringLiteral = "param assertion failed"]():
__mlir_op.`kgen.param.assert`[
cond = cond.__mlir_i1__(), message = msg.value
]()
- return
+
+
+@always_inline("nodebug")
+fn constrained[cond: Bool, msg: String]():
+ """Compile time checks that the condition is true.
+
+ The `constrained` is similar to `static_assert` in C++ and is used to
+ introduce constraints on the enclosing function. In Mojo, the assert places
+ a constraint on the function. The message is displayed when the assertion
+ fails, and takes a generalized string.
+
+ Parameters:
+ cond: The bool value to assert.
+ msg: The message to display on failure.
+
+ Example:
+
+ ```mojo
+ from sys.info import num_physical_cores
+
+ def main():
+ alias cores_to_use = 2
+ multicore_check[cores_to_use]()
+
+ def multicore_check[cores: Int]():
+ constrained[
+ cores <= num_physical_cores(),
+ "build failed: not enough cores"
+ ]()
+ constrained[
+ cores >= 2,
+ "at least two cores are required"
+ ]()
+ """
+ constrained[cond, StringLiteral.get[msg]()]()
diff --git a/stdlib/src/builtin/coroutine.mojo b/stdlib/src/builtin/coroutine.mojo
index d33445e100..c2c0ee1d81 100644
--- a/stdlib/src/builtin/coroutine.mojo
+++ b/stdlib/src/builtin/coroutine.mojo
@@ -78,6 +78,7 @@ fn _coro_resume_noop_callback(null: AnyCoroutine):
# ===----------------------------------------------------------------------=== #
+@explicit_destroy
@register_passable
struct Coroutine[type: AnyType, origins: OriginSet]:
"""Represents a coroutine.
@@ -130,12 +131,13 @@ struct Coroutine[type: AnyType, origins: OriginSet]:
self._handle = handle
@always_inline
- fn __del__(owned self):
+ fn force_destroy(owned self):
"""Destroy the coroutine object."""
__mlir_op.`co.destroy`(self._handle)
+ __disable_del self
@always_inline
- fn __await__(owned self) -> type as out:
+ fn __await__(owned self, out result: type):
"""Suspends the current coroutine until the coroutine is complete.
Returns:
@@ -145,12 +147,14 @@ struct Coroutine[type: AnyType, origins: OriginSet]:
# Black magic! Internal implementation detail!
# Don't you dare copy this code! 😤
var handle = self._handle
- __mlir_op.`lit.ownership.mark_destroyed`(__get_mvalue_as_litref(self))
+ __disable_del self
__mlir_op.`co.await`[_type=NoneType](
handle,
- __mlir_op.`lit.ref.to_pointer`(__get_mvalue_as_litref(out)),
+ __mlir_op.`lit.ref.to_pointer`(__get_mvalue_as_litref(result)),
+ )
+ __mlir_op.`lit.ownership.mark_initialized`(
+ __get_mvalue_as_litref(result)
)
- __mlir_op.`lit.ownership.mark_initialized`(__get_mvalue_as_litref(out))
# ===----------------------------------------------------------------------=== #
@@ -158,6 +162,7 @@ struct Coroutine[type: AnyType, origins: OriginSet]:
# ===----------------------------------------------------------------------=== #
+@explicit_destroy
@register_passable
struct RaisingCoroutine[type: AnyType, origins: OriginSet]:
"""Represents a coroutine that can raise.
@@ -211,12 +216,13 @@ struct RaisingCoroutine[type: AnyType, origins: OriginSet]:
self._handle = handle
@always_inline
- fn __del__(owned self):
+ fn force_destroy(owned self):
"""Destroy the coroutine object."""
__mlir_op.`co.destroy`(self._handle)
+ __disable_del self
@always_inline
- fn __await__(owned self) raises -> type as out:
+ fn __await__(owned self, out result: type) raises:
"""Suspends the current coroutine until the coroutine is complete.
Returns:
@@ -226,10 +232,10 @@ struct RaisingCoroutine[type: AnyType, origins: OriginSet]:
# Black magic! Internal implementation detail!
# Don't you dare copy this code! 😤
var handle = self._handle
- __mlir_op.`lit.ownership.mark_destroyed`(__get_mvalue_as_litref(self))
+ __disable_del self
if __mlir_op.`co.await`[_type = __mlir_type.i1](
handle,
- __mlir_op.`lit.ref.to_pointer`(__get_mvalue_as_litref(out)),
+ __mlir_op.`lit.ref.to_pointer`(__get_mvalue_as_litref(result)),
__mlir_op.`lit.ref.to_pointer`(
__get_mvalue_as_litref(__get_nearest_error_slot())
),
@@ -238,4 +244,6 @@ struct RaisingCoroutine[type: AnyType, origins: OriginSet]:
__get_mvalue_as_litref(__get_nearest_error_slot())
)
__mlir_op.`lit.raise`()
- __mlir_op.`lit.ownership.mark_initialized`(__get_mvalue_as_litref(out))
+ __mlir_op.`lit.ownership.mark_initialized`(
+ __get_mvalue_as_litref(result)
+ )
diff --git a/stdlib/src/builtin/debug_assert.mojo b/stdlib/src/builtin/debug_assert.mojo
index 6d33f5f5e4..e66c968189 100644
--- a/stdlib/src/builtin/debug_assert.mojo
+++ b/stdlib/src/builtin/debug_assert.mojo
@@ -17,15 +17,20 @@ These are Mojo built-ins, so you don't need to import them.
from os import abort
-from sys import is_nvidia_gpu, llvm_intrinsic
+from sys import is_gpu, is_nvidia_gpu, llvm_intrinsic
from sys._build import is_debug_build
+from sys.ffi import c_char, c_size_t, c_uint, external_call
from sys.param_env import env_get_string
-from sys.ffi import external_call, c_uint, c_size_t, c_char
-from memory import UnsafePointer
-from utils.write import _WriteBufferHeap, _WriteBufferStack, write_args
-
from builtin._location import __call_location, _SourceLocation
+from memory import UnsafePointer, Span
+
+from utils.write import (
+ _ArgBytes,
+ _WriteBufferHeap,
+ _WriteBufferStack,
+ write_args,
+)
alias defined_mode = env_get_string["ASSERT", "safe"]()
@@ -44,7 +49,7 @@ fn _assert_enabled[assert_mode: StringLiteral, cpu_only: Bool]() -> Bool:
]()
@parameter
- if defined_mode == "none" or (is_nvidia_gpu() and cpu_only):
+ if defined_mode == "none" or (is_gpu() and cpu_only):
return False
elif defined_mode == "all" or defined_mode == "warn" or is_debug_build():
return True
@@ -236,19 +241,33 @@ fn _debug_assert_msg(
var stdout = sys.stdout
@parameter
- if is_nvidia_gpu():
- var buffer = _WriteBufferHeap[4096](stdout)
- buffer.write("At ", loc, ": ")
- _write_gpu_thread_context(buffer)
-
- @parameter
- if defined_mode == "warn":
- buffer.write(" Assert Warning: ")
- else:
- buffer.write(" Assert Error: ")
-
+ if is_gpu():
+ # Count the total length of bytes to allocate only once
+ var arg_bytes = _ArgBytes()
+ arg_bytes.write(
+ "At ",
+ loc,
+ ": ",
+ _ThreadContext(),
+ " Assert ",
+ "Warning: " if defined_mode == "warn" else " Error: ",
+ )
+ write_args(arg_bytes, messages, end="\n")
+
+ var buffer = _WriteBufferHeap(arg_bytes.size + 1)
+ buffer.write(
+ "At ",
+ loc,
+ ": ",
+ _ThreadContext(),
+ " Assert ",
+ "Warning: " if defined_mode == "warn" else "Error: ",
+ )
write_args(buffer, messages, end="\n")
- buffer.flush()
+ buffer.data[buffer.pos] = 0
+ stdout.write_bytes(
+ Span[Byte, ImmutableAnyOrigin](ptr=buffer.data, length=buffer.pos)
+ )
@parameter
if defined_mode != "warn":
@@ -272,28 +291,43 @@ fn _debug_assert_msg(
abort()
-# Can't import gpu module at this stage in compilation for thread/block idx
-fn _write_gpu_thread_context[W: Writer](inout writer: W):
- writer.write("block: [")
- _write_id["block", "x"](writer)
- writer.write(",")
- _write_id["block", "y"](writer)
- writer.write(",")
- _write_id["block", "z"](writer)
- writer.write("] thread: [")
- _write_id["thread", "x"](writer)
- writer.write(",")
- _write_id["thread", "y"](writer)
- writer.write(",")
- _write_id["thread", "z"](writer)
- writer.write("]")
-
-
-fn _write_id[
- W: Writer, //, type: StringLiteral, dim: StringLiteral
-](inout writer: W):
+struct _ThreadContext(Writable):
+ var block_x: Int32
+ var block_y: Int32
+ var block_z: Int32
+ var thread_x: Int32
+ var thread_y: Int32
+ var thread_z: Int32
+
+ fn __init__(out self):
+ self.block_x = _get_id["block", "x"]()
+ self.block_y = _get_id["block", "y"]()
+ self.block_z = _get_id["block", "z"]()
+ self.thread_x = _get_id["thread", "x"]()
+ self.thread_y = _get_id["thread", "y"]()
+ self.thread_z = _get_id["thread", "z"]()
+
+ fn write_to[W: Writer](self, mut writer: W):
+ writer.write(
+ "block: [",
+ self.block_x,
+ ",",
+ self.block_y,
+ ",",
+ self.block_z,
+ "] thread: [",
+ self.thread_x,
+ ",",
+ self.thread_y,
+ ",",
+ self.thread_z,
+ "]",
+ )
+
+
+fn _get_id[type: StringLiteral, dim: StringLiteral]() -> Int32:
alias intrinsic_name = _get_intrinsic_name[type, dim]()
- writer.write(llvm_intrinsic[intrinsic_name, Int32, has_side_effect=False]())
+ return llvm_intrinsic[intrinsic_name, Int32, has_side_effect=False]()
fn _get_intrinsic_name[
diff --git a/stdlib/src/builtin/dtype.mojo b/stdlib/src/builtin/dtype.mojo
index fa7a222492..b8a7dff5d6 100644
--- a/stdlib/src/builtin/dtype.mojo
+++ b/stdlib/src/builtin/dtype.mojo
@@ -17,7 +17,7 @@ These are Mojo built-ins, so you don't need to import them.
from collections import KeyElement
from hashlib._hasher import _HashableWithHasher, _Hasher
-from sys import sizeof, bitwidthof, os_is_windows
+from sys import bitwidthof, os_is_windows, sizeof
alias _mIsSigned = UInt8(1)
alias _mIsInteger = UInt8(1 << 7)
@@ -66,11 +66,65 @@ struct DType(
alias float8e5m2 = DType(
__mlir_attr.`#kgen.dtype.constant : !kgen.dtype`
)
- """Represents a FP8E5M2 floating point format whose bitwidth is 8."""
+ """Represents a FP8E5M2 floating point format from the [OFP8
+ standard](https://www.opencompute.org/documents/ocp-8-bit-floating-point-specification-ofp8-revision-1-0-2023-12-01-pdf-1).
+
+ The 8 bits are encoded as `seeeeemm`:
+ - (s)ign: 1 bit
+ - (e)xponent: 5 bits
+ - (m)antissa: 2 bits
+ - exponent bias: 15
+ - nan: {0,1}11111{01,10,11}
+ - inf: 01111100
+ - -inf: 11111100
+ - -0: 10000000
+ """
+ alias float8e5m2fnuz = DType(
+ __mlir_attr.`#kgen.dtype.constant : !kgen.dtype`
+ )
+ """Represents a FP8E5M2FNUZ floating point format.
+
+ The 8 bits are encoded as `seeeeemm`:
+ - (s)ign: 1 bit
+ - (e)xponent: 5 bits
+ - (m)antissa: 2 bits
+ - exponent bias: 16
+ - nan: 10000000
+ - fn: finite (no inf or -inf encodings)
+ - uz: unsigned zero (no -0 encoding)
+ """
alias float8e4m3 = DType(
__mlir_attr.`#kgen.dtype.constant : !kgen.dtype`
)
- """Represents a FP8E4M3 floating point format whose bitwidth is 8."""
+ """Represents a FP8E4M3 floating point format from the [OFP8
+ standard](https://www.opencompute.org/documents/ocp-8-bit-floating-point-specification-ofp8-revision-1-0-2023-12-01-pdf-1).
+
+ This type is named `float8_e4m3fn` (the "fn" stands for "finite") in some
+ frameworks, as it does not encode -inf or inf.
+
+ The 8 bits are encoded as `seeeemmm`:
+ - (s)ign: 1 bit
+ - (e)xponent: 4 bits
+ - (m)antissa: 3 bits
+ - exponent bias: 7
+ - nan: 01111111, 11111111
+ - -0: 10000000
+ - fn: finite (no inf or -inf encodings)
+ """
+ alias float8e4m3fnuz = DType(
+ __mlir_attr.`#kgen.dtype.constant : !kgen.dtype`
+ )
+ """Represents a FP8E4M3FNUZ floating point format.
+
+ The 8 bits are encoded as `seeeemmm`:
+ - (s)ign: 1 bit
+ - (e)xponent: 4 bits
+ - (m)antissa: 3 bits
+ - exponent bias: 8
+ - nan: 10000000
+ - fn: finite (no inf or -inf encodings)
+ - uz: unsigned zero (no -0 encoding)
+ """
alias bfloat16 = DType(
__mlir_attr.`#kgen.dtype.constant : !kgen.dtype`
)
@@ -101,6 +155,16 @@ struct DType(
"""
self = other
+ @always_inline
+ @implicit
+ fn __init__(out self, value: Self.type):
+ """Construct a DType from MLIR dtype.
+
+ Args:
+ value: The MLIR dtype.
+ """
+ self.value = value
+
@staticmethod
fn _from_str(str: String) -> DType:
"""Construct a DType from a string.
@@ -132,8 +196,12 @@ struct DType(
return DType.index
elif str == String("float8e5m2"):
return DType.float8e5m2
+ elif str == String("float8e5m2fnuz"):
+ return DType.float8e5m2fnuz
elif str == String("float8e4m3"):
return DType.float8e4m3
+ elif str == String("float8e4m3fnuz"):
+ return DType.float8e4m3fnuz
elif str == String("bfloat16"):
return DType.bfloat16
elif str == String("float16"):
@@ -160,7 +228,7 @@ struct DType(
return String.write(self)
@no_inline
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""
Formats this dtype to the provided Writer.
@@ -193,8 +261,12 @@ struct DType(
return writer.write("index")
if self == DType.float8e5m2:
return writer.write("float8e5m2")
+ if self == DType.float8e5m2fnuz:
+ return writer.write("float8e5m2fnuz")
if self == DType.float8e4m3:
return writer.write("float8e4m3")
+ if self == DType.float8e4m3fnuz:
+ return writer.write("float8e4m3fnuz")
if self == DType.bfloat16:
return writer.write("bfloat16")
if self == DType.float16:
@@ -307,7 +379,7 @@ struct DType(
"""
return hash(UInt8(self._as_i8()))
- fn __hash__[H: _Hasher](self, inout hasher: H):
+ fn __hash__[H: _Hasher](self, mut hasher: H):
"""Updates hasher with this `DType` value.
Parameters:
@@ -397,13 +469,18 @@ struct DType(
@always_inline("nodebug")
fn is_float8(self) -> Bool:
"""Returns True if the type is a 8bit-precision floating point type,
- e.g. either float8e5m2 or float8e4m3.
+ e.g. float8e5m2, float8e5m2fnuz, float8e4m3 and float8e4m3fnuz.
Returns:
True if the type is a 8bit-precision float, false otherwise.
"""
- return self in (DType.float8e5m2, DType.float8e4m3)
+ return self in (
+ DType.float8e5m2,
+ DType.float8e4m3,
+ DType.float8e5m2fnuz,
+ DType.float8e4m3fnuz,
+ )
@always_inline("nodebug")
fn is_half_float(self) -> Bool:
@@ -459,8 +536,12 @@ struct DType(
return sizeof[DType.index]()
if self == DType.float8e5m2:
return sizeof[DType.float8e5m2]()
+ if self == DType.float8e5m2fnuz:
+ return sizeof[DType.float8e5m2fnuz]()
if self == DType.float8e4m3:
return sizeof[DType.float8e4m3]()
+ if self == DType.float8e4m3fnuz:
+ return sizeof[DType.float8e4m3fnuz]()
if self == DType.bfloat16:
return sizeof[DType.bfloat16]()
if self == DType.float16:
@@ -482,9 +563,9 @@ struct DType(
"""
return 8 * self.sizeof()
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
# dispatch_integral
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
@always_inline
fn dispatch_integral[
@@ -519,9 +600,9 @@ struct DType(
else:
raise Error("only integral types are supported")
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
# dispatch_floating
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
@always_inline
fn dispatch_floating[
@@ -597,9 +678,9 @@ struct DType(
"dispatch_custom: dynamic_type does not match any dtype parameters"
)
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
# dispatch_arithmetic
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
@always_inline
fn dispatch_arithmetic[
diff --git a/stdlib/src/builtin/error.mojo b/stdlib/src/builtin/error.mojo
index c319e708ea..e282d56ba0 100644
--- a/stdlib/src/builtin/error.mojo
+++ b/stdlib/src/builtin/error.mojo
@@ -23,9 +23,9 @@ from memory.memory import _free
from utils import StringRef
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Error
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@register_passable
@@ -162,7 +162,7 @@ struct Error(
return String.write(self)
@no_inline
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""
Formats this error to the provided Writer.
diff --git a/stdlib/src/builtin/file.mojo b/stdlib/src/builtin/file.mojo
index 0803d4f3e0..f5f4e6e5f6 100644
--- a/stdlib/src/builtin/file.mojo
+++ b/stdlib/src/builtin/file.mojo
@@ -34,9 +34,10 @@ with open("my_file.txt", "r") as f:
from os import PathLike, abort
from sys import external_call, sizeof
from sys.ffi import OpaquePointer
-from utils import Span, StringRef, StringSlice, write_buffered
-from memory import AddressSpace, UnsafePointer
+from memory import AddressSpace, UnsafePointer, Span
+
+from utils import StringRef, StringSlice, write_buffered
@register_passable
@@ -111,7 +112,7 @@ struct FileHandle:
except:
pass
- fn close(inout self) raises:
+ fn close(mut self) raises:
"""Closes the file handle."""
if not self.handle:
return
@@ -404,7 +405,7 @@ struct FileHandle:
return pos
@always_inline
- fn write_bytes(inout self, bytes: Span[Byte, _]):
+ fn write_bytes(mut self, bytes: Span[Byte, _]):
"""
Write a span of bytes to the file.
@@ -422,7 +423,7 @@ struct FileHandle:
if err_msg:
abort(err_msg^.consume_as_error())
- fn write[*Ts: Writable](inout self, *args: *Ts):
+ fn write[*Ts: Writable](mut self, *args: *Ts):
"""Write a sequence of Writable arguments to the provided Writer.
Parameters:
@@ -436,7 +437,9 @@ struct FileHandle:
fn _write[
address_space: AddressSpace
- ](self, ptr: UnsafePointer[UInt8, address_space], len: Int) raises:
+ ](
+ self, ptr: UnsafePointer[UInt8, address_space=address_space], len: Int
+ ) raises:
"""Write the data to the file.
Params:
diff --git a/stdlib/src/builtin/file_descriptor.mojo b/stdlib/src/builtin/file_descriptor.mojo
index 241fa10bf3..fef115e471 100644
--- a/stdlib/src/builtin/file_descriptor.mojo
+++ b/stdlib/src/builtin/file_descriptor.mojo
@@ -23,11 +23,11 @@ f.close()
```
"""
-from utils import Span
-from builtin.io import _printf
from sys.ffi import external_call
-from sys.info import is_nvidia_gpu
-from memory import UnsafePointer
+from sys.info import is_gpu
+
+from builtin.io import _printf
+from memory import UnsafePointer, Span
@value
@@ -57,7 +57,7 @@ struct FileDescriptor(Writer):
self.value = f._get_raw_fd()
@always_inline
- fn write_bytes(inout self, bytes: Span[Byte, _]):
+ fn write_bytes(mut self, bytes: Span[Byte, _]):
"""
Write a span of bytes to the file.
@@ -67,7 +67,7 @@ struct FileDescriptor(Writer):
var len_bytes = len(bytes)
@parameter
- if is_nvidia_gpu():
+ if is_gpu():
_printf["%*s"](len_bytes, bytes.unsafe_ptr())
else:
written = external_call["write", Int32](
@@ -81,7 +81,7 @@ struct FileDescriptor(Writer):
written,
)
- fn write[*Ts: Writable](inout self, *args: *Ts):
+ fn write[*Ts: Writable](mut self, *args: *Ts):
"""Write a sequence of Writable arguments to the provided Writer.
Parameters:
diff --git a/stdlib/src/builtin/float_literal.mojo b/stdlib/src/builtin/float_literal.mojo
index 81308401b5..6cee98bafa 100644
--- a/stdlib/src/builtin/float_literal.mojo
+++ b/stdlib/src/builtin/float_literal.mojo
@@ -17,9 +17,9 @@ These are Mojo built-ins, so you don't need to import them.
from math import Ceilable, CeilDivable, Floorable, Truncable
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# FloatLiteral
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@value
@@ -466,7 +466,7 @@ struct FloatLiteral(
# ===------------------------------------------------------------------===#
@always_inline("nodebug")
- fn __iadd__(inout self, rhs: FloatLiteral):
+ fn __iadd__(mut self, rhs: FloatLiteral):
"""In-place addition operator.
Args:
@@ -475,7 +475,7 @@ struct FloatLiteral(
self = self + rhs
@always_inline("nodebug")
- fn __isub__(inout self, rhs: FloatLiteral):
+ fn __isub__(mut self, rhs: FloatLiteral):
"""In-place subtraction operator.
Args:
@@ -484,7 +484,7 @@ struct FloatLiteral(
self = self - rhs
@always_inline("nodebug")
- fn __imul__(inout self, rhs: FloatLiteral):
+ fn __imul__(mut self, rhs: FloatLiteral):
"""In-place multiplication operator.
Args:
@@ -493,7 +493,7 @@ struct FloatLiteral(
self = self * rhs
@always_inline("nodebug")
- fn __itruediv__(inout self, rhs: FloatLiteral):
+ fn __itruediv__(mut self, rhs: FloatLiteral):
"""In-place division.
Args:
diff --git a/stdlib/src/builtin/format_int.mojo b/stdlib/src/builtin/format_int.mojo
index 940ac43683..0598bb816a 100644
--- a/stdlib/src/builtin/format_int.mojo
+++ b/stdlib/src/builtin/format_int.mojo
@@ -16,16 +16,17 @@
These are Mojo built-ins, so you don't need to import them.
"""
+from collections import InlineArray, List, Optional
from os import abort
-from collections import List, Optional, InlineArray
-from utils import StringSlice, StaticString
+
+from utils import StaticString, StringSlice
alias _DEFAULT_DIGIT_CHARS = "0123456789abcdefghijklmnopqrstuvwxyz"
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# bin
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
fn bin(num: Scalar, /, *, prefix: StaticString = "0b") -> String:
@@ -81,9 +82,9 @@ fn bin[T: Indexer, //](num: T, /, *, prefix: StaticString = "0b") -> String:
return bin(Scalar[DType.index](index(num)), prefix=prefix)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# hex
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
fn hex(value: Scalar, /, *, prefix: StaticString = "0x") -> String:
@@ -143,9 +144,9 @@ fn hex(value: Scalar[DType.bool], /, *, prefix: StaticString = "0x") -> String:
return hex(value.cast[DType.int8](), prefix=prefix)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# oct
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
fn oct(value: Scalar, /, *, prefix: StaticString = "0o") -> String:
@@ -205,9 +206,9 @@ fn oct(value: Scalar[DType.bool], /, *, prefix: StaticString = "0o") -> String:
return oct(value.cast[DType.int8](), prefix=prefix)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Integer formatting utilities
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
fn _try_format_int(
@@ -248,7 +249,7 @@ fn _write_int[
type: DType,
W: Writer,
](
- inout writer: W,
+ mut writer: W,
value: Scalar[type],
/,
radix: Int = 10,
@@ -267,7 +268,7 @@ fn _try_write_int[
type: DType,
W: Writer,
](
- inout writer: W,
+ mut writer: W,
value: Scalar[type],
/,
radix: Int = 10,
diff --git a/stdlib/src/builtin/int.mojo b/stdlib/src/builtin/int.mojo
index 960ac5e00b..92cb98be75 100644
--- a/stdlib/src/builtin/int.mojo
+++ b/stdlib/src/builtin/int.mojo
@@ -16,23 +16,23 @@ These are Mojo built-ins, so you don't need to import them.
"""
from collections import KeyElement
-
-from math import Ceilable, CeilDivable, Floorable, Truncable
-from hashlib.hash import _hash_simd
-from hashlib._hasher import _HashableWithHasher, _Hasher
-from builtin.io import _snprintf
from collections.string import (
_calc_initial_buffer_size_int32,
_calc_initial_buffer_size_int64,
)
+from hashlib._hasher import _HashableWithHasher, _Hasher
+from hashlib.hash import _hash_simd
+from math import Ceilable, CeilDivable, Floorable, Truncable
+from sys import bitwidthof
+
+from builtin.io import _snprintf
+from memory import UnsafePointer
from python import Python, PythonObject
from python._cpython import Py_ssize_t
-from memory import UnsafePointer
from utils import Writable, Writer
-from utils._visualizers import lldb_formatter_wrapping_type
from utils._select import _select_register_value as select
-from sys import is_nvidia_gpu, bitwidthof
+from utils._visualizers import lldb_formatter_wrapping_type
# ===----------------------------------------------------------------------=== #
# Indexer
@@ -241,21 +241,39 @@ fn int[T: IntableRaising](value: T) raises -> Int:
fn int(value: String, base: Int = 10) raises -> Int:
- """Parses the given string as an integer in the given base and returns that value.
+ """Parses and returns the given string as an integer in the given base.
- For example, `atol("19")` returns `19`. If the given string cannot be parsed
- as an integer value, an error is raised. For example, `atol("hi")` raises an
- error.
-
- If base is 0 the the string is parsed as an Integer literal,
- see: https://docs.python.org/3/reference/lexical_analysis.html#integers
+ If base is set to 0, the string is parsed as an Integer literal, with the
+ following considerations:
+ - '0b' or '0B' prefix indicates binary (base 2)
+ - '0o' or '0O' prefix indicates octal (base 8)
+ - '0x' or '0X' prefix indicates hexadecimal (base 16)
+ - Without a prefix, it's treated as decimal (base 10)
Args:
value: A string to be parsed as an integer in the given base.
base: Base used for conversion, value must be between 2 and 36, or 0.
Returns:
- An integer value that represents the string, or otherwise raises.
+ An integer value that represents the string.
+
+ Raises:
+ If the given string cannot be parsed as an integer value or if an
+ incorrect base is provided.
+
+ Examples:
+ >>> int("32")
+ 32
+ >>> int("FF", 16)
+ 255
+ >>> int("0xFF", 0)
+ 255
+ >>> int("0b1010", 0)
+ 10
+
+ Notes:
+ This follows [Python's integer literals](
+ https://docs.python.org/3/reference/lexical_analysis.html#integers).
"""
return atol(value, base)
@@ -400,7 +418,7 @@ struct Int(
@always_inline("nodebug")
@implicit
- fn __init__[IndexerTy: Indexer](inout self, value: IndexerTy):
+ fn __init__[IndexerTy: Indexer](mut self, value: IndexerTy):
"""Construct Int from the given Indexer value.
Parameters:
@@ -742,12 +760,12 @@ struct Int(
"""
return __mlir_op.`index.or`(self.value, rhs.value)
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
# In place operations.
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
@always_inline("nodebug")
- fn __iadd__(inout self, rhs: Int):
+ fn __iadd__(mut self, rhs: Int):
"""Compute `self + rhs` and save the result in self.
Args:
@@ -756,7 +774,7 @@ struct Int(
self = self + rhs
@always_inline("nodebug")
- fn __isub__(inout self, rhs: Int):
+ fn __isub__(mut self, rhs: Int):
"""Compute `self - rhs` and save the result in self.
Args:
@@ -765,7 +783,7 @@ struct Int(
self = self - rhs
@always_inline("nodebug")
- fn __imul__(inout self, rhs: Int):
+ fn __imul__(mut self, rhs: Int):
"""Compute self*rhs and save the result in self.
Args:
@@ -773,7 +791,7 @@ struct Int(
"""
self = self * rhs
- fn __itruediv__(inout self, rhs: Int):
+ fn __itruediv__(mut self, rhs: Int):
"""Compute `self / rhs`, convert to int, and save the result in self.
Since `floor(self / rhs)` is equivalent to `self // rhs`, this yields
@@ -785,7 +803,7 @@ struct Int(
self = self // rhs
@always_inline("nodebug")
- fn __ifloordiv__(inout self, rhs: Int):
+ fn __ifloordiv__(mut self, rhs: Int):
"""Compute `self // rhs` and save the result in self.
Args:
@@ -793,7 +811,7 @@ struct Int(
"""
self = self // rhs
- fn __imod__(inout self, rhs: Int):
+ fn __imod__(mut self, rhs: Int):
"""Compute `self % rhs` and save the result in self.
Args:
@@ -802,7 +820,7 @@ struct Int(
self = self % rhs
@always_inline("nodebug")
- fn __ipow__(inout self, rhs: Int):
+ fn __ipow__(mut self, rhs: Int):
"""Compute `pow(self, rhs)` and save the result in self.
Args:
@@ -811,7 +829,7 @@ struct Int(
self = self**rhs
@always_inline("nodebug")
- fn __ilshift__(inout self, rhs: Int):
+ fn __ilshift__(mut self, rhs: Int):
"""Compute `self << rhs` and save the result in self.
Args:
@@ -820,7 +838,7 @@ struct Int(
self = self << rhs
@always_inline("nodebug")
- fn __irshift__(inout self, rhs: Int):
+ fn __irshift__(mut self, rhs: Int):
"""Compute `self >> rhs` and save the result in self.
Args:
@@ -829,7 +847,7 @@ struct Int(
self = self >> rhs
@always_inline("nodebug")
- fn __iand__(inout self, rhs: Int):
+ fn __iand__(mut self, rhs: Int):
"""Compute `self & rhs` and save the result in self.
Args:
@@ -838,7 +856,7 @@ struct Int(
self = self & rhs
@always_inline("nodebug")
- fn __ixor__(inout self, rhs: Int):
+ fn __ixor__(mut self, rhs: Int):
"""Compute `self ^ rhs` and save the result in self.
Args:
@@ -847,7 +865,7 @@ struct Int(
self = self ^ rhs
@always_inline("nodebug")
- fn __ior__(inout self, rhs: Int):
+ fn __ior__(mut self, rhs: Int):
"""Compute self|rhs and save the result in self.
Args:
@@ -855,9 +873,9 @@ struct Int(
"""
self = self | rhs
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
# Reversed operations
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
@always_inline("nodebug")
fn __radd__(self, value: Int) -> Int:
@@ -1123,7 +1141,7 @@ struct Int(
# TODO(MOCO-636): switch to DType.index
return _hash_simd(Scalar[DType.int64](self))
- fn __hash__[H: _Hasher](self, inout hasher: H):
+ fn __hash__[H: _Hasher](self, mut hasher: H):
"""Updates hasher with this int value.
Parameters:
@@ -1136,7 +1154,7 @@ struct Int(
@doc_private
@staticmethod
- fn try_from_python(obj: PythonObject) raises -> Self as result:
+ fn try_from_python(obj: PythonObject, out result: Self) raises:
"""Construct an `Int` from a Python integer value.
Raises:
@@ -1162,7 +1180,7 @@ struct Int(
# Methods
# ===-------------------------------------------------------------------===#
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""
Formats this integer to the provided Writer.
@@ -1175,7 +1193,7 @@ struct Int(
writer.write(Int64(self))
- fn write_padded[W: Writer](self, inout writer: W, width: Int):
+ fn write_padded[W: Writer](self, mut writer: W, width: Int):
"""Write the int right-aligned to a set padding.
Parameters:
diff --git a/stdlib/src/builtin/int_literal.mojo b/stdlib/src/builtin/int_literal.mojo
index 0432c933d3..3d50918458 100644
--- a/stdlib/src/builtin/int_literal.mojo
+++ b/stdlib/src/builtin/int_literal.mojo
@@ -373,12 +373,12 @@ struct IntLiteral(
](self.value, rhs.value)
)
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
# In place operations.
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
@always_inline("nodebug")
- fn __iadd__(inout self, rhs: Self):
+ fn __iadd__(mut self, rhs: Self):
"""Compute `self + rhs` and save the result in self.
Args:
@@ -387,7 +387,7 @@ struct IntLiteral(
self = self + rhs
@always_inline("nodebug")
- fn __isub__(inout self, rhs: Self):
+ fn __isub__(mut self, rhs: Self):
"""Compute `self - rhs` and save the result in self.
Args:
@@ -396,7 +396,7 @@ struct IntLiteral(
self = self - rhs
@always_inline("nodebug")
- fn __imul__(inout self, rhs: Self):
+ fn __imul__(mut self, rhs: Self):
"""Compute self*rhs and save the result in self.
Args:
@@ -405,7 +405,7 @@ struct IntLiteral(
self = self * rhs
@always_inline("nodebug")
- fn __ifloordiv__(inout self, rhs: Self):
+ fn __ifloordiv__(mut self, rhs: Self):
"""Compute self//rhs and save the result in self.
Args:
@@ -414,7 +414,7 @@ struct IntLiteral(
self = self // rhs
@always_inline("nodebug")
- fn __ilshift__(inout self, rhs: Self):
+ fn __ilshift__(mut self, rhs: Self):
"""Compute `self << rhs` and save the result in self.
Args:
@@ -423,7 +423,7 @@ struct IntLiteral(
self = self << rhs
@always_inline("nodebug")
- fn __irshift__(inout self, rhs: Self):
+ fn __irshift__(mut self, rhs: Self):
"""Compute `self >> rhs` and save the result in self.
Args:
@@ -432,7 +432,7 @@ struct IntLiteral(
self = self >> rhs
@always_inline("nodebug")
- fn __iand__(inout self, rhs: Self):
+ fn __iand__(mut self, rhs: Self):
"""Compute `self & rhs` and save the result in self.
Args:
@@ -441,7 +441,7 @@ struct IntLiteral(
self = self & rhs
@always_inline("nodebug")
- fn __ixor__(inout self, rhs: Self):
+ fn __ixor__(mut self, rhs: Self):
"""Compute `self ^ rhs` and save the result in self.
Args:
@@ -450,7 +450,7 @@ struct IntLiteral(
self = self ^ rhs
@always_inline("nodebug")
- fn __ior__(inout self, rhs: Self):
+ fn __ior__(mut self, rhs: Self):
"""Compute self|rhs and save the result in self.
Args:
@@ -458,9 +458,9 @@ struct IntLiteral(
"""
self = self | rhs
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
# Reversed operations
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
@always_inline("nodebug")
fn __radd__(self, value: Self) -> Self:
@@ -717,9 +717,9 @@ struct IntLiteral(
"""
return -(self // -denominator)
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
# Methods
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
@always_inline("nodebug")
fn _bit_width(self) -> IntLiteral:
diff --git a/stdlib/src/builtin/io.mojo b/stdlib/src/builtin/io.mojo
index c2d3f82a33..bb15718f20 100644
--- a/stdlib/src/builtin/io.mojo
+++ b/stdlib/src/builtin/io.mojo
@@ -15,23 +15,30 @@
These are Mojo built-ins, so you don't need to import them.
"""
+from collections import InlineArray
+from sys import _libc as libc
from sys import (
bitwidthof,
external_call,
- stdout,
+ is_amd_gpu,
+ is_gpu,
is_nvidia_gpu,
- _libc as libc,
+ stdout,
)
from sys._libc import dup, fclose, fdopen, fflush
from sys.ffi import OpaquePointer
-from utils import Span, write_buffered, write_args
-from collections import InlineArray
from builtin.dtype import _get_dtype_printf_format
from builtin.file_descriptor import FileDescriptor
from memory import UnsafePointer, memcpy
-from utils import StringRef, StaticString, StringSlice
+from utils import (
+ StaticString,
+ StringRef,
+ StringSlice,
+ write_args,
+ write_buffered,
+)
# ===----------------------------------------------------------------------=== #
# _file_handle
@@ -170,6 +177,9 @@ fn _printf[
_ = external_call["vprintf", Int32](
fmt.unsafe_cstr_ptr(), Pointer.address_of(loaded_pack)
)
+ elif is_amd_gpu():
+ # constrained[False, "_printf on AMDGPU is not implemented"]()
+ pass
else:
with _fdopen(file) as fd:
_ = __mlir_op.`pop.external_call`[
@@ -255,10 +265,16 @@ fn print[
flush: If set to true, then the stream is forcibly flushed.
file: The output stream.
"""
+
+ # TODO(MSTDL-1027): Print on AMD GPUs is not implemented yet.
+ @parameter
+ if is_amd_gpu():
+ return
+
write_buffered[buffer_size=4096](file, values, sep=sep, end=end)
@parameter
- if not is_nvidia_gpu():
+ if not is_gpu():
if flush:
_flush(file=file)
diff --git a/stdlib/src/builtin/math.mojo b/stdlib/src/builtin/math.mojo
index eb1b088242..428407f857 100644
--- a/stdlib/src/builtin/math.mojo
+++ b/stdlib/src/builtin/math.mojo
@@ -182,7 +182,7 @@ fn max(x: SIMD, y: __type_of(x), /) -> __type_of(x):
corresponding elements in x and y.
Constraints:
- The type of the inputs must be numeric.
+ The type of the inputs must be numeric or boolean.
Args:
x: First SIMD vector.
@@ -191,8 +191,16 @@ fn max(x: SIMD, y: __type_of(x), /) -> __type_of(x):
Returns:
A SIMD vector containing the elementwise maximum of x and y.
"""
- constrained[x.type.is_numeric(), "the SIMD type must be numeric"]()
- return __mlir_op.`pop.max`(x.value, y.value)
+
+ @parameter
+ if x.type is DType.bool:
+ return max(x.cast[DType.uint8](), y.cast[DType.uint8]()).cast[x.type]()
+ else:
+ constrained[
+ x.type.is_numeric(), "the SIMD type must be numeric or boolean"
+ ]()
+
+ return __mlir_op.`pop.max`(x.value, y.value)
# ===----------------------------------------------------------------------=== #
@@ -236,7 +244,7 @@ fn min(x: SIMD, y: __type_of(x), /) -> __type_of(x):
corresponding elements in x and y.
Constraints:
- The type of the inputs must be numeric.
+ The type of the inputs must be numeric or boolean.
Args:
x: First SIMD vector.
@@ -245,8 +253,16 @@ fn min(x: SIMD, y: __type_of(x), /) -> __type_of(x):
Returns:
A SIMD vector containing the elementwise minimum of x and y.
"""
- constrained[x.type.is_numeric(), "the SIMD type must be numeric"]()
- return __mlir_op.`pop.min`(x.value, y.value)
+
+ @parameter
+ if x.type is DType.bool:
+ return min(x.cast[DType.uint8](), y.cast[DType.uint8]()).cast[x.type]()
+ else:
+ constrained[
+ x.type.is_numeric(), "the SIMD type must be numeric or boolean"
+ ]()
+
+ return __mlir_op.`pop.min`(x.value, y.value)
# ===----------------------------------------------------------------------=== #
diff --git a/stdlib/src/builtin/none.mojo b/stdlib/src/builtin/none.mojo
index 3cfc856b32..2e5dc6ef35 100644
--- a/stdlib/src/builtin/none.mojo
+++ b/stdlib/src/builtin/none.mojo
@@ -75,7 +75,7 @@ struct NoneType(
return "None"
@no_inline
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""Write `None` to a writer stream.
Parameters:
diff --git a/stdlib/src/builtin/object.mojo b/stdlib/src/builtin/object.mojo
index c54d99fc18..fce05d2476 100644
--- a/stdlib/src/builtin/object.mojo
+++ b/stdlib/src/builtin/object.mojo
@@ -16,10 +16,10 @@ These are Mojo built-ins, so you don't need to import them.
"""
from collections import Dict, List
-from sys.intrinsics import _type_is_eq
from sys.ffi import OpaquePointer
+from sys.intrinsics import _type_is_eq
-from memory import Arc, memcmp, memcpy, UnsafePointer
+from memory import ArcPointer, UnsafePointer, memcmp, memcpy
from utils import StringRef, Variant
@@ -75,11 +75,11 @@ struct _RefCountedList:
ref-counted data types.
"""
- var impl: Arc[List[_ObjectImpl]]
+ var impl: ArcPointer[List[_ObjectImpl]]
"""The list value."""
fn __init__(out self):
- self.impl = Arc[List[_ObjectImpl]](List[_ObjectImpl]())
+ self.impl = ArcPointer[List[_ObjectImpl]](List[_ObjectImpl]())
@register_passable("trivial")
@@ -115,16 +115,16 @@ struct _RefCountedAttrsDict:
directly with `x.attr`, the key will always be a `StringLiteral`.
"""
- var impl: Arc[Dict[StringLiteral, _ObjectImpl]]
+ var impl: ArcPointer[Dict[StringLiteral, _ObjectImpl]]
"""The implementation of the map."""
fn __init__(out self):
- self.impl = Arc[Dict[StringLiteral, _ObjectImpl]](
+ self.impl = ArcPointer[Dict[StringLiteral, _ObjectImpl]](
Dict[StringLiteral, _ObjectImpl]()
)
@always_inline
- fn set(inout self, key: StringLiteral, value: _ObjectImpl) raises:
+ fn set(mut self, key: StringLiteral, value: _ObjectImpl) raises:
if key in self.impl[]:
self.impl[][key].destroy()
self.impl[][key] = value
@@ -210,7 +210,7 @@ struct _Function(CollectionElement, CollectionElementNew):
"""The function pointer."""
@always_inline
- fn __init__[FnT: AnyTrivialRegType](inout self, value: FnT):
+ fn __init__[FnT: AnyTrivialRegType](mut self, value: FnT):
# FIXME: No "pointer bitcast" for signature function pointers.
var f = UnsafePointer[Int16]()
UnsafePointer.address_of(f).bitcast[FnT]()[] = value
@@ -320,7 +320,8 @@ struct _ObjectImpl(
self.value = Self.type(value)
@always_inline
- fn __init__[dt: DType](inout self, value: SIMD[dt, 1]):
+ @implicit
+ fn __init__[dt: DType](mut self, value: SIMD[dt, 1]):
@parameter
if dt.is_integral():
self.value = Self.type(value)
@@ -517,7 +518,7 @@ struct _ObjectImpl(
return self.get_as_int().cast[DType.float64]()
@staticmethod
- fn coerce_comparison_type(inout lhs: _ObjectImpl, inout rhs: _ObjectImpl):
+ fn coerce_comparison_type(mut lhs: _ObjectImpl, mut rhs: _ObjectImpl):
"""Coerces two values of arithmetic type to the appropriate
lowest-common denominator type for performing comparisons, in order of
increasing priority: bool, int, and then float.
@@ -528,7 +529,7 @@ struct _ObjectImpl(
return
@parameter
- fn convert(inout value: _ObjectImpl, id: Int, to: Int):
+ fn convert(mut value: _ObjectImpl, id: Int, to: Int):
if to == Self.int:
value = value.convert_bool_to_int()
else:
@@ -543,7 +544,7 @@ struct _ObjectImpl(
convert(lhs, lhsId, rhsId)
@staticmethod
- fn coerce_arithmetic_type(inout lhs: _ObjectImpl, inout rhs: _ObjectImpl):
+ fn coerce_arithmetic_type(mut lhs: _ObjectImpl, mut rhs: _ObjectImpl):
"""Coerces two values of arithmetic type to the appropriate
lowest-common denominator type for performing arithmetic operations.
Bools are always converted to integers, to match Python's behavior.
@@ -560,7 +561,7 @@ struct _ObjectImpl(
lhs = lhs.convert_int_to_float()
@staticmethod
- fn coerce_integral_type(inout lhs: _ObjectImpl, inout rhs: _ObjectImpl):
+ fn coerce_integral_type(mut lhs: _ObjectImpl, mut rhs: _ObjectImpl):
"""Coerces two values of integral type to the appropriate
lowest-common denominator type for performing bitwise operations.
"""
@@ -571,7 +572,7 @@ struct _ObjectImpl(
else:
lhs = lhs.convert_bool_to_int()
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""Performs conversion to string according to Python
semantics.
"""
@@ -653,7 +654,7 @@ struct _ObjectImpl(
# ===------------------------------------------------------------------=== #
@always_inline
- fn get_list_ptr(self) -> Arc[List[_ObjectImpl]]:
+ fn get_list_ptr(self) -> ArcPointer[List[_ObjectImpl]]:
return self.get_as_list().lst.bitcast[_RefCountedList]()[].impl
@always_inline
@@ -785,7 +786,8 @@ struct object(
self._value = value
@always_inline
- fn __init__[dt: DType](inout self, value: SIMD[dt, 1]):
+ @implicit
+ fn __init__[dt: DType](mut self, value: SIMD[dt, 1]):
"""Initializes the object with a generic scalar value. If the scalar
value type is bool, it is converted to a boolean. Otherwise, it is
converted to the appropriate integer or floating point type.
@@ -842,7 +844,8 @@ struct object(
self._value = impl
@always_inline
- fn __init__[*Ts: CollectionElement](inout self, value: ListLiteral[*Ts]):
+ @implicit
+ fn __init__[*Ts: CollectionElement](mut self, value: ListLiteral[*Ts]):
"""Initializes the object from a list literal.
Parameters:
@@ -1003,7 +1006,7 @@ struct object(
"""
return self.__bool__()
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""Performs conversion to string according to Python
semantics.
@@ -1537,7 +1540,7 @@ struct object(
# ===------------------------------------------------------------------=== #
@always_inline
- fn __iadd__(inout self, rhs: object) raises:
+ fn __iadd__(mut self, rhs: object) raises:
"""In-place addition or concatenation operator.
Args:
@@ -1546,7 +1549,7 @@ struct object(
self = self + rhs
@always_inline
- fn __isub__(inout self, rhs: object) raises:
+ fn __isub__(mut self, rhs: object) raises:
"""In-place subtraction operator.
Args:
@@ -1555,7 +1558,7 @@ struct object(
self = self - rhs
@always_inline
- fn __imul__(inout self, rhs: object) raises:
+ fn __imul__(mut self, rhs: object) raises:
"""In-place multiplication operator.
Args:
@@ -1564,7 +1567,7 @@ struct object(
self = self * rhs
@always_inline
- fn __ipow__(inout self, rhs: object) raises:
+ fn __ipow__(mut self, rhs: object) raises:
"""In-place exponentiation operator.
Args:
@@ -1573,7 +1576,7 @@ struct object(
self = self**rhs
@always_inline
- fn __imod__(inout self, rhs: object) raises:
+ fn __imod__(mut self, rhs: object) raises:
"""In-place modulo operator.
Args:
@@ -1582,7 +1585,7 @@ struct object(
self = self % rhs
@always_inline
- fn __itruediv__(inout self, rhs: object) raises:
+ fn __itruediv__(mut self, rhs: object) raises:
"""In-place true division operator.
Args:
@@ -1591,7 +1594,7 @@ struct object(
self = self / rhs
@always_inline
- fn __ifloordiv__(inout self, rhs: object) raises:
+ fn __ifloordiv__(mut self, rhs: object) raises:
"""In-place floor division operator.
Args:
@@ -1600,7 +1603,7 @@ struct object(
self = self // rhs
@always_inline
- fn __ilshift__(inout self, rhs: object) raises:
+ fn __ilshift__(mut self, rhs: object) raises:
"""In-place left shift operator.
Args:
@@ -1609,7 +1612,7 @@ struct object(
self = self << rhs
@always_inline
- fn __irshift__(inout self, rhs: object) raises:
+ fn __irshift__(mut self, rhs: object) raises:
"""In-place right shift operator.
Args:
@@ -1618,7 +1621,7 @@ struct object(
self = self >> rhs
@always_inline
- fn __iand__(inout self, rhs: object) raises:
+ fn __iand__(mut self, rhs: object) raises:
"""In-place AND operator.
Args:
@@ -1627,7 +1630,7 @@ struct object(
self = self & rhs
@always_inline
- fn __ior__(inout self, rhs: object) raises:
+ fn __ior__(mut self, rhs: object) raises:
"""In-place OR operator.
Args:
@@ -1636,7 +1639,7 @@ struct object(
self = self | rhs
@always_inline
- fn __ixor__(inout self, rhs: object) raises:
+ fn __ixor__(mut self, rhs: object) raises:
"""In-place XOR operator.
Args:
@@ -1861,7 +1864,7 @@ struct object(
var impl = _ImmutableString(UnsafePointer[UInt8].alloc(1), 1)
var char = self._value.get_as_string().data[index]
impl.data.init_pointee_move(char)
- return _ObjectImpl(impl)
+ return object(impl)
return self._value.get_list_element(i._value.get_as_int().value)
@always_inline
@@ -1936,7 +1939,7 @@ struct object(
return self._value.get_obj_attr(key)
@always_inline
- fn __setattr__(inout self, key: StringLiteral, value: object) raises:
+ fn __setattr__(mut self, key: StringLiteral, value: object) raises:
"""Sets the named attribute.
Args:
diff --git a/stdlib/src/builtin/range.mojo b/stdlib/src/builtin/range.mojo
index b97b8c1586..3bc6b6c96d 100644
--- a/stdlib/src/builtin/range.mojo
+++ b/stdlib/src/builtin/range.mojo
@@ -16,12 +16,14 @@ These are Mojo built-ins, so you don't need to import them.
"""
+from math import ceildiv
+
# FIXME(MOCO-658): Explicit conformance to these traits shouldn't be needed.
from builtin._stubs import _IntIterable, _StridedIterable, _UIntStridedIterable
from python import (
PythonObject,
) # TODO: remove this and fixup downstream imports
-from math import ceildiv
+
from utils._select import _select_register_value as select
from utils.string_slice import StringSlice, _StringSliceIter, Stringlike
from collections.list import _ListIter
@@ -67,7 +69,7 @@ struct _ZeroStartingRange(Sized, ReversibleRange, _IntIterable):
return self
@always_inline
- fn __next__(inout self) -> Int:
+ fn __next__(mut self) -> Int:
var curr = self.curr
self.curr -= 1
return self.end - curr
@@ -101,7 +103,7 @@ struct _SequentialRange(Sized, ReversibleRange, _IntIterable):
return self
@always_inline
- fn __next__(inout self) -> Int:
+ fn __next__(mut self) -> Int:
var start = self.start
self.start += 1
return start
@@ -141,7 +143,7 @@ struct _StridedRangeIterator(Sized):
return 0
@always_inline
- fn __next__(inout self) -> Int:
+ fn __next__(mut self) -> Int:
var result = self.start
self.start += self.step
return result
@@ -169,7 +171,7 @@ struct _StridedRange(Sized, ReversibleRange, _StridedIterable):
return _StridedRangeIterator(self.start, self.end, self.step)
@always_inline
- fn __next__(inout self) -> Int:
+ fn __next__(mut self) -> Int:
var result = self.start
self.start += self.step
return result
@@ -344,7 +346,7 @@ struct _UIntZeroStartingRange(UIntSized):
return self
@always_inline
- fn __next__(inout self) -> UInt:
+ fn __next__(mut self) -> UInt:
var curr = self.curr
self.curr -= 1
return self.end - curr
@@ -375,7 +377,7 @@ struct _UIntStridedRangeIterator(UIntSized):
return select(self.start < self.end, self.end - self.start, 0)
@always_inline
- fn __next__(inout self) -> UInt:
+ fn __next__(mut self) -> UInt:
var result = self.start
self.start += self.step
return result
@@ -413,7 +415,7 @@ struct _UIntStridedRange(UIntSized, _UIntStridedIterable):
return _UIntStridedRangeIterator(self.start, self.end, self.step)
@always_inline
- fn __next__(inout self) -> UInt:
+ fn __next__(mut self) -> UInt:
if self.start >= self.end:
return self.end
var result = self.start
@@ -485,7 +487,7 @@ struct _ZeroStartingScalarRange[type: DType]:
return self
@always_inline
- fn __next__(inout self) -> Scalar[type]:
+ fn __next__(mut self) -> Scalar[type]:
var curr = self.curr
self.curr -= 1
return self.end - curr
@@ -522,7 +524,7 @@ struct _SequentialScalarRange[type: DType]:
return self
@always_inline
- fn __next__(inout self) -> Scalar[type]:
+ fn __next__(mut self) -> Scalar[type]:
var start = self.start
self.start += 1
return start
@@ -564,7 +566,7 @@ struct _StridedScalarRangeIterator[type: DType]:
return self.end < self.start
@always_inline
- fn __next__(inout self) -> Scalar[type]:
+ fn __next__(mut self) -> Scalar[type]:
var result = self.start
self.start += self.step
return result
diff --git a/stdlib/src/builtin/reversed.mojo b/stdlib/src/builtin/reversed.mojo
index 50713bd26d..399aa1f859 100644
--- a/stdlib/src/builtin/reversed.mojo
+++ b/stdlib/src/builtin/reversed.mojo
@@ -19,6 +19,7 @@ from collections import Deque, Dict
from collections.deque import _DequeIter
from collections.dict import _DictEntryIter, _DictKeyIter, _DictValueIter
from collections.list import _ListIter
+from memory.span import Span, _SpanIter
from utils.string_slice import _StringSliceIter, StringSlice, Stringlike
from .range import _StridedRange
@@ -137,7 +138,7 @@ fn reversed[
K: KeyElement,
V: CollectionElement,
dict_mutability: Bool,
- dict_origin: Origin[dict_mutability].type,
+ dict_origin: Origin[dict_mutability],
](ref value: _DictValueIter[K, V, dict_origin]) -> _DictValueIter[
K, V, dict_origin, False
]:
@@ -162,7 +163,7 @@ fn reversed[
K: KeyElement,
V: CollectionElement,
dict_mutability: Bool,
- dict_origin: Origin[dict_mutability].type,
+ dict_origin: Origin[dict_mutability],
](ref value: _DictEntryIter[K, V, dict_origin]) -> _DictEntryIter[
K, V, dict_origin, False
]:
@@ -186,6 +187,26 @@ fn reversed[
)
+@always_inline
+fn reversed[
+ T: CollectionElement
+](value: Span[T]) -> _SpanIter[T, value.origin, forward=False]:
+ """Get a reversed iterator of the input Span.
+
+ **Note**: iterators are currently non-raising.
+
+ Parameters:
+ T: The type of the elements in the Span.
+
+ Args:
+ value: The Span to get the reversed iterator of.
+
+ Returns:
+ The reversed iterator of the Span.
+ """
+ return value.__reversed__()
+
+
@always_inline
fn reversed[
T: Stringlike
diff --git a/stdlib/src/builtin/simd.mojo b/stdlib/src/builtin/simd.mojo
index 9d9fe69a00..d93be3a050 100644
--- a/stdlib/src/builtin/simd.mojo
+++ b/stdlib/src/builtin/simd.mojo
@@ -16,36 +16,43 @@ These are Mojo built-ins, so you don't need to import them.
"""
import math
+from collections import InlineArray
+from collections.string import (
+ _calc_format_buffer_size,
+ _calc_initial_buffer_size,
+)
+from hashlib._hasher import _HashableWithHasher, _Hasher
+from hashlib.hash import _hash_simd
+from math import Ceilable, CeilDivable, Floorable, Truncable
from math.math import _call_ptx_intrinsic
+from os import abort
from sys import (
PrefetchOptions,
_RegisterPackType,
+ alignof,
+ bitwidthof,
has_neon,
+ is_amd_gpu,
+ is_gpu,
+ is_nvidia_gpu,
is_x86,
llvm_intrinsic,
prefetch,
simdwidthof,
- is_nvidia_gpu,
- bitwidthof,
+ sizeof,
)
-from sys.info import _current_arch, _is_sm_8x, _is_sm_9x
-
from sys._assembly import inlined_assembly
-from os import abort
+from sys.info import _current_arch, _is_sm_8x, _is_sm_9x
from bit import pop_count
-from documentation import doc_private
-from math import Ceilable, CeilDivable, Floorable, Truncable
+from builtin._format_float import _write_float
from builtin.dtype import _uint_type_of_width
-from hashlib.hash import _hash_simd
-from hashlib._hasher import _HashableWithHasher, _Hasher
from builtin.format_int import _try_write_int
-from builtin._format_float import _write_float
from builtin.io import _snprintf
-from collections import InlineArray
-from memory import bitcast, UnsafePointer
+from documentation import doc_private
+from memory import UnsafePointer, bitcast, Span
-from utils import StringSlice, StaticTuple, IndexList, Span
+from utils import IndexList, StaticTuple, StringSlice
from utils._visualizers import lldb_formatter_wrapping_type
from utils.numerics import FPUtils
from utils.numerics import isnan as _isnan
@@ -54,17 +61,12 @@ from utils.numerics import max_or_inf as _max_or_inf
from utils.numerics import min_finite as _min_finite
from utils.numerics import min_or_neg_inf as _min_or_neg_inf
from utils.numerics import nan as _nan
-from sys import sizeof, alignof
from .dtype import (
_get_dtype_printf_format,
_integral_type_of,
- _unsigned_integral_type_of,
_scientific_notation_digits,
-)
-from collections.string import (
- _calc_format_buffer_size,
- _calc_initial_buffer_size,
+ _unsigned_integral_type_of,
)
# ===----------------------------------------------------------------------=== #
@@ -92,9 +94,59 @@ alias UInt64 = Scalar[DType.uint64]
"""Represents a 64-bit unsigned scalar integer."""
alias Float8e5m2 = Scalar[DType.float8e5m2]
-"""Represents a FP8E5M2 floating point format whose bitwidth is 8."""
+"""Represents a FP8E5M2 floating point format from the [OFP8
+standard](https://www.opencompute.org/documents/ocp-8-bit-floating-point-specification-ofp8-revision-1-0-2023-12-01-pdf-1).
+
+The 8 bits are encoded as `seeeeemm`:
+- (s)ign: 1 bit
+- (e)xponent: 5 bits
+- (m)antissa: 2 bits
+- exponent bias: 15
+- nan: {0,1}11111{01,10,11}
+- inf: 01111100
+- -inf: 11111100
+- -0: 10000000
+"""
+alias Float8e5m2fnuz = Scalar[DType.float8e5m2fnuz]
+"""Represents a FP8E5M2FNUZ floating point format.
+
+The 8 bits are encoded as `seeeeemm`:
+- (s)ign: 1 bit
+- (e)xponent: 5 bits
+- (m)antissa: 2 bits
+- exponent bias: 16
+- nan: 10000000
+- fn: finite (no inf or -inf encodings)
+- uz: unsigned zero (no -0 encoding)
+"""
alias Float8e4m3 = Scalar[DType.float8e4m3]
-"""Represents a FP8E4M3 floating point format whose bitwidth is 8."""
+"""Represents a FP8E4M3 floating point format from the [OFP8
+standard](https://www.opencompute.org/documents/ocp-8-bit-floating-point-specification-ofp8-revision-1-0-2023-12-01-pdf-1).
+
+This type is named `float8_e4m3fn` (the "fn" stands for "finite") in some
+frameworks, as it does not encode -inf or inf.
+
+The 8 bits are encoded as `seeeemmm`:
+- (s)ign: 1 bit
+- (e)xponent: 4 bits
+- (m)antissa: 3 bits
+- exponent bias: 7
+- nan: 01111111, 11111111
+- -0: 10000000
+- fn: finite (no inf or -inf encodings)
+"""
+alias Float8e4m3fnuz = Scalar[DType.float8e4m3fnuz]
+"""Represents a FP8E4M3FNUZ floating point format.
+
+The 8 bits are encoded as `seeeemmm`:
+- (s)ign: 1 bit
+- (e)xponent: 4 bits
+- (m)antissa: 3 bits
+- exponent bias: 8
+- nan: 10000000
+- fn: finite (no inf or -inf encodings)
+- uz: unsigned zero (no -0 encoding)
+"""
alias BFloat16 = Scalar[DType.bfloat16]
"""Represents a 16-bit brain floating point value."""
alias Float16 = Scalar[DType.float16]
@@ -135,6 +187,13 @@ fn _simd_construction_checks[type: DType, size: Int]():
not (type.is_float8() and not _has_native_f8_support()),
"f8 is not supported on non sm_89 and sm_90 architectures",
]()
+ constrained[
+ not (
+ type in (DType.float8e4m3fnuz, DType.float8e5m2fnuz)
+ and not is_amd_gpu()
+ ),
+ "f8 fnuz variants is only supported for AMD GPU.",
+ ]()
@always_inline("nodebug")
@@ -156,12 +215,12 @@ fn _unchecked_zero[type: DType, size: Int]() -> SIMD[type, size]:
@always_inline("nodebug")
fn _has_native_bf16_support() -> Bool:
- return is_nvidia_gpu()
+ return is_gpu()
@always_inline("nodebug")
fn _has_native_f8_support() -> Bool:
- return _is_sm_9x() or is_nvidia_gpu["sm_89"]()
+ return _is_sm_9x() or is_nvidia_gpu["sm_89"]() or is_amd_gpu()
# ===----------------------------------------------------------------------=== #
@@ -222,7 +281,7 @@ struct SIMD[type: DType, size: Int](
alias MIN_FINITE = Self(_min_finite[type]())
"""Returns the minimum (lowest) finite value of SIMD value."""
- alias _default_alignment = alignof[Scalar[type]]() if is_nvidia_gpu() else 1
+ alias _default_alignment = alignof[Scalar[type]]() if is_gpu() else 1
# ===-------------------------------------------------------------------===#
# Life cycle methods
@@ -337,7 +396,7 @@ struct SIMD[type: DType, size: Int](
@always_inline("nodebug")
@implicit
fn __init__(
- inout self,
+ mut self,
value: __mlir_type[`!pop.simd<`, size.value, `, `, type.value, `>`],
):
"""Initializes the SIMD vector with the underlying mlir value.
@@ -424,16 +483,86 @@ struct SIMD[type: DType, size: Int](
# TODO (#36686): This introduces unneeded casts here to work around
# parameter if issues.
@parameter
- if type is DType.float16:
+ if type is DType.float8e4m3:
self = SIMD[type, size](
__mlir_op.`pop.simd.splat`[
_type = __mlir_type[
`!pop.simd<`, size.value, `,`, type.value, `>`
]
](
- __mlir_op.`pop.cast`[
- _type = __mlir_type[`!pop.scalar<`, type.value, `>`]
- ](
+ rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
+ __mlir_op.`pop.cast_from_builtin`[
+ _type = __mlir_type[`!pop.scalar`]
+ ](
+ __mlir_op.`kgen.float_literal.convert`[
+ _type = __mlir_type.f8E4M3
+ ](value.value)
+ )
+ )
+ )
+ )
+ elif type is DType.float8e4m3fnuz:
+ self = SIMD[type, size](
+ __mlir_op.`pop.simd.splat`[
+ _type = __mlir_type[
+ `!pop.simd<`, size.value, `,`, type.value, `>`
+ ]
+ ](
+ rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
+ __mlir_op.`pop.cast_from_builtin`[
+ _type = __mlir_type[`!pop.scalar`]
+ ](
+ __mlir_op.`kgen.float_literal.convert`[
+ _type = __mlir_type.f8E4M3FNUZ
+ ](value.value)
+ )
+ )
+ )
+ )
+ elif type is DType.float8e5m2:
+ self = SIMD[type, size](
+ __mlir_op.`pop.simd.splat`[
+ _type = __mlir_type[
+ `!pop.simd<`, size.value, `,`, type.value, `>`
+ ]
+ ](
+ rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
+ __mlir_op.`pop.cast_from_builtin`[
+ _type = __mlir_type[`!pop.scalar`]
+ ](
+ __mlir_op.`kgen.float_literal.convert`[
+ _type = __mlir_type.f8E5M2
+ ](value.value)
+ )
+ )
+ )
+ )
+ elif type is DType.float8e5m2fnuz:
+ self = SIMD[type, size](
+ __mlir_op.`pop.simd.splat`[
+ _type = __mlir_type[
+ `!pop.simd<`, size.value, `,`, type.value, `>`
+ ]
+ ](
+ rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
+ __mlir_op.`pop.cast_from_builtin`[
+ _type = __mlir_type[`!pop.scalar`]
+ ](
+ __mlir_op.`kgen.float_literal.convert`[
+ _type = __mlir_type.f8E5M2FNUZ
+ ](value.value)
+ )
+ )
+ )
+ )
+ elif type is DType.float16:
+ self = SIMD[type, size](
+ __mlir_op.`pop.simd.splat`[
+ _type = __mlir_type[
+ `!pop.simd<`, size.value, `,`, type.value, `>`
+ ]
+ ](
+ rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
__mlir_op.`pop.cast_from_builtin`[
_type = __mlir_type[`!pop.scalar`]
](
@@ -451,9 +580,7 @@ struct SIMD[type: DType, size: Int](
`!pop.simd<`, size.value, `,`, type.value, `>`
]
](
- __mlir_op.`pop.cast`[
- _type = __mlir_type[`!pop.scalar<`, type.value, `>`]
- ](
+ rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
__mlir_op.`pop.cast_from_builtin`[
_type = __mlir_type[`!pop.scalar`]
](
@@ -471,9 +598,7 @@ struct SIMD[type: DType, size: Int](
`!pop.simd<`, size.value, `,`, type.value, `>`
]
](
- __mlir_op.`pop.cast`[
- _type = __mlir_type[`!pop.scalar<`, type.value, `>`]
- ](
+ rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
__mlir_op.`pop.cast_from_builtin`[
_type = __mlir_type[`!pop.scalar`]
](
@@ -491,9 +616,7 @@ struct SIMD[type: DType, size: Int](
`!pop.simd<`, size.value, `,`, type.value, `>`
]
](
- __mlir_op.`pop.cast`[
- _type = __mlir_type[`!pop.scalar<`, type.value, `>`]
- ](
+ rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
__mlir_op.`pop.cast_from_builtin`[
_type = __mlir_type[`!pop.scalar`]
](
@@ -507,7 +630,7 @@ struct SIMD[type: DType, size: Int](
fn __init__[
int_type: DType, //
- ](inout self, *, from_bits: SIMD[int_type, size]):
+ ](mut self, *, from_bits: SIMD[int_type, size]):
"""Initializes the SIMD vector from the bits of an integral SIMD vector.
Parameters:
@@ -538,7 +661,7 @@ struct SIMD[type: DType, size: Int](
](self.value, index(idx).value)
@always_inline("nodebug")
- fn __setitem__(inout self, idx: Int, val: Scalar[type]):
+ fn __setitem__(mut self, idx: Int, val: Scalar[type]):
"""Sets an element in the vector.
Args:
@@ -721,7 +844,7 @@ struct SIMD[type: DType, size: Int](
specified exponent value.
"""
constrained[type.is_numeric(), "the SIMD type must be numeric"]()
- return _pow[type, size, DType.index](self, exp)
+ return _pow(self, SIMD[DType.index, size](exp))
# TODO(#22771): remove this overload.
@always_inline("nodebug")
@@ -995,7 +1118,7 @@ struct SIMD[type: DType, size: Int](
# ===------------------------------------------------------------------=== #
@always_inline("nodebug")
- fn __iadd__(inout self, rhs: Self):
+ fn __iadd__(mut self, rhs: Self):
"""Performs in-place addition.
The vector is mutated where each element at position `i` is computed as
@@ -1008,7 +1131,7 @@ struct SIMD[type: DType, size: Int](
self = self + rhs
@always_inline("nodebug")
- fn __isub__(inout self, rhs: Self):
+ fn __isub__(mut self, rhs: Self):
"""Performs in-place subtraction.
The vector is mutated where each element at position `i` is computed as
@@ -1021,7 +1144,7 @@ struct SIMD[type: DType, size: Int](
self = self - rhs
@always_inline("nodebug")
- fn __imul__(inout self, rhs: Self):
+ fn __imul__(mut self, rhs: Self):
"""Performs in-place multiplication.
The vector is mutated where each element at position `i` is computed as
@@ -1034,7 +1157,7 @@ struct SIMD[type: DType, size: Int](
self = self * rhs
@always_inline("nodebug")
- fn __itruediv__(inout self, rhs: Self):
+ fn __itruediv__(mut self, rhs: Self):
"""In-place true divide operator.
The vector is mutated where each element at position `i` is computed as
@@ -1047,7 +1170,7 @@ struct SIMD[type: DType, size: Int](
self = self / rhs
@always_inline("nodebug")
- fn __ifloordiv__(inout self, rhs: Self):
+ fn __ifloordiv__(mut self, rhs: Self):
"""In-place flood div operator.
The vector is mutated where each element at position `i` is computed as
@@ -1060,7 +1183,7 @@ struct SIMD[type: DType, size: Int](
self = self // rhs
@always_inline("nodebug")
- fn __imod__(inout self, rhs: Self):
+ fn __imod__(mut self, rhs: Self):
"""In-place mod operator.
The vector is mutated where each element at position `i` is computed as
@@ -1073,7 +1196,7 @@ struct SIMD[type: DType, size: Int](
self = self.__mod__(rhs)
@always_inline("nodebug")
- fn __ipow__(inout self, rhs: Int):
+ fn __ipow__(mut self, rhs: Int):
"""In-place pow operator.
The vector is mutated where each element at position `i` is computed as
@@ -1086,7 +1209,7 @@ struct SIMD[type: DType, size: Int](
self = self.__pow__(rhs)
@always_inline("nodebug")
- fn __iand__(inout self, rhs: Self):
+ fn __iand__(mut self, rhs: Self):
"""Computes `self & rhs` and save the result in `self`.
Constraints:
@@ -1102,7 +1225,7 @@ struct SIMD[type: DType, size: Int](
self = self & rhs
@always_inline("nodebug")
- fn __ixor__(inout self, rhs: Self):
+ fn __ixor__(mut self, rhs: Self):
"""Computes `self ^ rhs` and save the result in `self`.
Constraints:
@@ -1118,7 +1241,7 @@ struct SIMD[type: DType, size: Int](
self = self ^ rhs
@always_inline("nodebug")
- fn __ior__(inout self, rhs: Self):
+ fn __ior__(mut self, rhs: Self):
"""Computes `self | rhs` and save the result in `self`.
Constraints:
@@ -1134,7 +1257,7 @@ struct SIMD[type: DType, size: Int](
self = self | rhs
@always_inline("nodebug")
- fn __ilshift__(inout self, rhs: Self):
+ fn __ilshift__(mut self, rhs: Self):
"""Computes `self << rhs` and save the result in `self`.
Constraints:
@@ -1147,7 +1270,7 @@ struct SIMD[type: DType, size: Int](
self = self << rhs
@always_inline("nodebug")
- fn __irshift__(inout self, rhs: Self):
+ fn __irshift__(mut self, rhs: Self):
"""Computes `self >> rhs` and save the result in `self`.
Constraints:
@@ -1562,7 +1685,7 @@ struct SIMD[type: DType, size: Int](
"""
return _hash_simd(self)
- fn __hash__[H: _Hasher](self, inout hasher: H):
+ fn __hash__[H: _Hasher](self, mut hasher: H):
"""Updates hasher with this SIMD value.
Parameters:
@@ -1701,7 +1824,7 @@ struct SIMD[type: DType, size: Int](
](self.value)
@no_inline
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""
Formats this SIMD value to the provided Writer.
@@ -2206,7 +2329,7 @@ struct SIMD[type: DType, size: Int](
](self, value, Int64(offset))
@always_inline("nodebug")
- fn join(self, other: Self) -> SIMD[type, 2 * size] as result:
+ fn join(self, other: Self, out result: SIMD[type, 2 * size]):
"""Concatenates the two vectors together.
Args:
@@ -2871,17 +2994,13 @@ fn _tbl1(
@always_inline
fn _pow[
- BaseTy: DType, simd_width: Int, ExpTy: DType
-](base: SIMD[BaseTy, simd_width], exp: SIMD[ExpTy, simd_width]) -> __type_of(
- base
-):
+ simd_width: Int
+](base: SIMD[_, simd_width], exp: SIMD[_, simd_width]) -> __type_of(base):
"""Computes the power of the elements of a SIMD vector raised to the
corresponding elements of another SIMD vector.
Parameters:
- BaseTy: The `dtype` of the `base` SIMD vector.
simd_width: The width of the input and output SIMD vectors.
- ExpTy: The `dtype` of the `exp` SIMD vector.
Args:
base: Base of the power operation.
@@ -2892,9 +3011,9 @@ fn _pow[
"""
@parameter
- if ExpTy.is_floating_point() and BaseTy == ExpTy:
+ if exp.type.is_floating_point() and base.type is exp.type:
return _powf(base, exp)
- elif ExpTy.is_integral():
+ elif exp.type.is_integral():
# Common cases
if all(exp == 2):
return base * base
@@ -2949,12 +3068,15 @@ fn _powf[
@always_inline
-fn _powi[type: DType](base: Scalar[type], exp: Int32) -> __type_of(base):
+fn _powi(base: Scalar, exp: Int32) -> __type_of(base):
+ alias type = base.type
+
if type.is_integral() and exp < 0:
# Not defined for Integers, this should raise an
# exception.
debug_assert(False, "exponent < 0 is undefined for integers")
return 0
+
var a = base
var b = abs(exp) if type.is_floating_point() else exp
var res: Scalar[type] = 1
@@ -3309,16 +3431,6 @@ fn _modf(x: SIMD) -> Tuple[__type_of(x), __type_of(x)]:
return (result_int, result_frac)
-@always_inline("nodebug")
-fn _sub_with_saturation[
- width: Int, //
-](a: SIMD[DType.uint8, width], b: SIMD[DType.uint8, width]) -> SIMD[
- DType.uint8, width
-]:
- # generates a single `vpsubusb` on x86 with AVX
- return llvm_intrinsic["llvm.usub.sat", __type_of(a)](a, b)
-
-
# ===----------------------------------------------------------------------=== #
# floor
# ===----------------------------------------------------------------------=== #
@@ -3351,7 +3463,7 @@ fn _floor(x: SIMD) -> __type_of(x):
fn _write_scalar[
dtype: DType,
W: Writer, //,
-](inout writer: W, value: Scalar[dtype]):
+](mut writer: W, value: Scalar[dtype]):
@parameter
if dtype == DType.bool:
if value:
@@ -3362,24 +3474,10 @@ fn _write_scalar[
elif dtype.is_floating_point():
_write_float(writer, value)
- # TODO: bring in modern int formatter and remove GPU specific code
+ # TODO(MSTDL-1039): bring in performant integer to string formatter
elif dtype.is_integral():
-
- @parameter
- if is_nvidia_gpu():
- var err = _try_write_int(writer, value)
- if err:
- abort(
- "unreachable: unexpected write int failure condition: "
- + str(err.value())
- )
- else:
- # Stack allocate enough bytes to store any formatted Scalar value.
- alias size: Int = _calc_format_buffer_size[dtype]()
- var buf = InlineArray[UInt8, size](fill=0)
- var wrote = _snprintf[_get_dtype_printf_format[dtype]()](
- buf.unsafe_ptr(), size, value
- )
- # SAFETY:
- # Create a slice to only those bytes in `buf` that have been initialized.
- writer.write_bytes(Span[Byte](buf)[:wrote])
+ _ = _try_write_int(writer, value)
+ else:
+ constrained[
+ False, "unable to write dtype, only integral/float/bool supported"
+ ]()
diff --git a/stdlib/src/builtin/sort.mojo b/stdlib/src/builtin/sort.mojo
index 8e2f0aadbe..23429d9b4f 100644
--- a/stdlib/src/builtin/sort.mojo
+++ b/stdlib/src/builtin/sort.mojo
@@ -16,16 +16,15 @@ These are Mojo built-ins, so you don't need to import them.
"""
from collections import List
-from sys import bitwidthof
from math import ceil
+from sys import bitwidthof
from bit import count_leading_zeros
-from memory import UnsafePointer
-from utils import Span
+from memory import UnsafePointer, Span
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# sort
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
alias insertion_sort_threshold = 32
@@ -259,9 +258,9 @@ fn _quicksort[
stack.append(ImmSpan(ptr=ptr, length=pivot))
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# stable sort
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
fn _merge[
@@ -365,9 +364,9 @@ fn _stable_sort[
temp_buff.free()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# partition
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -500,9 +499,9 @@ fn partition[
_partition[_cmp_fn](span, k)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# sort
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Junction from public to private API
@@ -685,9 +684,9 @@ fn sort[
sort[_cmp_fn, stable=stable](span)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# sort networks
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
diff --git a/stdlib/src/builtin/string_literal.mojo b/stdlib/src/builtin/string_literal.mojo
index abf8bb5f0b..ed55ad0704 100644
--- a/stdlib/src/builtin/string_literal.mojo
+++ b/stdlib/src/builtin/string_literal.mojo
@@ -15,25 +15,20 @@
These are Mojo built-ins, so you don't need to import them.
"""
-from sys.ffi import c_char
-
-from memory import memcpy, UnsafePointer
from collections import List
from hashlib._hasher import _HashableWithHasher, _Hasher
-from utils import StringRef, Span, StringSlice, StaticString
-from utils import Writable, Writer
-from utils._visualizers import lldb_formatter_wrapping_type
+from sys.ffi import c_char
+
+from memory import UnsafePointer, memcpy, Span
-from utils.string_slice import (
- _StringSliceIter,
- _FormatCurlyEntry,
- _CurlyEntryFormattable,
- _to_string_list,
-)
+from utils import StaticString, StringRef, StringSlice, Writable, Writer
+from utils._visualizers import lldb_formatter_wrapping_type
+from utils.format import _CurlyEntryFormattable, _FormatCurlyEntry
+from utils.string_slice import _StringSliceIter, _to_string_list
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# StringLiteral
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@lldb_formatter_wrapping_type
@@ -88,6 +83,56 @@ struct StringLiteral(
"""
self = other
+ # TODO(MOCO-1460): This should be: fn __init__[*, value: String](out self):
+ # but Mojo tries to bind the parameter in `StringLiteral["foo"]()` to the
+ # type instead of the initializer. Use a static method to work around this
+ # for now.
+ @always_inline("nodebug")
+ @staticmethod
+ fn _from_string[value: String]() -> StringLiteral:
+ """Form a string literal from an arbitrary compile-time String value.
+
+ Parameters:
+ value: The string value to use.
+
+ Returns:
+ The string value as a StringLiteral.
+ """
+ return __mlir_attr[
+ `#kgen.param.expr : !kgen.string`,
+ ]
+
+ @always_inline("nodebug")
+ @staticmethod
+ fn get[value: String]() -> StringLiteral:
+ """Form a string literal from an arbitrary compile-time String value.
+
+ Parameters:
+ value: The value to convert to StringLiteral.
+
+ Returns:
+ The string value as a StringLiteral.
+ """
+ return Self._from_string[value]()
+
+ @always_inline("nodebug")
+ @staticmethod
+ fn get[type: Stringable, //, value: type]() -> StringLiteral:
+ """Form a string literal from an arbitrary compile-time stringable value.
+
+ Parameters:
+ type: The type of the value.
+ value: The value to serialize.
+
+ Returns:
+ The string value as a StringLiteral.
+ """
+ return Self._from_string[str(value)]()
+
# ===-------------------------------------------------------------------===#
# Operator dunders
# ===-------------------------------------------------------------------===#
@@ -105,7 +150,7 @@ struct StringLiteral(
return __mlir_op.`pop.string.concat`(self.value, rhs.value)
@always_inline("nodebug")
- fn __iadd__(inout self, rhs: StringLiteral):
+ fn __iadd__(mut self, rhs: StringLiteral):
"""Concatenate a string literal to an existing one. Can only be
evaluated at compile time using the `alias` keyword, which will write
the result into the binary.
@@ -370,7 +415,7 @@ struct StringLiteral(
"""
return hash(self.unsafe_ptr(), len(self))
- fn __hash__[H: _Hasher](self, inout hasher: H):
+ fn __hash__[H: _Hasher](self, mut hasher: H):
"""Updates hasher with the underlying bytes.
Parameters:
@@ -533,7 +578,7 @@ struct StringLiteral(
"""
return _FormatCurlyEntry.format(self, args)
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""
Formats this string literal to the provided Writer.
@@ -599,6 +644,50 @@ struct StringLiteral(
"""
return str(self).join(elems)
+ fn join(self, *elems: Int) -> String:
+ """Joins the elements from the tuple using the current string literal as a
+ delimiter.
+
+ Args:
+ elems: The input tuple.
+
+ Returns:
+ The joined string.
+ """
+ if len(elems) == 0:
+ return ""
+ var curr = str(elems[0])
+ for i in range(1, len(elems)):
+ curr += self + str(elems[i])
+ return curr
+
+ fn join[*Types: Stringable](self, *elems: *Types) -> String:
+ """Joins string elements using the current string as a delimiter.
+
+ Parameters:
+ Types: The types of the elements.
+
+ Args:
+ elems: The input values.
+
+ Returns:
+ The joined string.
+ """
+
+ var result: String = ""
+ var is_first = True
+
+ @parameter
+ fn add_elt[T: Stringable](a: T):
+ if is_first:
+ is_first = False
+ else:
+ result += self
+ result += str(a)
+
+ elems.each[add_elt]()
+ return result
+
fn split(self, sep: String, maxsplit: Int = -1) raises -> List[String]:
"""Split the string literal by a separator.
diff --git a/stdlib/src/builtin/swap.mojo b/stdlib/src/builtin/swap.mojo
index fed7502fd1..549e71e28b 100644
--- a/stdlib/src/builtin/swap.mojo
+++ b/stdlib/src/builtin/swap.mojo
@@ -17,7 +17,7 @@ These are Mojo built-ins, so you don't need to import them.
@always_inline
-fn swap[T: Movable](inout lhs: T, inout rhs: T):
+fn swap[T: Movable](mut lhs: T, mut rhs: T):
"""Swaps the two given arguments.
Parameters:
diff --git a/stdlib/src/builtin/tuple.mojo b/stdlib/src/builtin/tuple.mojo
index 698a73286e..b18221e3b3 100644
--- a/stdlib/src/builtin/tuple.mojo
+++ b/stdlib/src/builtin/tuple.mojo
@@ -16,13 +16,14 @@ These are Mojo built-ins, so you don't need to import them.
"""
from sys.intrinsics import _type_is_eq
+
from memory import UnsafePointer
from utils._visualizers import lldb_formatter_wrapping_type
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Tuple
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@lldb_formatter_wrapping_type
@@ -58,7 +59,7 @@ struct Tuple[*element_types: CollectionElement](Sized, CollectionElement):
@always_inline("nodebug")
fn __init__(
- inout self,
+ mut self,
*,
owned storage: VariadicPack[_, CollectionElement, *element_types],
):
@@ -80,8 +81,10 @@ struct Tuple[*element_types: CollectionElement](Sized, CollectionElement):
UnsafePointer.address_of(self[i])
)
- # Mark the elements as destroyed.
- storage._is_owned = False
+ # Do not destroy the elements when 'storage' goes away.
+ __mlir_op.`lit.ownership.mark_destroyed`(
+ __get_mvalue_as_litref(storage)
+ )
fn __del__(owned self):
"""Destructor that destroys all of the elements."""
@@ -125,6 +128,7 @@ struct Tuple[*element_types: CollectionElement](Sized, CollectionElement):
UnsafePointer.address_of(existing[i]).move_pointee_into(
UnsafePointer.address_of(self[i])
)
+ # Note: The destructor on `existing` is auto-disabled in a moveinit.
@always_inline
@staticmethod
diff --git a/stdlib/src/builtin/type_aliases.mojo b/stdlib/src/builtin/type_aliases.mojo
index 70d70a664e..762746f8c2 100644
--- a/stdlib/src/builtin/type_aliases.mojo
+++ b/stdlib/src/builtin/type_aliases.mojo
@@ -18,10 +18,10 @@ These are Mojo built-ins, so you don't need to import them.
alias AnyTrivialRegType = __mlir_type.`!kgen.type`
"""Represents any register passable Mojo data type."""
-alias ImmutableOrigin = __mlir_type.`!lit.origin<0>`
+alias ImmutableOrigin = Origin[False]
"""Immutable origin reference type."""
-alias MutableOrigin = __mlir_type.`!lit.origin<1>`
+alias MutableOrigin = Origin[True]
"""Mutable origin reference type."""
alias ImmutableAnyOrigin = __mlir_attr.`#lit.any.origin : !lit.origin<0>`
@@ -42,18 +42,78 @@ alias OriginSet = __mlir_type.`!lit.origin.set`
"""A set of origin parameters."""
-# Helper to build a value of !lit.origin type.
-# TODO: Should be a parametric alias.
+@value
+@register_passable("trivial")
struct Origin[is_mutable: Bool]:
- """This represents a origin reference of potentially parametric type.
- TODO: This should be replaced with a parametric type alias.
+ """This represents a origin reference for a memory value.
Parameters:
- is_mutable: Whether the origin reference is mutable.
+ is_mutable: Whether the origin is mutable.
"""
- alias type = __mlir_type[
+ alias _mlir_type = __mlir_type[
`!lit.origin<`,
is_mutable.value,
`>`,
]
+
+ alias cast_from = _lit_mut_cast[result_mutable=is_mutable]
+ """Cast an existing Origin to be of the specified mutability.
+
+ This is a low-level way to coerce Origin mutability. This should be used
+ rarely, typically when building low-level fundamental abstractions. Strongly
+ consider alternatives before reaching for this "escape hatch".
+
+ Safety:
+ This is an UNSAFE operation if used to cast an immutable origin to
+ a mutable origin.
+
+ Examples:
+
+ Cast a mutable origin to be immutable:
+
+ ```mojo
+ struct Container[mut: Bool, //, origin: Origin[mut]]:
+ var data: Int
+
+ fn imm_borrow(self) -> Container[ImmutableOrigin.cast_from[origin].result]:
+ # ...
+ ```
+ """
+
+ # ===-------------------------------------------------------------------===#
+ # Fields
+ # ===-------------------------------------------------------------------===#
+
+ var _mlir_origin: Self._mlir_type
+
+ # ===-------------------------------------------------------------------===#
+ # Life cycle methods
+ # ===-------------------------------------------------------------------===#
+
+ # NOTE:
+ # Needs to be @implicit convertible for the time being so that
+ # `__origin_of(..)` can implicilty convert to `Origin` in use cases like:
+ # Span[Byte, __origin_of(self)]
+ @implicit
+ @always_inline("nodebug")
+ fn __init__(out self, mlir_origin: Self._mlir_type):
+ """Initialize an Origin from a raw MLIR `!lit.origin` value.
+
+ Args:
+ mlir_origin: The raw MLIR origin value."""
+ self._mlir_origin = mlir_origin
+
+
+struct _lit_mut_cast[
+ is_mutable: Bool, //,
+ result_mutable: Bool,
+ operand: Origin[is_mutable],
+]:
+ alias result = __mlir_attr[
+ `#lit.origin.mutcast<`,
+ operand._mlir_origin,
+ `> : !lit.origin<`,
+ result_mutable.value,
+ `>`,
+ ]
diff --git a/stdlib/src/builtin/uint.mojo b/stdlib/src/builtin/uint.mojo
index 2c0f3f7de9..9c3feb155f 100644
--- a/stdlib/src/builtin/uint.mojo
+++ b/stdlib/src/builtin/uint.mojo
@@ -15,11 +15,13 @@
These are Mojo built-ins, so you don't need to import them.
"""
+from hashlib._hasher import _HashableWithHasher, _Hasher
+from hashlib.hash import _hash_simd
from sys import bitwidthof
-from utils._visualizers import lldb_formatter_wrapping_type
+
from documentation import doc_private
-from hashlib.hash import _hash_simd
-from hashlib._hasher import _HashableWithHasher, _Hasher
+
+from utils._visualizers import lldb_formatter_wrapping_type
@lldb_formatter_wrapping_type
@@ -128,7 +130,7 @@ struct UInt(IntLike, _HashableWithHasher):
return String.write(self)
@no_inline
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""Formats this integer to the provided Writer.
Parameters:
@@ -166,7 +168,7 @@ struct UInt(IntLike, _HashableWithHasher):
# TODO(MOCO-636): switch to DType.index
return _hash_simd(Scalar[DType.uint64](self))
- fn __hash__[H: _Hasher](self, inout hasher: H):
+ fn __hash__[H: _Hasher](self, mut hasher: H):
"""Updates hasher with this uint value.
Parameters:
@@ -396,12 +398,12 @@ struct UInt(IntLike, _HashableWithHasher):
"""
return __mlir_op.`index.ceildivu`(self.value, denominator.value)
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
# In place operations.
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
@always_inline("nodebug")
- fn __iadd__(inout self, rhs: UInt):
+ fn __iadd__(mut self, rhs: UInt):
"""Compute `self + rhs` and save the result in self.
Args:
@@ -410,7 +412,7 @@ struct UInt(IntLike, _HashableWithHasher):
self = self + rhs
@always_inline("nodebug")
- fn __isub__(inout self, rhs: UInt):
+ fn __isub__(mut self, rhs: UInt):
"""Compute `self - rhs` and save the result in self.
Args:
@@ -419,7 +421,7 @@ struct UInt(IntLike, _HashableWithHasher):
self = self - rhs
@always_inline("nodebug")
- fn __imul__(inout self, rhs: UInt):
+ fn __imul__(mut self, rhs: UInt):
"""Compute self*rhs and save the result in self.
Args:
@@ -427,7 +429,7 @@ struct UInt(IntLike, _HashableWithHasher):
"""
self = self * rhs
- fn __itruediv__(inout self, rhs: UInt):
+ fn __itruediv__(mut self, rhs: UInt):
"""Compute `self / rhs`, convert to int, and save the result in self.
Since `floor(self / rhs)` is equivalent to `self // rhs`, this yields
@@ -439,7 +441,7 @@ struct UInt(IntLike, _HashableWithHasher):
self = self // rhs
@always_inline("nodebug")
- fn __ifloordiv__(inout self, rhs: UInt):
+ fn __ifloordiv__(mut self, rhs: UInt):
"""Compute `self // rhs` and save the result in self.
Args:
@@ -447,7 +449,7 @@ struct UInt(IntLike, _HashableWithHasher):
"""
self = self // rhs
- fn __imod__(inout self, rhs: UInt):
+ fn __imod__(mut self, rhs: UInt):
"""Compute `self % rhs` and save the result in self.
Args:
@@ -456,7 +458,7 @@ struct UInt(IntLike, _HashableWithHasher):
self = self % rhs
@always_inline("nodebug")
- fn __ipow__(inout self, rhs: UInt):
+ fn __ipow__(mut self, rhs: UInt):
"""Compute `pow(self, rhs)` and save the result in self.
Args:
@@ -465,7 +467,7 @@ struct UInt(IntLike, _HashableWithHasher):
self = self**rhs
@always_inline("nodebug")
- fn __ilshift__(inout self, rhs: UInt):
+ fn __ilshift__(mut self, rhs: UInt):
"""Compute `self << rhs` and save the result in self.
Args:
@@ -474,7 +476,7 @@ struct UInt(IntLike, _HashableWithHasher):
self = self << rhs
@always_inline("nodebug")
- fn __irshift__(inout self, rhs: UInt):
+ fn __irshift__(mut self, rhs: UInt):
"""Compute `self >> rhs` and save the result in self.
Args:
@@ -483,7 +485,7 @@ struct UInt(IntLike, _HashableWithHasher):
self = self >> rhs
@always_inline("nodebug")
- fn __iand__(inout self, rhs: UInt):
+ fn __iand__(mut self, rhs: UInt):
"""Compute `self & rhs` and save the result in self.
Args:
@@ -492,7 +494,7 @@ struct UInt(IntLike, _HashableWithHasher):
self = self & rhs
@always_inline("nodebug")
- fn __ixor__(inout self, rhs: UInt):
+ fn __ixor__(mut self, rhs: UInt):
"""Compute `self ^ rhs` and save the result in self.
Args:
@@ -501,7 +503,7 @@ struct UInt(IntLike, _HashableWithHasher):
self = self ^ rhs
@always_inline("nodebug")
- fn __ior__(inout self, rhs: UInt):
+ fn __ior__(mut self, rhs: UInt):
"""Compute self|rhs and save the result in self.
Args:
@@ -509,9 +511,9 @@ struct UInt(IntLike, _HashableWithHasher):
"""
self = self | rhs
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
# Reversed operations
- # ===----------------------------------------------------------------------===#
+ # ===-------------------------------------------------------------------===#
@always_inline("nodebug")
fn __radd__(self, value: Self) -> Self:
diff --git a/stdlib/src/builtin/value.mojo b/stdlib/src/builtin/value.mojo
index fab16a7b44..3dc291c522 100644
--- a/stdlib/src/builtin/value.mojo
+++ b/stdlib/src/builtin/value.mojo
@@ -109,7 +109,7 @@ trait ExplicitlyCopyable:
initializer is called intentionally by the programmer.
An explicit copy initializer is just a normal `__init__` method that takes
- a `borrowed` argument of `Self`.
+ a `read-only` argument of `Self`.
Example implementing the `ExplicitlyCopyable` trait on `Foo` which requires
the `__init__(.., Self)` method:
diff --git a/stdlib/src/collections/counter.mojo b/stdlib/src/collections/counter.mojo
index e6000ce5fb..55baedf606 100644
--- a/stdlib/src/collections/counter.mojo
+++ b/stdlib/src/collections/counter.mojo
@@ -18,7 +18,8 @@ You can import these APIs from the `collections` package. For example:
from collections import Counter
```
"""
-from collections.dict import Dict, _DictKeyIter, _DictValueIter, _DictEntryIter
+from collections.dict import Dict, _DictEntryIter, _DictKeyIter, _DictValueIter
+
from utils import Variant
@@ -113,7 +114,7 @@ struct Counter[V: KeyElement](Sized, CollectionElement, Boolable):
"""
return self.get(key, 0)
- fn __setitem__(inout self, value: V, count: Int):
+ fn __setitem__(mut self, value: V, count: Int):
"""Set a value in the keyword Counter by key.
Args:
@@ -275,7 +276,7 @@ struct Counter[V: KeyElement](Sized, CollectionElement, Boolable):
return +result^ # Remove zero and negative counts
- fn __iadd__(inout self, other: Self):
+ fn __iadd__(mut self, other: Self):
"""Add counts from another Counter to this Counter.
Args:
@@ -300,7 +301,7 @@ struct Counter[V: KeyElement](Sized, CollectionElement, Boolable):
return +result^ # Remove zero and negative counts
- fn __isub__(inout self, other: Self):
+ fn __isub__(mut self, other: Self):
"""Subtract counts from another Counter from this Counter.
Args:
@@ -328,7 +329,7 @@ struct Counter[V: KeyElement](Sized, CollectionElement, Boolable):
return result^
- fn __iand__(inout self, other: Self):
+ fn __iand__(mut self, other: Self):
"""Intersection: keep common elements with the minimum count.
Args:
@@ -369,7 +370,7 @@ struct Counter[V: KeyElement](Sized, CollectionElement, Boolable):
return result^
- fn __ior__(inout self, other: Self):
+ fn __ior__(mut self, other: Self):
"""Union: keep all elements with the maximum count.
Args:
@@ -381,7 +382,7 @@ struct Counter[V: KeyElement](Sized, CollectionElement, Boolable):
if newcount > 0:
self[key] = newcount
- fn _keep_positive(inout self):
+ fn _keep_positive(mut self):
"""Remove zero and negative counts from the Counter."""
for key_ref in self.keys():
var key = key_ref[]
@@ -450,7 +451,7 @@ struct Counter[V: KeyElement](Sized, CollectionElement, Boolable):
"""
return self._data.get(value, default)
- fn pop(inout self, value: V) raises -> Int:
+ fn pop(mut self, value: V) raises -> Int:
"""Remove a value from the Counter by value.
Args:
@@ -464,7 +465,7 @@ struct Counter[V: KeyElement](Sized, CollectionElement, Boolable):
"""
return self._data.pop(value)
- fn pop(inout self, value: V, owned default: Int) raises -> Int:
+ fn pop(mut self, value: V, owned default: Int) raises -> Int:
"""Remove a value from the Counter by value.
Args:
@@ -506,11 +507,11 @@ struct Counter[V: KeyElement](Sized, CollectionElement, Boolable):
"""
return self._data.items()
- fn clear(inout self):
+ fn clear(mut self):
"""Remove all elements from the Counter."""
self._data.clear()
- fn popitem(inout self) raises -> CountTuple[V]:
+ fn popitem(mut self) raises -> CountTuple[V]:
"""Remove and return an arbitrary (key, value) pair from the Counter.
Returns:
@@ -572,7 +573,7 @@ struct Counter[V: KeyElement](Sized, CollectionElement, Boolable):
elements.append(item.key)
return elements
- fn update(inout self, other: Self):
+ fn update(mut self, other: Self):
"""Update the Counter, like `dict.update()` but add counts instead of
replacing them.
@@ -583,7 +584,7 @@ struct Counter[V: KeyElement](Sized, CollectionElement, Boolable):
var item = item_ref[]
self._data[item.key] = self._data.get(item.key, 0) + item.value
- fn subtract(inout self, other: Self):
+ fn subtract(mut self, other: Self):
"""Subtract count. Both inputs and outputs may be zero or negative.
Args:
diff --git a/stdlib/src/collections/deque.mojo b/stdlib/src/collections/deque.mojo
index 5af332c273..284fb630da 100644
--- a/stdlib/src/collections/deque.mojo
+++ b/stdlib/src/collections/deque.mojo
@@ -21,14 +21,14 @@ from collections import Deque
```
"""
-from bit import bit_ceil
from collections import Optional
-from memory import UnsafePointer
+from bit import bit_ceil
+from memory import UnsafePointer
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Deque
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
struct Deque[ElementType: CollectionElement](
@@ -139,17 +139,15 @@ struct Deque[ElementType: CollectionElement](
Args:
values: The values to populate the deque with.
"""
- self = Self(variadic_list=values^)
+ self = Self(elements=values^)
- fn __init__(
- inout self, *, owned variadic_list: VariadicListMem[ElementType, _]
- ):
+ fn __init__(mut self, *, owned elements: VariadicListMem[ElementType, _]):
"""Constructs a deque from the given values.
Args:
- variadic_list: The values to populate the deque with.
+ elements: The values to populate the deque with.
"""
- args_length = len(variadic_list)
+ args_length = len(elements)
if args_length < self.default_capacity:
capacity = self.default_capacity
@@ -159,12 +157,14 @@ struct Deque[ElementType: CollectionElement](
self = Self(capacity=capacity)
for i in range(args_length):
- src = UnsafePointer.address_of(variadic_list[i])
+ src = UnsafePointer.address_of(elements[i])
dst = self._data + i
src.move_pointee_into(dst)
- # Mark the elements as unowned to avoid del'ing uninitialized objects.
- variadic_list._is_owned = False
+ # Do not destroy the elements when their backing storage goes away.
+ __mlir_op.`lit.ownership.mark_destroyed`(
+ __get_mvalue_as_litref(elements)
+ )
self._tail = args_length
@@ -226,7 +226,7 @@ struct Deque[ElementType: CollectionElement](
new.append(element[])
return new^
- fn __iadd__(inout self, other: Self):
+ fn __iadd__(mut self, other: Self):
"""Appends the elements of other deque into self.
Args:
@@ -257,7 +257,7 @@ struct Deque[ElementType: CollectionElement](
new.append(element[])
return new^
- fn __imul__(inout self, n: Int):
+ fn __imul__(mut self, n: Int):
"""Concatenates self `n` times in place.
Args:
@@ -410,7 +410,7 @@ struct Deque[ElementType: CollectionElement](
fn write_to[
RepresentableElementType: RepresentableCollectionElement,
WriterType: Writer, //,
- ](self: Deque[RepresentableElementType], inout writer: WriterType):
+ ](self: Deque[RepresentableElementType], mut writer: WriterType):
"""Writes `my_deque.__str__()` to a `Writer`.
Parameters:
@@ -491,7 +491,7 @@ struct Deque[ElementType: CollectionElement](
# Methods
# ===-------------------------------------------------------------------===#
- fn append(inout self, owned value: ElementType):
+ fn append(mut self, owned value: ElementType):
"""Appends a value to the right side of the deque.
Args:
@@ -508,7 +508,7 @@ struct Deque[ElementType: CollectionElement](
if self._head == self._tail:
self._realloc(self._capacity << 1)
- fn appendleft(inout self, owned value: ElementType):
+ fn appendleft(mut self, owned value: ElementType):
"""Appends a value to the left side of the deque.
Args:
@@ -525,7 +525,7 @@ struct Deque[ElementType: CollectionElement](
if self._head == self._tail:
self._realloc(self._capacity << 1)
- fn clear(inout self):
+ fn clear(mut self):
"""Removes all elements from the deque leaving it with length 0.
Resets the underlying storage capacity to `_min_capacity`.
@@ -561,7 +561,7 @@ struct Deque[ElementType: CollectionElement](
count += 1
return count
- fn extend(inout self, owned values: List[ElementType]):
+ fn extend(mut self, owned values: List[ElementType]):
"""Extends the right side of the deque by consuming elements of the list argument.
Args:
@@ -593,7 +593,7 @@ struct Deque[ElementType: CollectionElement](
(src + i).move_pointee_into(self._data + self._tail)
self._tail = self._physical_index(self._tail + 1)
- fn extendleft(inout self, owned values: List[ElementType]):
+ fn extendleft(mut self, owned values: List[ElementType]):
"""Extends the left side of the deque by consuming elements from the list argument.
Acts as series of left appends resulting in reversed order of elements in the list argument.
@@ -676,7 +676,7 @@ struct Deque[ElementType: CollectionElement](
return idx
raise "ValueError: Given element is not in deque"
- fn insert(inout self, idx: Int, owned value: ElementType) raises:
+ fn insert(mut self, idx: Int, owned value: ElementType) raises:
"""Inserts the `value` into the deque at position `idx`.
Args:
@@ -723,10 +723,7 @@ struct Deque[ElementType: CollectionElement](
fn remove[
EqualityElementType: EqualityComparableCollectionElement, //
- ](
- inout self: Deque[EqualityElementType],
- value: EqualityElementType,
- ) raises:
+ ](mut self: Deque[EqualityElementType], value: EqualityElementType,) raises:
"""Removes the first occurrence of the `value`.
Parameters:
@@ -797,7 +794,7 @@ struct Deque[ElementType: CollectionElement](
return (self._data + self._head)[]
- fn pop(inout self) raises -> ElementType as element:
+ fn pop(mut self, out element: ElementType) raises:
"""Removes and returns the element from the right side of the deque.
Returns:
@@ -821,7 +818,7 @@ struct Deque[ElementType: CollectionElement](
return
- fn popleft(inout self) raises -> ElementType as element:
+ fn popleft(mut self, out element: ElementType) raises:
"""Removes and returns the element from the left side of the deque.
Returns:
@@ -845,7 +842,7 @@ struct Deque[ElementType: CollectionElement](
return
- fn reverse(inout self):
+ fn reverse(mut self):
"""Reverses the elements of the deque in-place."""
last = self._head + len(self) - 1
for i in range(len(self) // 2):
@@ -855,7 +852,7 @@ struct Deque[ElementType: CollectionElement](
(self._data + src).move_pointee_into(self._data + dst)
(self._data + src).init_pointee_move(tmp^)
- fn rotate(inout self, n: Int = 1):
+ fn rotate(mut self, n: Int = 1):
"""Rotates the deque by `n` steps.
If `n` is positive, rotates to the right.
@@ -932,7 +929,7 @@ struct Deque[ElementType: CollectionElement](
"""
return logical_index & (self._capacity - 1)
- fn _prepare_for_new_elements(inout self, n_total: Int, n_retain: Int):
+ fn _prepare_for_new_elements(mut self, n_total: Int, n_retain: Int):
"""Prepares the deque’s internal buffer for adding new elements by
reallocating memory and retaining the specified number of existing elements.
@@ -958,7 +955,7 @@ struct Deque[ElementType: CollectionElement](
self._head = 0
self._tail = n_retain
- fn _realloc(inout self, new_capacity: Int):
+ fn _realloc(mut self, new_capacity: Int):
"""Relocates data to a new storage buffer.
Args:
@@ -998,7 +995,7 @@ struct Deque[ElementType: CollectionElement](
struct _DequeIter[
deque_mutability: Bool, //,
ElementType: CollectionElement,
- deque_lifetime: Origin[deque_mutability].type,
+ deque_lifetime: Origin[deque_mutability],
forward: Bool = True,
]:
"""Iterator for Deque.
@@ -1018,7 +1015,7 @@ struct _DequeIter[
fn __iter__(self) -> Self:
return self
- fn __next__(inout self) -> Pointer[ElementType, deque_lifetime]:
+ fn __next__(mut self) -> Pointer[ElementType, deque_lifetime]:
@parameter
if forward:
self.index += 1
diff --git a/stdlib/src/collections/dict.mojo b/stdlib/src/collections/dict.mojo
index e6c8c2a821..99aa18c45f 100644
--- a/stdlib/src/collections/dict.mojo
+++ b/stdlib/src/collections/dict.mojo
@@ -31,12 +31,13 @@ value types must always be Movable so we can resize the dictionary as it grows.
See the `Dict` docs for more details.
"""
+from sys.ffi import OpaquePointer
+
+from bit import is_power_of_two
from builtin.value import StringableCollectionElement
+from memory import UnsafePointer, bitcast, memcpy
from .optional import Optional
-from bit import is_power_of_two
-from sys.ffi import OpaquePointer
-from memory import memcpy, bitcast, UnsafePointer
trait KeyElement(CollectionElement, Hashable, EqualityComparable):
@@ -60,7 +61,7 @@ struct _DictEntryIter[
dict_mutability: Bool, //,
K: KeyElement,
V: CollectionElement,
- dict_origin: Origin[dict_mutability].type,
+ dict_origin: Origin[dict_mutability],
forward: Bool = True,
]:
"""Iterator over immutable DictEntry references.
@@ -78,7 +79,7 @@ struct _DictEntryIter[
var src: Pointer[Dict[K, V], dict_origin]
fn __init__(
- inout self, index: Int, seen: Int, ref [dict_origin]dict: Dict[K, V]
+ mut self, index: Int, seen: Int, ref [dict_origin]dict: Dict[K, V]
):
self.index = index
self.seen = seen
@@ -89,7 +90,7 @@ struct _DictEntryIter[
@always_inline
fn __next__(
- inout self,
+ mut self,
) -> Pointer[DictEntry[K, V], __origin_of(self.src[]._entries[0].value())]:
while True:
var opt_entry_ref = Pointer.address_of(
@@ -119,7 +120,7 @@ struct _DictKeyIter[
dict_mutability: Bool, //,
K: KeyElement,
V: CollectionElement,
- dict_origin: Origin[dict_mutability].type,
+ dict_origin: Origin[dict_mutability],
forward: Bool = True,
]:
"""Iterator over immutable Dict key references.
@@ -140,7 +141,7 @@ struct _DictKeyIter[
return self
fn __next__(
- inout self,
+ mut self,
) -> Pointer[K, __origin_of(self.iter.__next__()[].key)]:
return Pointer.address_of(self.iter.__next__()[].key)
@@ -157,7 +158,7 @@ struct _DictValueIter[
dict_mutability: Bool, //,
K: KeyElement,
V: CollectionElement,
- dict_origin: Origin[dict_mutability].type,
+ dict_origin: Origin[dict_mutability],
forward: Bool = True,
]:
"""Iterator over Dict value references. These are mutable if the dict
@@ -186,7 +187,7 @@ struct _DictValueIter[
)
)
- fn __next__(inout self) -> Self.ref_type:
+ fn __next__(mut self) -> Self.ref_type:
var entry_ref = self.iter.__next__()
# Cast through a pointer to grant additional mutability because
# _DictEntryIter.next erases it.
@@ -330,7 +331,7 @@ struct _DictIndex:
var data = self.data.bitcast[Int64]()
return int(data.load(slot & (reserved - 1)))
- fn set_index(inout self, reserved: Int, slot: Int, value: Int):
+ fn set_index(mut self, reserved: Int, slot: Int, value: Int):
if reserved <= 128:
var data = self.data.bitcast[Int8]()
return data.store(slot & (reserved - 1), value)
@@ -598,7 +599,7 @@ struct Dict[K: KeyElement, V: CollectionElement](
"""
return self._find_ref(key)
- fn __setitem__(inout self, owned key: K, owned value: V):
+ fn __setitem__(mut self, owned key: K, owned value: V):
"""Set a value in the dictionary by key.
Args:
@@ -649,7 +650,7 @@ struct Dict[K: KeyElement, V: CollectionElement](
result.update(other)
return result^
- fn __ior__(inout self, other: Self):
+ fn __ior__(mut self, other: Self):
"""Merge self with other in place.
Args:
@@ -804,7 +805,7 @@ struct Dict[K: KeyElement, V: CollectionElement](
"""
return self.find(key).or_else(default)
- fn pop(inout self, key: K, owned default: V) -> V:
+ fn pop(mut self, key: K, owned default: V) -> V:
"""Remove a value from the dictionary by key.
Args:
@@ -821,7 +822,7 @@ struct Dict[K: KeyElement, V: CollectionElement](
except:
return default
- fn pop(inout self, key: K) raises -> V:
+ fn pop(mut self, key: K) raises -> V:
"""Remove a value from the dictionary by key.
Args:
@@ -849,7 +850,7 @@ struct Dict[K: KeyElement, V: CollectionElement](
return entry_value^.reap_value()
raise "KeyError"
- fn popitem(inout self) raises -> DictEntry[K, V]:
+ fn popitem(mut self) raises -> DictEntry[K, V]:
"""Remove and return a (key, value) pair from the dictionary. Pairs are returned in LIFO order.
popitem() is useful to destructively iterate over a dictionary, as often used in set algorithms.
If the dictionary is empty, calling popitem() raises a KeyError.
@@ -915,7 +916,7 @@ struct Dict[K: KeyElement, V: CollectionElement](
"""
return _DictEntryIter(0, 0, self)
- fn update(inout self, other: Self, /):
+ fn update(mut self, other: Self, /):
"""Update the dictionary with the key/value pairs from other, overwriting existing keys.
The argument must be positional only.
@@ -925,7 +926,7 @@ struct Dict[K: KeyElement, V: CollectionElement](
for entry in other.items():
self[entry[].key] = entry[].value
- fn clear(inout self):
+ fn clear(mut self):
"""Remove all elements from the dictionary."""
self.size = 0
self._n_entries = 0
@@ -933,7 +934,7 @@ struct Dict[K: KeyElement, V: CollectionElement](
self._index = _DictIndex(self._reserved())
fn setdefault(
- inout self, key: K, owned default: V
+ mut self, key: K, owned default: V
) raises -> ref [self._find_ref(key)] V:
"""Get a value from the dictionary by key, or set it to a default if it doesn't exist.
@@ -959,12 +960,12 @@ struct Dict[K: KeyElement, V: CollectionElement](
entries.append(None)
return entries
- fn _insert(inout self, owned key: K, owned value: V):
+ fn _insert(mut self, owned key: K, owned value: V):
self._insert(DictEntry[K, V](key^, value^))
fn _insert[
safe_context: Bool = False
- ](inout self, owned entry: DictEntry[K, V]):
+ ](mut self, owned entry: DictEntry[K, V]):
@parameter
if not safe_context:
self._maybe_resize()
@@ -982,10 +983,10 @@ struct Dict[K: KeyElement, V: CollectionElement](
fn _get_index(self, slot: Int) -> Int:
return self._index.get_index(self._reserved(), slot)
- fn _set_index(inout self, slot: Int, index: Int):
+ fn _set_index(mut self, slot: Int, index: Int):
return self._index.set_index(self._reserved(), slot, index)
- fn _next_index_slot(self, inout slot: Int, inout perturb: UInt64):
+ fn _next_index_slot(self, mut slot: Int, mut perturb: UInt64):
alias PERTURB_SHIFT = 5
perturb >>= PERTURB_SHIFT
slot = ((5 * slot) + int(perturb + 1)) & (self._reserved() - 1)
@@ -1022,7 +1023,7 @@ struct Dict[K: KeyElement, V: CollectionElement](
fn _over_compact_factor(self) -> Bool:
return 4 * self._n_entries > 3 * self._reserved()
- fn _maybe_resize(inout self):
+ fn _maybe_resize(mut self):
if not self._over_load_factor():
if self._over_compact_factor():
self._compact()
@@ -1039,7 +1040,7 @@ struct Dict[K: KeyElement, V: CollectionElement](
if entry:
self._insert[safe_context=True](entry.unsafe_take())
- fn _compact(inout self):
+ fn _compact(mut self):
self._index = _DictIndex(self._reserved())
var right = 0
for left in range(self.size):
@@ -1128,7 +1129,7 @@ struct OwnedKwargsDict[V: CollectionElement](
return self._dict[key]
@always_inline
- fn __setitem__(inout self, key: Self.key_type, value: V):
+ fn __setitem__(mut self, key: Self.key_type, value: V):
"""Set a value in the keyword dictionary by key.
Args:
@@ -1181,7 +1182,7 @@ struct OwnedKwargsDict[V: CollectionElement](
return self._dict.find(key)
@always_inline
- fn pop(inout self, key: self.key_type, owned default: V) -> V:
+ fn pop(mut self, key: self.key_type, owned default: V) -> V:
"""Remove a value from the dictionary by key.
Args:
@@ -1196,7 +1197,7 @@ struct OwnedKwargsDict[V: CollectionElement](
return self._dict.pop(key, default^)
@always_inline
- fn pop(inout self, key: self.key_type) raises -> V:
+ fn pop(mut self, key: self.key_type) raises -> V:
"""Remove a value from the dictionary by key.
Args:
@@ -1269,9 +1270,9 @@ struct OwnedKwargsDict[V: CollectionElement](
return _DictEntryIter(0, 0, self._dict)
@always_inline
- fn _insert(inout self, owned key: Self.key_type, owned value: V):
+ fn _insert(mut self, owned key: Self.key_type, owned value: V):
self._dict._insert(key^, value^)
@always_inline
- fn _insert(inout self, key: StringLiteral, owned value: V):
+ fn _insert(mut self, key: StringLiteral, owned value: V):
self._insert(String(key), value^)
diff --git a/stdlib/src/collections/inline_array.mojo b/stdlib/src/collections/inline_array.mojo
index b1c833b75c..6901ed1327 100644
--- a/stdlib/src/collections/inline_array.mojo
+++ b/stdlib/src/collections/inline_array.mojo
@@ -21,12 +21,13 @@ from collections import InlineArray
from collections._index_normalization import normalize_index
from sys.intrinsics import _type_is_eq
+
from memory import UnsafePointer
from memory.maybe_uninitialized import UnsafeMaybeUninitialized
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Array
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
fn _inline_array_construction_checks[size: Int]():
@@ -111,7 +112,7 @@ struct InlineArray[
]()
fn __init__(
- inout self,
+ mut self,
*,
owned unsafe_assume_initialized: InlineArray[
UnsafeMaybeUninitialized[Self.ElementType], Self.size
@@ -170,7 +171,7 @@ struct InlineArray[
@always_inline
fn __init__(
- inout self,
+ mut self,
*,
owned storage: VariadicListMem[Self.ElementType, _],
):
@@ -193,8 +194,10 @@ struct InlineArray[
var eltptr = UnsafePointer.address_of(self.unsafe_get(i))
UnsafePointer.address_of(storage[i]).move_pointee_into(eltptr)
- # Mark the elements as already destroyed.
- storage._is_owned = False
+ # Do not destroy the elements when their backing storage goes away.
+ __mlir_op.`lit.ownership.mark_destroyed`(
+ __get_mvalue_as_litref(storage)
+ )
fn __init__(out self, *, other: Self):
"""Explicitly copy the provided value.
diff --git a/stdlib/src/collections/inline_list.mojo b/stdlib/src/collections/inline_list.mojo
index 9d5610ff36..f98e307940 100644
--- a/stdlib/src/collections/inline_list.mojo
+++ b/stdlib/src/collections/inline_list.mojo
@@ -20,18 +20,19 @@ from collections import InlineList
"""
from sys.intrinsics import _type_is_eq
+
from memory.maybe_uninitialized import UnsafeMaybeUninitialized
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# InlineList
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@value
struct _InlineListIter[
list_mutability: Bool, //,
T: CollectionElementNew,
capacity: Int,
- list_origin: Origin[list_mutability].type,
+ list_origin: Origin[list_mutability],
forward: Bool = True,
]:
"""Iterator for InlineList.
@@ -53,7 +54,7 @@ struct _InlineListIter[
return self
fn __next__(
- inout self,
+ mut self,
) -> Pointer[T, __origin_of(self.src[][0])]:
@parameter
if forward:
@@ -242,7 +243,7 @@ struct InlineList[ElementType: CollectionElementNew, capacity: Int = 16](Sized):
count += int(rebind[C](e[]) == value)
return count
- fn append(inout self, owned value: ElementType):
+ fn append(mut self, owned value: ElementType):
"""Appends a value to the list.
Args:
diff --git a/stdlib/src/collections/list.mojo b/stdlib/src/collections/list.mojo
index 1ed439c040..13ee261638 100644
--- a/stdlib/src/collections/list.mojo
+++ b/stdlib/src/collections/list.mojo
@@ -20,17 +20,17 @@ from collections import List
"""
-from sys.intrinsics import _type_is_eq
-from sys import sizeof
from os import abort
-from memory import Pointer, UnsafePointer, memcpy
-from utils import Span
+from sys import sizeof
+from sys.intrinsics import _type_is_eq
+
+from memory import Pointer, UnsafePointer, memcpy, Span
from .optional import Optional
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# List
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@value
@@ -38,7 +38,7 @@ struct _ListIter[
list_mutability: Bool, //,
T: CollectionElement,
hint_trivial_type: Bool,
- list_origin: Origin[list_mutability].type,
+ list_origin: Origin[list_mutability],
forward: Bool = True,
]:
"""Iterator for List.
@@ -61,7 +61,7 @@ struct _ListIter[
return self
fn __next__(
- inout self,
+ mut self,
) -> Pointer[T, list_origin]:
@parameter
if forward:
@@ -142,26 +142,28 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
Args:
values: The values to populate the list with.
"""
- self = Self(variadic_list=values^)
+ self = Self(elements=values^)
- fn __init__(out self, *, owned variadic_list: VariadicListMem[T, _]):
+ fn __init__(out self, *, owned elements: VariadicListMem[T, _]):
"""Constructs a list from the given values.
Args:
- variadic_list: The values to populate the list with.
+ elements: The values to populate the list with.
"""
- var length = len(variadic_list)
+ var length = len(elements)
self = Self(capacity=length)
for i in range(length):
- var src = UnsafePointer.address_of(variadic_list[i])
+ var src = UnsafePointer.address_of(elements[i])
var dest = self.data + i
src.move_pointee_into(dest)
- # Mark the elements as unowned to avoid del'ing uninitialized objects.
- variadic_list._is_owned = False
+ # Do not destroy the elements when their backing storage goes away.
+ __mlir_op.`lit.ownership.mark_destroyed`(
+ __get_mvalue_as_litref(elements)
+ )
self.size = length
@@ -176,9 +178,7 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
for value in span:
self.append(value[])
- fn __init__(
- inout self, *, ptr: UnsafePointer[T], length: Int, capacity: Int
- ):
+ fn __init__(mut self, *, ptr: UnsafePointer[T], length: Int, capacity: Int):
"""Constructs a list from a pointer, its length, and its capacity.
Args:
@@ -318,7 +318,7 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
result.__mul(x)
return result^
- fn __imul__(inout self, x: Int):
+ fn __imul__(mut self, x: Int):
"""Multiplies the list by x in place.
Args:
@@ -339,7 +339,7 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
result.extend(other^)
return result^
- fn __iadd__(inout self, owned other: Self):
+ fn __iadd__(mut self, owned other: Self):
"""Appends the elements of other into self.
Args:
@@ -418,7 +418,7 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
@no_inline
fn write_to[
W: Writer, U: RepresentableCollectionElement, //
- ](self: List[U, *_], inout writer: W):
+ ](self: List[U, *_], mut writer: W):
"""Write `my_list.__str__()` to a `Writer`.
Parameters:
@@ -475,7 +475,7 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
"""
return len(self) * sizeof[T]()
- fn _realloc(inout self, new_capacity: Int):
+ fn _realloc(mut self, new_capacity: Int):
var new_data = UnsafePointer[T].alloc(new_capacity)
_move_pointee_into_many_elements[hint_trivial_type](
@@ -489,7 +489,7 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
self.data = new_data
self.capacity = new_capacity
- fn append(inout self, owned value: T):
+ fn append(mut self, owned value: T):
"""Appends a value to this list.
Args:
@@ -500,7 +500,7 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
(self.data + self.size).init_pointee_move(value^)
self.size += 1
- fn insert(inout self, i: Int, owned value: T):
+ fn insert(mut self, i: Int, owned value: T):
"""Inserts a value to the list at the given index.
`a.insert(len(a), value)` is equivalent to `a.append(value)`.
@@ -529,7 +529,7 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
earlier_idx -= 1
later_idx -= 1
- fn __mul(inout self, x: Int):
+ fn __mul(mut self, x: Int):
"""Appends the original elements of this list x-1 times.
```mojo
@@ -548,7 +548,7 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
for i in range(x - 1):
self.extend(orig)
- fn extend(inout self, owned other: List[T, *_]):
+ fn extend(mut self, owned other: List[T, *_]):
"""Extends this list by consuming the elements of `other`.
Args:
@@ -588,7 +588,7 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
# list.
self.size = final_size
- fn pop(inout self, i: Int = -1) -> T:
+ fn pop(mut self, i: Int = -1) -> T:
"""Pops a value from the list at the given index.
Args:
@@ -612,7 +612,7 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
self._realloc(self.capacity // 2)
return ret_val^
- fn reserve(inout self, new_capacity: Int):
+ fn reserve(mut self, new_capacity: Int):
"""Reserves the requested capacity.
If the current capacity is greater or equal, this is a no-op.
@@ -625,7 +625,7 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
return
self._realloc(new_capacity)
- fn resize(inout self, new_size: Int, value: T):
+ fn resize(mut self, new_size: Int, value: T):
"""Resizes the list to the given new size.
If the new size is smaller than the current one, elements at the end
@@ -644,7 +644,7 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
(self.data + i).init_pointee_copy(value)
self.size = new_size
- fn resize(inout self, new_size: Int):
+ fn resize(mut self, new_size: Int):
"""Resizes the list to the given new size.
With no new value provided, the new size must be smaller than or equal
@@ -665,7 +665,7 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
self.size = new_size
self.reserve(new_size)
- fn reverse(inout self):
+ fn reverse(mut self):
"""Reverses the elements of the list."""
var earlier_idx = 0
@@ -742,13 +742,13 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
return i
raise "ValueError: Given element is not in list"
- fn clear(inout self):
+ fn clear(mut self):
"""Clears the elements in the list."""
for i in range(self.size):
(self.data + i).destroy_pointee()
self.size = 0
- fn steal_data(inout self) -> UnsafePointer[T]:
+ fn steal_data(mut self) -> UnsafePointer[T]:
"""Take ownership of the underlying pointer from the list.
Returns:
@@ -838,7 +838,7 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
return (self.data + idx)[]
@always_inline
- fn unsafe_set(inout self, idx: Int, owned value: T):
+ fn unsafe_set(mut self, idx: Int, owned value: T):
"""Write a value to a given location without checking index bounds.
Users should consider using `my_list[idx] = value` instead of this method as it
@@ -895,7 +895,7 @@ struct List[T: CollectionElement, hint_trivial_type: Bool = False](
count += 1
return count
- fn swap_elements(inout self, elt_idx_1: Int, elt_idx_2: Int):
+ fn swap_elements(mut self, elt_idx_1: Int, elt_idx_2: Int):
"""Swaps elements at the specified indexes if they are different.
```mojo
diff --git a/stdlib/src/collections/optional.mojo b/stdlib/src/collections/optional.mojo
index 2bcaf9ea8e..73518b55a5 100644
--- a/stdlib/src/collections/optional.mojo
+++ b/stdlib/src/collections/optional.mojo
@@ -32,6 +32,7 @@ print(d) # prints 2
"""
from os import abort
+
from utils import Variant
@@ -42,9 +43,9 @@ struct _NoneType(CollectionElement, CollectionElementNew):
pass
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Optional
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@value
@@ -280,7 +281,7 @@ struct Optional[T: CollectionElement](
fn write_to[
W: Writer, U: RepresentableCollectionElement, //
- ](self: Optional[U], inout writer: W):
+ ](self: Optional[U], mut writer: W):
"""Write Optional string representation to a `Writer`.
Parameters:
@@ -332,7 +333,7 @@ struct Optional[T: CollectionElement](
debug_assert(self.__bool__(), ".value() on empty Optional")
return self._value.unsafe_get[T]()
- fn take(inout self) -> T:
+ fn take(mut self) -> T:
"""Move the value out of the Optional.
The caller takes ownership over the new value, which is moved
@@ -350,7 +351,7 @@ struct Optional[T: CollectionElement](
abort(".take() on empty Optional")
return self.unsafe_take()
- fn unsafe_take(inout self) -> T:
+ fn unsafe_take(mut self) -> T:
"""Unsafely move the value out of the Optional.
The caller takes ownership over the new value, which is moved
@@ -382,9 +383,9 @@ struct Optional[T: CollectionElement](
return default
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# OptionalReg
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@register_passable("trivial")
diff --git a/stdlib/src/collections/set.mojo b/stdlib/src/collections/set.mojo
index 10451bc126..9c017dbfe8 100644
--- a/stdlib/src/collections/set.mojo
+++ b/stdlib/src/collections/set.mojo
@@ -15,9 +15,9 @@
from .dict import (
Dict,
KeyElement,
+ RepresentableKeyElement,
_DictEntryIter,
_DictKeyIter,
- RepresentableKeyElement,
)
@@ -149,7 +149,7 @@ struct Set[T: KeyElement](Sized, Comparable, Hashable, Boolable):
"""
return self.intersection(other)
- fn __iand__(inout self, other: Self):
+ fn __iand__(mut self, other: Self):
"""In-place set intersection.
Updates the set to contain only the elements which are already in
@@ -172,7 +172,7 @@ struct Set[T: KeyElement](Sized, Comparable, Hashable, Boolable):
"""
return self.union(other)
- fn __ior__(inout self, other: Self):
+ fn __ior__(mut self, other: Self):
"""In-place set union.
Updates the set to contain all elements in the `other` set
@@ -195,7 +195,7 @@ struct Set[T: KeyElement](Sized, Comparable, Hashable, Boolable):
"""
return self.difference(other)
- fn __isub__(inout self, other: Self):
+ fn __isub__(mut self, other: Self):
"""In-place set subtraction.
Updates the set to remove any elements from the `other` set.
@@ -260,7 +260,7 @@ struct Set[T: KeyElement](Sized, Comparable, Hashable, Boolable):
"""
return self.symmetric_difference(other)
- fn __ixor__(inout self, other: Self):
+ fn __ixor__(mut self, other: Self):
"""Overloads the ^= operator. Works like as `symmetric_difference_update` method.
Updates the set with the symmetric difference of itself and another set.
@@ -334,7 +334,7 @@ struct Set[T: KeyElement](Sized, Comparable, Hashable, Boolable):
fn write_to[
W: Writer,
U: RepresentableKeyElement,
- ](self: Set[U], inout writer: W):
+ ](self: Set[U], mut writer: W):
"""Write Set string representation to a `Writer`.
Parameters:
@@ -366,7 +366,7 @@ struct Set[T: KeyElement](Sized, Comparable, Hashable, Boolable):
# here we rely on Set being a trivial wrapper of a Dict
return _DictKeyIter(_DictEntryIter(0, 0, self._data))
- fn add(inout self, t: T):
+ fn add(mut self, t: T):
"""Add an element to the set.
Args:
@@ -374,7 +374,7 @@ struct Set[T: KeyElement](Sized, Comparable, Hashable, Boolable):
"""
self._data[t] = None
- fn remove(inout self, t: T) raises:
+ fn remove(mut self, t: T) raises:
"""Remove an element from the set.
Args:
@@ -385,7 +385,7 @@ struct Set[T: KeyElement](Sized, Comparable, Hashable, Boolable):
"""
self._data.pop(t)
- fn pop(inout self) raises -> T:
+ fn pop(mut self) raises -> T:
"""Remove any one item from the set, and return it.
As an implementation detail this will remove the first item
@@ -454,7 +454,7 @@ struct Set[T: KeyElement](Sized, Comparable, Hashable, Boolable):
result.add(e[])
return result^
- fn update(inout self, other: Self):
+ fn update(mut self, other: Self):
"""In-place set update.
Updates the set to contain all elements in the `other` set
@@ -466,7 +466,7 @@ struct Set[T: KeyElement](Sized, Comparable, Hashable, Boolable):
for e in other:
self.add(e[])
- fn intersection_update(inout self, other: Self):
+ fn intersection_update(mut self, other: Self):
"""In-place set intersection update.
Updates the set by retaining only elements found in both this set and the `other` set,
@@ -479,7 +479,7 @@ struct Set[T: KeyElement](Sized, Comparable, Hashable, Boolable):
# careful about concurrent iteration + mutation
self.difference_update(self - other)
- fn difference_update(inout self, other: Self):
+ fn difference_update(mut self, other: Self):
"""In-place set subtraction.
Updates the set by removing all elements found in the `other` set,
@@ -566,7 +566,7 @@ struct Set[T: KeyElement](Sized, Comparable, Hashable, Boolable):
return result^
- fn symmetric_difference_update(inout self, other: Self):
+ fn symmetric_difference_update(mut self, other: Self):
"""Updates the set with the symmetric difference of itself and another set.
Args:
@@ -574,7 +574,7 @@ struct Set[T: KeyElement](Sized, Comparable, Hashable, Boolable):
"""
self = self.symmetric_difference(other)
- fn discard(inout self, value: T):
+ fn discard(mut self, value: T):
"""Remove a value from the set if it exists. Pass otherwise.
Args:
@@ -585,7 +585,7 @@ struct Set[T: KeyElement](Sized, Comparable, Hashable, Boolable):
except:
pass
- fn clear(inout self):
+ fn clear(mut self):
"""Removes all elements from the set.
This method modifies the set in-place, removing all of its elements.
diff --git a/stdlib/src/collections/string.mojo b/stdlib/src/collections/string.mojo
index 363c9a6929..ba1eae54be 100644
--- a/stdlib/src/collections/string.mojo
+++ b/stdlib/src/collections/string.mojo
@@ -17,42 +17,39 @@ These are Mojo built-ins, so you don't need to import them.
from collections import KeyElement, List, Optional
from collections._index_normalization import normalize_index
+from hashlib._hasher import _HashableWithHasher, _Hasher
from sys import bitwidthof, llvm_intrinsic
from sys.ffi import c_char
-from utils import StaticString, write_args
+from sys.intrinsics import _type_is_eq
from bit import count_leading_zeros
-from memory import UnsafePointer, memcmp, memcpy
+from memory import UnsafePointer, memcmp, memcpy, Span
from python import PythonObject
-from sys.intrinsics import _type_is_eq
-from hashlib._hasher import _HashableWithHasher, _Hasher
-
from utils import (
- Span,
IndexList,
+ StaticString,
StringRef,
StringSlice,
Variant,
Writable,
Writer,
+ write_args,
)
-from utils.string_slice import (
- _utf8_byte_type,
- _StringSliceIter,
- _unicode_codepoint_utf8_byte_length,
- _shift_unicode_to_utf8,
- _FormatCurlyEntry,
- _CurlyEntryFormattable,
- _to_string_list,
-)
-
from utils._unicode import (
is_lowercase,
is_uppercase,
to_lowercase,
to_uppercase,
)
+from utils.format import _CurlyEntryFormattable, _FormatCurlyEntry
+from utils.string_slice import (
+ _shift_unicode_to_utf8,
+ _StringSliceIter,
+ _to_string_list,
+ _unicode_codepoint_utf8_byte_length,
+ _utf8_byte_type,
+)
# ===----------------------------------------------------------------------=== #
# ord
@@ -235,15 +232,15 @@ fn ascii(value: String) -> String:
# ===----------------------------------------------------------------------=== #
-fn _atol(str_ref: StringSlice[_], base: Int = 10) raises -> Int:
- """Implementation of `atol` for StringRef inputs.
+fn _atol(str_slice: StringSlice, base: Int = 10) raises -> Int:
+ """Implementation of `atol` for StringSlice inputs.
Please see its docstring for details.
"""
if (base != 0) and (base < 2 or base > 36):
raise Error("Base must be >= 2 and <= 36, or 0.")
- if not str_ref:
- raise Error(_atol_error(base, str_ref))
+ if not str_slice:
+ raise Error(_str_to_base_error(base, str_slice))
var real_base: Int
var ord_num_max: Int
@@ -253,53 +250,23 @@ fn _atol(str_ref: StringSlice[_], base: Int = 10) raises -> Int:
var is_negative: Bool = False
var has_prefix: Bool = False
var start: Int = 0
- var str_len = len(str_ref)
- var buff = str_ref.unsafe_ptr()
-
- for pos in range(start, str_len):
- if _isspace(buff[pos]):
- continue
+ var str_len = str_slice.byte_length()
- if str_ref[pos] == "-":
- is_negative = True
- start = pos + 1
- elif str_ref[pos] == "+":
- start = pos + 1
- else:
- start = pos
- break
-
- if str_ref[start] == "0" and start + 1 < str_len:
- if base == 2 and (
- str_ref[start + 1] == "b" or str_ref[start + 1] == "B"
- ):
- start += 2
- has_prefix = True
- elif base == 8 and (
- str_ref[start + 1] == "o" or str_ref[start + 1] == "O"
- ):
- start += 2
- has_prefix = True
- elif base == 16 and (
- str_ref[start + 1] == "x" or str_ref[start + 1] == "X"
- ):
- start += 2
- has_prefix = True
+ start, is_negative = _trim_and_handle_sign(str_slice, str_len)
alias ord_0 = ord("0")
- # FIXME:
- # Change this to `alias` after fixing support for __getitem__ of alias.
- var ord_letter_min = (ord("a"), ord("A"))
+ alias ord_letter_min = (ord("a"), ord("A"))
alias ord_underscore = ord("_")
if base == 0:
- var real_base_new_start = _identify_base(str_ref, start)
+ var real_base_new_start = _identify_base(str_slice, start)
real_base = real_base_new_start[0]
start = real_base_new_start[1]
has_prefix = real_base != 10
if real_base == -1:
- raise Error(_atol_error(base, str_ref))
+ raise Error(_str_to_base_error(base, str_slice))
else:
+ start, has_prefix = _handle_base_prefix(start, str_slice, str_len, base)
real_base = base
if real_base <= 10:
@@ -311,21 +278,23 @@ fn _atol(str_ref: StringSlice[_], base: Int = 10) raises -> Int:
ord("A") + (real_base - 11),
)
+ var buff = str_slice.unsafe_ptr()
var found_valid_chars_after_start = False
var has_space_after_number = False
+
# Prefixed integer literals with real_base 2, 8, 16 may begin with leading
# underscores under the conditions they have a prefix
- var was_last_digit_undescore = not (real_base in (2, 8, 16) and has_prefix)
+ var was_last_digit_underscore = not (real_base in (2, 8, 16) and has_prefix)
for pos in range(start, str_len):
var ord_current = int(buff[pos])
if ord_current == ord_underscore:
- if was_last_digit_undescore:
- raise Error(_atol_error(base, str_ref))
+ if was_last_digit_underscore:
+ raise Error(_str_to_base_error(base, str_slice))
else:
- was_last_digit_undescore = True
+ was_last_digit_underscore = True
continue
else:
- was_last_digit_undescore = False
+ was_last_digit_underscore = False
if ord_0 <= ord_current <= ord_num_max:
result += ord_current - ord_0
found_valid_chars_after_start = True
@@ -340,45 +309,100 @@ fn _atol(str_ref: StringSlice[_], base: Int = 10) raises -> Int:
start = pos + 1
break
else:
- raise Error(_atol_error(base, str_ref))
+ raise Error(_str_to_base_error(base, str_slice))
if pos + 1 < str_len and not _isspace(buff[pos + 1]):
var nextresult = result * real_base
if nextresult < result:
raise Error(
- _atol_error(base, str_ref)
+ _str_to_base_error(base, str_slice)
+ " String expresses an integer too large to store in Int."
)
result = nextresult
- if was_last_digit_undescore or (not found_valid_chars_after_start):
- raise Error(_atol_error(base, str_ref))
+ if was_last_digit_underscore or (not found_valid_chars_after_start):
+ raise Error(_str_to_base_error(base, str_slice))
if has_space_after_number:
for pos in range(start, str_len):
if not _isspace(buff[pos]):
- raise Error(_atol_error(base, str_ref))
+ raise Error(_str_to_base_error(base, str_slice))
if is_negative:
result = -result
return result
-fn _atol_error(base: Int, str_ref: StringSlice[_]) -> String:
+@always_inline
+fn _trim_and_handle_sign(str_slice: StringSlice, str_len: Int) -> (Int, Bool):
+ """Trims leading whitespace, handles the sign of the number in the string.
+
+ Args:
+ str_slice: A StringSlice containing the number to parse.
+ str_len: The length of the string.
+
+ Returns:
+ A tuple containing:
+ - The starting index of the number after whitespace and sign.
+ - A boolean indicating whether the number is negative.
+ """
+ var buff = str_slice.unsafe_ptr()
+ var start: Int = 0
+ while start < str_len and _isspace(buff[start]):
+ start += 1
+ var p: Bool = buff[start] == ord("+")
+ var n: Bool = buff[start] == ord("-")
+ return start + (p or n), n
+
+
+@always_inline
+fn _handle_base_prefix(
+ pos: Int, str_slice: StringSlice, str_len: Int, base: Int
+) -> (Int, Bool):
+ """Adjusts the starting position if a valid base prefix is present.
+
+ Handles "0b"/"0B" for base 2, "0o"/"0O" for base 8, and "0x"/"0X" for base
+ 16. Only adjusts if the base matches the prefix.
+
+ Args:
+ pos: Current position in the string.
+ str_slice: The input StringSlice.
+ str_len: Length of the input string.
+ base: The specified base.
+
+ Returns:
+ A tuple containing:
+ - Updated position after the prefix, if applicable.
+ - A boolean indicating if the prefix was valid for the given base.
+ """
+ var start = pos
+ var buff = str_slice.unsafe_ptr()
+ if start + 1 < str_len:
+ var prefix_char = chr(int(buff[start + 1]))
+ if buff[start] == ord("0") and (
+ (base == 2 and (prefix_char == "b" or prefix_char == "B"))
+ or (base == 8 and (prefix_char == "o" or prefix_char == "O"))
+ or (base == 16 and (prefix_char == "x" or prefix_char == "X"))
+ ):
+ start += 2
+ return start, start != pos
+
+
+fn _str_to_base_error(base: Int, str_slice: StringSlice) -> String:
return (
"String is not convertible to integer with base "
+ str(base)
+ ": '"
- + str(str_ref)
+ + str(str_slice)
+ "'"
)
-fn _identify_base(str_ref: StringSlice[_], start: Int) -> Tuple[Int, Int]:
- var length = len(str_ref)
+fn _identify_base(str_slice: StringSlice[_], start: Int) -> Tuple[Int, Int]:
+ var length = str_slice.byte_length()
# just 1 digit, assume base 10
if start == (length - 1):
return 10, start
- if str_ref[start] == "0":
- var second_digit = str_ref[start + 1]
+ if str_slice[start] == "0":
+ var second_digit = str_slice[start + 1]
if second_digit == "b" or second_digit == "B":
return 2, start + 2
if second_digit == "o" or second_digit == "O":
@@ -388,7 +412,7 @@ fn _identify_base(str_ref: StringSlice[_], start: Int) -> Tuple[Int, Int]:
# checking for special case of all "0", "_" are also allowed
var was_last_character_underscore = False
for i in range(start + 1, length):
- if str_ref[i] == "_":
+ if str_slice[i] == "_":
if was_last_character_underscore:
return -1, -1
else:
@@ -396,9 +420,9 @@ fn _identify_base(str_ref: StringSlice[_], start: Int) -> Tuple[Int, Int]:
continue
else:
was_last_character_underscore = False
- if str_ref[i] != "0":
+ if str_slice[i] != "0":
return -1, -1
- elif ord("1") <= ord(str_ref[start]) <= ord("9"):
+ elif ord("1") <= ord(str_slice[start]) <= ord("9"):
return 10, start
else:
return -1, -1
@@ -409,19 +433,37 @@ fn _identify_base(str_ref: StringSlice[_], start: Int) -> Tuple[Int, Int]:
fn atol(str: String, base: Int = 10) raises -> Int:
"""Parses and returns the given string as an integer in the given base.
- For example, `atol("19")` returns `19`. If base is 0 the the string is
- parsed as an Integer literal, see: https://docs.python.org/3/reference/lexical_analysis.html#integers.
-
- Raises:
- If the given string cannot be parsed as an integer value. For example in
- `atol("hi")`.
+ If base is set to 0, the string is parsed as an Integer literal, with the
+ following considerations:
+ - '0b' or '0B' prefix indicates binary (base 2)
+ - '0o' or '0O' prefix indicates octal (base 8)
+ - '0x' or '0X' prefix indicates hexadecimal (base 16)
+ - Without a prefix, it's treated as decimal (base 10)
Args:
str: A string to be parsed as an integer in the given base.
base: Base used for conversion, value must be between 2 and 36, or 0.
Returns:
- An integer value that represents the string, or otherwise raises.
+ An integer value that represents the string.
+
+ Raises:
+ If the given string cannot be parsed as an integer value or if an
+ incorrect base is provided.
+
+ Examples:
+ >>> atol("32")
+ 32
+ >>> atol("FF", 16)
+ 255
+ >>> atol("0xFF", 0)
+ 255
+ >>> atol("0b1010", 0)
+ 10
+
+ Notes:
+ This follows [Python's integer literals](
+ https://docs.python.org/3/reference/lexical_analysis.html#integers).
"""
return _atol(str.as_string_slice(), base)
@@ -743,7 +785,8 @@ struct String(
@always_inline
@implicit
fn __init__(out self, owned impl: List[UInt8, *_]):
- """Construct a string from a buffer of bytes.
+ """Construct a string from a buffer of bytes without copying the
+ allocated data.
The buffer must be terminated with a null byte:
@@ -773,6 +816,37 @@ struct String(
ptr=impl.steal_data(), length=size, capacity=capacity
)
+ @always_inline
+ @implicit
+ fn __init__(out self, impl: Self._buffer_type):
+ """Construct a string from a buffer of bytes, copying the allocated
+ data. Use the transfer operator ^ to avoid the copy.
+
+ The buffer must be terminated with a null byte:
+
+ ```mojo
+ var buf = List[UInt8]()
+ buf.append(ord('H'))
+ buf.append(ord('i'))
+ buf.append(0)
+ var hi = String(buf)
+ ```
+
+ Args:
+ impl: The buffer.
+ """
+ debug_assert(
+ len(impl) > 0 and impl[-1] == 0,
+ "expected last element of String buffer to be null terminator",
+ )
+ # We make a backup because steal_data() will clear size and capacity.
+ var size = impl.size
+ debug_assert(
+ impl[size - 1] == 0,
+ "expected last element of String buffer to be null terminator",
+ )
+ self._buffer = impl
+
@always_inline
fn __init__(out self):
"""Construct an uninitialized string."""
@@ -861,7 +935,7 @@ struct String(
# Factory dunders
# ===------------------------------------------------------------------=== #
- fn write_bytes(inout self, bytes: Span[Byte, _]):
+ fn write_bytes(mut self, bytes: Span[Byte, _]):
"""Write a byte span to this String.
Args:
@@ -870,7 +944,7 @@ struct String(
"""
self._iadd[False](bytes)
- fn write[*Ts: Writable](inout self, *args: *Ts):
+ fn write[*Ts: Writable](mut self, *args: *Ts):
"""Write a sequence of Writable arguments to the provided Writer.
Parameters:
@@ -1224,7 +1298,7 @@ struct String(
"""
return Self._add[True](other.as_bytes(), self.as_bytes())
- fn _iadd[has_null: Bool](inout self, other: Span[Byte]):
+ fn _iadd[has_null: Bool](mut self, other: Span[Byte]):
var s_len = self.byte_length()
var o_len = len(other)
var o_ptr = other.unsafe_ptr()
@@ -1245,7 +1319,7 @@ struct String(
s_ptr[sum_len] = 0
@always_inline
- fn __iadd__(inout self, other: String):
+ fn __iadd__(mut self, other: String):
"""Appends another string to this string.
Args:
@@ -1254,7 +1328,7 @@ struct String(
self._iadd[True](other.as_bytes())
@always_inline
- fn __iadd__(inout self, other: StringLiteral):
+ fn __iadd__(mut self, other: StringLiteral):
"""Appends another string literal to this string.
Args:
@@ -1263,7 +1337,7 @@ struct String(
self._iadd[False](other.as_bytes())
@always_inline
- fn __iadd__(inout self, other: StringSlice):
+ fn __iadd__(mut self, other: StringSlice):
"""Appends another string slice to this string.
Args:
@@ -1380,7 +1454,7 @@ struct String(
# Methods
# ===------------------------------------------------------------------=== #
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""
Formats this string to the provided Writer.
@@ -1435,7 +1509,6 @@ struct String(
result.write(a)
elems.each[add_elt]()
- _ = is_first
return result
fn join[T: StringableCollectionElement](self, elems: List[T, *_]) -> String:
@@ -1580,7 +1653,7 @@ struct String(
var length = len(self._buffer)
return length - int(length > 0)
- fn _steal_ptr(inout self) -> UnsafePointer[UInt8]:
+ fn _steal_ptr(mut self) -> UnsafePointer[UInt8]:
"""Transfer ownership of pointer to the underlying memory.
The caller is responsible for freeing up the memory.
@@ -1774,7 +1847,7 @@ struct String(
# Python adds all "whitespace chars" as one separator
# if no separator was specified
for s in self[lhs:]:
- if not str(s).isspace(): # TODO: with StringSlice.isspace()
+ if not s.isspace():
break
lhs += s.byte_length()
# if it went until the end of the String, then
@@ -1788,7 +1861,7 @@ struct String(
break
rhs = lhs + num_bytes(self.unsafe_ptr()[lhs])
for s in self[lhs + num_bytes(self.unsafe_ptr()[lhs]) :]:
- if str(s).isspace(): # TODO: with StringSlice.isspace()
+ if s.isspace():
break
rhs += s.byte_length()
@@ -1874,7 +1947,7 @@ struct String(
res.append(0)
return String(res^)
- fn strip(self, chars: String) -> String:
+ fn strip(self, chars: StringSlice) -> StringSlice[__origin_of(self)]:
"""Return a copy of the string with leading and trailing characters
removed.
@@ -1887,7 +1960,7 @@ struct String(
return self.lstrip(chars).rstrip(chars)
- fn strip(self) -> String:
+ fn strip(self) -> StringSlice[__origin_of(self)]:
"""Return a copy of the string with leading and trailing whitespaces
removed.
@@ -1896,7 +1969,7 @@ struct String(
"""
return self.lstrip().rstrip()
- fn rstrip(self, chars: String) -> String:
+ fn rstrip(self, chars: StringSlice) -> StringSlice[__origin_of(self)]:
"""Return a copy of the string with trailing characters removed.
Args:
@@ -1906,29 +1979,17 @@ struct String(
A copy of the string with no trailing characters.
"""
- var r_idx = self.byte_length()
- while r_idx > 0 and self[r_idx - 1] in chars:
- r_idx -= 1
-
- return self[:r_idx]
+ return self.as_string_slice().rstrip(chars)
- fn rstrip(self) -> String:
+ fn rstrip(self) -> StringSlice[__origin_of(self)]:
"""Return a copy of the string with trailing whitespaces removed.
Returns:
A copy of the string with no trailing whitespaces.
"""
- var r_idx = self.byte_length()
- # TODO (#933): should use this once llvm intrinsics can be used at comp time
- # for s in self.__reversed__():
- # if not s.isspace():
- # break
- # r_idx -= 1
- while r_idx > 0 and _isspace(self._buffer.unsafe_get(r_idx - 1)):
- r_idx -= 1
- return self[:r_idx]
-
- fn lstrip(self, chars: String) -> String:
+ return self.as_string_slice().rstrip()
+
+ fn lstrip(self, chars: StringSlice) -> StringSlice[__origin_of(self)]:
"""Return a copy of the string with leading characters removed.
Args:
@@ -1938,29 +1999,15 @@ struct String(
A copy of the string with no leading characters.
"""
- var l_idx = 0
- while l_idx < self.byte_length() and self[l_idx] in chars:
- l_idx += 1
+ return self.as_string_slice().lstrip(chars)
- return self[l_idx:]
-
- fn lstrip(self) -> String:
+ fn lstrip(self) -> StringSlice[__origin_of(self)]:
"""Return a copy of the string with leading whitespaces removed.
Returns:
A copy of the string with no leading whitespaces.
"""
- var l_idx = 0
- # TODO (#933): should use this once llvm intrinsics can be used at comp time
- # for s in self:
- # if not s.isspace():
- # break
- # l_idx += 1
- while l_idx < self.byte_length() and _isspace(
- self._buffer.unsafe_get(l_idx)
- ):
- l_idx += 1
- return self[l_idx:]
+ return self.as_string_slice().lstrip()
fn __hash__(self) -> UInt:
"""Hash the underlying buffer using builtin hash.
@@ -1972,7 +2019,7 @@ struct String(
"""
return hash(self.as_string_slice())
- fn __hash__[H: _Hasher](self, inout hasher: H):
+ fn __hash__[H: _Hasher](self, mut hasher: H):
"""Updates hasher with the underlying bytes.
Parameters:
@@ -2267,7 +2314,7 @@ struct String(
var result = String(buffer)
return result^
- fn reserve(inout self, new_capacity: Int):
+ fn reserve(mut self, new_capacity: Int):
"""Reserves the requested capacity.
Args:
diff --git a/stdlib/src/collections/vector.mojo b/stdlib/src/collections/vector.mojo
index 8812b4b61c..62196e6a15 100644
--- a/stdlib/src/collections/vector.mojo
+++ b/stdlib/src/collections/vector.mojo
@@ -19,14 +19,15 @@ from collections import InlinedFixedVector
```
"""
-from memory import Pointer, UnsafePointer, memcpy
from sys import sizeof
+from memory import Pointer, UnsafePointer, memcpy
+
from utils import StaticTuple
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# _VecIter
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@value
@@ -41,7 +42,7 @@ struct _VecIter[
var size: Int
var vec: UnsafePointer[vec_type]
- fn __next__(inout self) -> type:
+ fn __next__(mut self) -> type:
self.i += 1
return deref(self.vec, self.i - 1)
@@ -53,9 +54,9 @@ struct _VecIter[
return self.size - self.i
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# InlinedFixedVector
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -174,7 +175,7 @@ struct InlinedFixedVector[
self.dynamic_data = UnsafePointer[type]()
@always_inline
- fn append(inout self, value: type):
+ fn append(mut self, value: type):
"""Appends a value to this vector.
Args:
@@ -224,7 +225,7 @@ struct InlinedFixedVector[
return self.dynamic_data[normalized_idx - Self.static_size]
@always_inline
- fn __setitem__(inout self, idx: Int, value: type):
+ fn __setitem__(mut self, idx: Int, value: type):
"""Sets a vector element at the given index.
Args:
@@ -244,7 +245,7 @@ struct InlinedFixedVector[
else:
self.dynamic_data[normalized_idx - Self.static_size] = value
- fn clear(inout self):
+ fn clear(mut self):
"""Clears the elements in the vector."""
self.current_size = 0
@@ -254,7 +255,7 @@ struct InlinedFixedVector[
alias _iterator = _VecIter[type, Self, Self._deref_iter_impl]
- fn __iter__(inout self) -> Self._iterator:
+ fn __iter__(mut self) -> Self._iterator:
"""Iterate over the vector.
Returns:
diff --git a/stdlib/src/hashlib/__init__.mojo b/stdlib/src/hashlib/__init__.mojo
index 2bdc949799..9de67db15d 100644
--- a/stdlib/src/hashlib/__init__.mojo
+++ b/stdlib/src/hashlib/__init__.mojo
@@ -11,4 +11,4 @@
# limitations under the License.
# ===----------------------------------------------------------------------=== #
"""Implements the hashlib package that provides various hash algorithms."""
-from .hash import hash, Hashable
+from .hash import Hashable, hash
diff --git a/stdlib/src/hashlib/_ahash.mojo b/stdlib/src/hashlib/_ahash.mojo
index 0845dc8d58..56488c9a8d 100644
--- a/stdlib/src/hashlib/_ahash.mojo
+++ b/stdlib/src/hashlib/_ahash.mojo
@@ -11,10 +11,10 @@
# limitations under the License.
# ===----------------------------------------------------------------------=== #
-from bit import byte_swap
-from bit import rotate_bits_left
+from bit import byte_swap, rotate_bits_left
from memory import UnsafePointer
-from ._hasher import _Hasher, _HashableWithHasher
+
+from ._hasher import _HashableWithHasher, _Hasher
alias U256 = SIMD[DType.uint64, 4]
alias U128 = SIMD[DType.uint64, 2]
@@ -110,7 +110,7 @@ struct AHasher[key: U256](_Hasher):
self.extra_keys = U128(pi_key[2], pi_key[3])
@always_inline
- fn _update(inout self, new_data: UInt64):
+ fn _update(mut self, new_data: UInt64):
"""Update the buffer value with new data.
Args:
@@ -119,7 +119,7 @@ struct AHasher[key: U256](_Hasher):
self.buffer = _folded_multiply(new_data ^ self.buffer, MULTIPLE)
@always_inline
- fn _large_update(inout self, new_data: U128):
+ fn _large_update(mut self, new_data: U128):
"""Update the buffer value with new data.
Args:
@@ -129,7 +129,7 @@ struct AHasher[key: U256](_Hasher):
var combined = _folded_multiply(xored[0], xored[1])
self.buffer = rotate_bits_left[ROT]((self.buffer + self.pad) ^ combined)
- fn _update_with_bytes(inout self, data: UnsafePointer[UInt8], length: Int):
+ fn _update_with_bytes(mut self, data: UnsafePointer[UInt8], length: Int):
"""Consume provided data to update the internal buffer.
Args:
@@ -160,7 +160,7 @@ struct AHasher[key: U256](_Hasher):
var value = _read_small(data, length)
self._large_update(value)
- fn _update_with_simd(inout self, new_data: SIMD[_, _]):
+ fn _update_with_simd(mut self, new_data: SIMD[_, _]):
"""Update the buffer value with new data.
Args:
@@ -182,7 +182,7 @@ struct AHasher[key: U256](_Hasher):
for i in range(0, v64.size, 2):
self._large_update(U128(v64[i], v64[i + 1]))
- fn update[T: _HashableWithHasher](inout self, value: T):
+ fn update[T: _HashableWithHasher](mut self, value: T):
"""Update the buffer value with new hashable value.
Args:
diff --git a/stdlib/src/hashlib/_hasher.mojo b/stdlib/src/hashlib/_hasher.mojo
index 7bd278d5e9..f30e4de21a 100644
--- a/stdlib/src/hashlib/_hasher.mojo
+++ b/stdlib/src/hashlib/_hasher.mojo
@@ -11,12 +11,13 @@
# limitations under the License.
# ===----------------------------------------------------------------------=== #
-from ._ahash import AHasher
from memory import UnsafePointer
+from ._ahash import AHasher
+
trait _HashableWithHasher:
- fn __hash__[H: _Hasher](self, inout hasher: H):
+ fn __hash__[H: _Hasher](self, mut hasher: H):
...
@@ -24,13 +25,13 @@ trait _Hasher:
fn __init__(out self):
...
- fn _update_with_bytes(inout self, data: UnsafePointer[UInt8], length: Int):
+ fn _update_with_bytes(mut self, data: UnsafePointer[UInt8], length: Int):
...
- fn _update_with_simd(inout self, value: SIMD[_, _]):
+ fn _update_with_simd(mut self, value: SIMD[_, _]):
...
- fn update[T: _HashableWithHasher](inout self, value: T):
+ fn update[T: _HashableWithHasher](mut self, value: T):
...
fn finish(owned self) -> UInt64:
diff --git a/stdlib/src/hashlib/hash.mojo b/stdlib/src/hashlib/hash.mojo
index 84f3a82a58..5eddfc21b8 100644
--- a/stdlib/src/hashlib/hash.mojo
+++ b/stdlib/src/hashlib/hash.mojo
@@ -26,13 +26,12 @@ There are a few main tools in this module:
"""
import random
-
-from sys.ffi import _Global
-from sys import simdwidthof, bitwidthof
from collections import InlineArray
+from sys import bitwidthof, simdwidthof
+from sys.ffi import _Global
from builtin.dtype import _uint_type_of_width
-from memory import memcpy, memset_zero, stack_allocation, bitcast, UnsafePointer
+from memory import UnsafePointer, bitcast, memcpy, memset_zero, stack_allocation
# ===----------------------------------------------------------------------=== #
# Implementation
diff --git a/stdlib/src/math/__init__.mojo b/stdlib/src/math/__init__.mojo
index 3a9e67e7c7..54b918a837 100644
--- a/stdlib/src/math/__init__.mojo
+++ b/stdlib/src/math/__init__.mojo
@@ -15,7 +15,7 @@
# In Python, these are in the math module, so we also expose them here.
from utils.numerics import inf, isfinite, isinf, isnan, nan, nextafter, ulp
-from .constants import pi, e, tau
+from .constants import e, pi, tau
# These are not part of Python's `math` module, but we define them here.
from .math import (
@@ -36,6 +36,7 @@ from .math import (
cbrt,
ceil,
ceildiv,
+ clamp,
copysign,
cos,
cosh,
@@ -53,19 +54,20 @@ from .math import (
hypot,
iota,
isclose,
+ isqrt,
j0,
j1,
lcm,
ldexp,
lgamma,
log,
- log10,
log1p,
log2,
+ log10,
logb,
modf,
+ recip,
remainder,
- isqrt,
scalb,
sin,
sinh,
@@ -75,6 +77,4 @@ from .math import (
trunc,
y0,
y1,
- clamp,
- recip,
)
diff --git a/stdlib/src/math/math.mojo b/stdlib/src/math/math.mojo
index 7371d2a3df..9d5f53e0e4 100644
--- a/stdlib/src/math/math.mojo
+++ b/stdlib/src/math/math.mojo
@@ -20,26 +20,24 @@ from math import floor
"""
from collections import List
-from sys._assembly import inlined_assembly
-from sys.ffi import _external_call_const
from sys import (
- llvm_intrinsic,
bitwidthof,
has_avx512f,
- simdwidthof,
- is_nvidia_gpu,
is_amd_gpu,
+ is_nvidia_gpu,
+ llvm_intrinsic,
+ simdwidthof,
sizeof,
)
-
-from memory import UnsafePointer
+from sys._assembly import inlined_assembly
+from sys.ffi import _external_call_const
+from sys.info import _current_arch
from bit import count_trailing_zeros
from builtin.dtype import _integral_type_of
-from builtin.simd import _simd_apply, _modf
-from sys.info import _current_arch
+from builtin.simd import _modf, _simd_apply
+from memory import UnsafePointer, Span
-from utils import Span
from utils.index import IndexList
from utils.numerics import FPUtils, isnan, nan
from utils.static_tuple import StaticTuple
@@ -646,6 +644,8 @@ fn frexp[
type: DType, simd_width: Int, //
](x: SIMD[type, simd_width]) -> StaticTuple[SIMD[type, simd_width], 2]:
"""Breaks floating point values into a fractional part and an exponent part.
+ This follows C and Python in increasing the exponent by 1 and normalizing the
+ fraction from 0.5 to 1.0 instead of 1.0 to 2.0.
Constraints:
The input must be a floating-point type.
@@ -665,14 +665,15 @@ fn frexp[
constrained[type.is_floating_point(), "must be a floating point value"]()
alias T = SIMD[type, simd_width]
alias zero = T(0)
- alias max_exponent = FPUtils[type].max_exponent() - 1
+ # Add one to the resulting exponent up by subtracting 1 from the bias
+ alias exponent_bias = FPUtils[type].exponent_bias() - 1
alias mantissa_width = FPUtils[type].mantissa_width()
var mask1 = _frexp_mask1[simd_width, type]()
var mask2 = _frexp_mask2[simd_width, type]()
var x_int = x.to_bits()
var selector = x != zero
var exp = selector.select(
- (((mask1 & x_int) >> mantissa_width) - max_exponent).cast[type](),
+ (((mask1 & x_int) >> mantissa_width) - exponent_bias).cast[type](),
zero,
)
var frac = selector.select(T(from_bits=x_int & ~mask1 | mask2), zero)
@@ -1109,7 +1110,7 @@ fn iota[
buff.store(i, i + offset)
-fn iota[type: DType, //](inout v: List[Scalar[type], *_], offset: Int = 0):
+fn iota[type: DType, //](mut v: List[Scalar[type], *_], offset: Int = 0):
"""Fill a list with consecutive numbers starting from the specified offset.
Parameters:
@@ -1122,7 +1123,7 @@ fn iota[type: DType, //](inout v: List[Scalar[type], *_], offset: Int = 0):
iota(v.data, len(v), offset)
-fn iota(inout v: List[Int, *_], offset: Int = 0):
+fn iota(mut v: List[Int, *_], offset: Int = 0):
"""Fill a list with consecutive numbers starting from the specified offset.
Args:
@@ -1155,6 +1156,23 @@ fn fma(a: Int, b: Int, c: Int) -> Int:
return a * b + c
+@always_inline
+fn fma(a: UInt, b: UInt, c: UInt) -> UInt:
+ """Performs `fma` (fused multiply-add) on the inputs.
+
+ The result is `(a * b) + c`.
+
+ Args:
+ a: The first input.
+ b: The second input.
+ c: The third input.
+
+ Returns:
+ `(a * b) + c`.
+ """
+ return a * b + c
+
+
@always_inline("nodebug")
fn fma[
type: DType, simd_width: Int
@@ -1401,7 +1419,9 @@ fn cos[
instruction="cos.approx.ftz.f32", constraints="=f,f"
](x)
elif is_amd_gpu():
- return llvm_intrinsic["llvm.cos", __type_of(x)](x)
+ return llvm_intrinsic["llvm.cos", __type_of(x), has_side_effect=False](
+ x
+ )
else:
return _call_libm["cos"](x)
@@ -1436,7 +1456,9 @@ fn sin[
instruction="sin.approx.ftz.f32", constraints="=f,f"
](x)
elif is_amd_gpu():
- return llvm_intrinsic["llvm.sin", __type_of(x)](x)
+ return llvm_intrinsic["llvm.sin", __type_of(x), has_side_effect=False](
+ x
+ )
else:
return _call_libm["sin"](x)
@@ -1615,7 +1637,9 @@ fn log10(x: SIMD) -> __type_of(x):
* log10_2
)
elif is_amd_gpu():
- return llvm_intrinsic["llvm.log10", __type_of(x)](x)
+ return llvm_intrinsic[
+ "llvm.log10", __type_of(x), has_side_effect=False
+ ](x)
return _call_libm["log10"](x)
diff --git a/stdlib/src/math/polynomial.mojo b/stdlib/src/math/polynomial.mojo
index 8397218380..35384d33c1 100644
--- a/stdlib/src/math/polynomial.mojo
+++ b/stdlib/src/math/polynomial.mojo
@@ -21,9 +21,9 @@ from math.polynomial import polynomial_evaluate
from collections import List
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# polynomial_evaluate
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -49,9 +49,9 @@ fn polynomial_evaluate[
return _horner_evaluate[coefficients](x)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Horner Method
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
diff --git a/stdlib/src/memory/__init__.mojo b/stdlib/src/memory/__init__.mojo
index 06684698a7..2717a5127a 100644
--- a/stdlib/src/memory/__init__.mojo
+++ b/stdlib/src/memory/__init__.mojo
@@ -12,9 +12,10 @@
# ===----------------------------------------------------------------------=== #
"""Implements the memory package."""
-from .arc import Arc
+from .arc import ArcPointer
from .memory import memcmp, memcpy, memset, memset_zero, stack_allocation
from .owned_pointer import OwnedPointer
from .pointer import AddressSpace, Pointer
+from .span import AsBytes, Span
from .unsafe import bitcast, pack_bits
from .unsafe_pointer import UnsafePointer
diff --git a/stdlib/src/memory/arc.mojo b/stdlib/src/memory/arc.mojo
index fa904d53e8..8680d06560 100644
--- a/stdlib/src/memory/arc.mojo
+++ b/stdlib/src/memory/arc.mojo
@@ -10,47 +10,21 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# ===----------------------------------------------------------------------=== #
-"""Pointer-counted smart pointers.
+"""Reference-counted smart pointers.
-Example usage:
+You can import these APIs from the `memory` package. For example:
```mojo
-from memory import Arc
-var p = Arc(4)
-var p2 = p
-p2[]=3
-print(3 == p[])
+from memory import ArcPointer
```
-
-Subscripting(`[]`) is done by `Pointer`,
-in order to ensure that the underlying `Arc` outlive the operation.
-
-It is highly DISCOURAGED to manipulate an `Arc` through `UnsafePointer`.
-Mojo's ASAP deletion policy ensure values are destroyed at last use.
-Do not unsafely dereference the `Arc` inner `UnsafePointer` field.
-See [Lifecycle](https://docs.modular.com/mojo/manual/lifecycle/).
-
-```mojo
-# Illustration of what NOT to do, in order to understand:
-print(Arc(String("ok"))._inner[].payload)
-#........................^ASAP ^already freed
-```
-
-Always use `Pointer` subscripting (`[]`):
-
-```mojo
-print(Arc(String("ok"))[])
-```
-
"""
from os.atomic import Atomic
-from builtin.builtin_list import _lit_mut_cast
from memory import UnsafePointer, stack_allocation
-struct _ArcInner[T: Movable]:
+struct _ArcPointerInner[T: Movable]:
var refcount: Atomic[DType.uint64]
var payload: T
@@ -60,33 +34,60 @@ struct _ArcInner[T: Movable]:
self.refcount = Scalar[DType.uint64](1)
self.payload = value^
- fn add_ref(inout self):
+ fn add_ref(mut self):
"""Atomically increment the refcount."""
_ = self.refcount.fetch_add(1)
- fn drop_ref(inout self) -> Bool:
+ fn drop_ref(mut self) -> Bool:
"""Atomically decrement the refcount and return true if the result
hits zero."""
return self.refcount.fetch_sub(1) == 1
@register_passable
-struct Arc[T: Movable](CollectionElement, CollectionElementNew, Identifiable):
+struct ArcPointer[T: Movable](
+ CollectionElement, CollectionElementNew, Identifiable
+):
"""Atomic reference-counted pointer.
This smart pointer owns an instance of `T` indirectly managed on the heap.
This pointer is copyable, including across threads, maintaining a reference
count to the underlying data.
+ When you initialize an `ArcPointer` with a value, it allocates memory and
+ moves the value into the allocated memory. Copying an instance of an
+ `ArcPointer` increments the reference count. Destroying an instance
+ decrements the reference count. When the reference count reaches zero,
+ `ArcPointer` destroys the value and frees its memory.
+
This pointer itself is thread-safe using atomic accesses to reference count
the underlying data, but references returned to the underlying data are not
- thread safe.
+ thread-safe.
+
+ Subscripting an `ArcPointer` (`ptr[]`) returns a mutable reference to the
+ stored value. This is the only safe way to access the stored value. Other
+ methods, such as using the `unsafe_ptr()` method to retrieve an unsafe
+ pointer to the stored value, or accessing the private fields of an
+ `ArcPointer`, are unsafe and may result in memory errors.
+
+ For a comparison with other pointer types, see [Intro to
+ pointers](/mojo/manual/pointers/) in the Mojo Manual.
+
+ Examples:
+
+ ```mojo
+ from memory import ArcPointer
+ var p = ArcPointer(4)
+ var p2 = p
+ p2[]=3
+ print(3 == p[])
+ ```
Parameters:
T: The type of the stored value.
"""
- alias _inner_type = _ArcInner[T]
+ alias _inner_type = _ArcPointerInner[T]
var _inner: UnsafePointer[Self._inner_type]
@implicit
@@ -98,7 +99,7 @@ struct Arc[T: Movable](CollectionElement, CollectionElementNew, Identifiable):
value: The value to manage.
"""
self._inner = UnsafePointer[Self._inner_type].alloc(1)
- # Cannot use init_pointee_move as _ArcInner isn't movable.
+ # Cannot use init_pointee_move as _ArcPointerInner isn't movable.
__get_address_as_uninit_lvalue(self._inner.address) = Self._inner_type(
value^
)
@@ -125,9 +126,9 @@ struct Arc[T: Movable](CollectionElement, CollectionElementNew, Identifiable):
@no_inline
fn __del__(owned self):
- """Delete the smart pointer reference.
+ """Delete the smart pointer.
- Decrement the ref count for the reference. If there are no more
+ Decrement the reference count for the stored value. If there are no more
references, delete the object and free its memory."""
if self._inner[].drop_ref():
# Call inner destructor, then free the memory.
@@ -135,7 +136,7 @@ struct Arc[T: Movable](CollectionElement, CollectionElementNew, Identifiable):
self._inner.free()
# FIXME: The origin returned for this is currently self origin, which
- # keeps the Arc object alive as long as there are references into it. That
+ # keeps the ArcPointer object alive as long as there are references into it. That
# said, this isn't really the right modeling, we need hierarchical origins
# to model the mutability and invalidation of the returned reference
# correctly.
@@ -144,7 +145,7 @@ struct Arc[T: Movable](CollectionElement, CollectionElementNew, Identifiable):
](
ref [self_life]self,
) -> ref [
- _lit_mut_cast[self_life, result_mutable=True].result
+ MutableOrigin.cast_from[self_life].result
] T:
"""Returns a mutable reference to the managed value.
@@ -160,7 +161,7 @@ struct Arc[T: Movable](CollectionElement, CollectionElementNew, Identifiable):
"""Retrieves a pointer to the underlying memory.
Returns:
- The UnsafePointer to the underlying memory.
+ The `UnsafePointer` to the pointee.
"""
# TODO: consider removing this method.
return UnsafePointer.address_of(self._inner[].payload)
@@ -174,23 +175,27 @@ struct Arc[T: Movable](CollectionElement, CollectionElementNew, Identifiable):
return self._inner[].refcount.load()
fn __is__(self, rhs: Self) -> Bool:
- """Returns True if the two Arcs point at the same object.
+ """Returns True if the two `ArcPointer` instances point at the same
+ object.
Args:
- rhs: The other Arc.
+ rhs: The other `ArcPointer`.
Returns:
- True if the two Arcs point at the same object and False otherwise.
+ True if the two `ArcPointers` instances point at the same object and
+ False otherwise.
"""
return self._inner == rhs._inner
fn __isnot__(self, rhs: Self) -> Bool:
- """Returns True if the two Arcs point at different objects.
+ """Returns True if the two `ArcPointer` instances point at different
+ objects.
Args:
- rhs: The other Arc.
+ rhs: The other `ArcPointer`.
Returns:
- True if the two Arcs point at different objects and False otherwise.
+ True if the two `ArcPointer` instances point at different objects
+ and False otherwise.
"""
return self._inner != rhs._inner
diff --git a/stdlib/src/memory/maybe_uninitialized.mojo b/stdlib/src/memory/maybe_uninitialized.mojo
index 20901a6fff..8d224bdd88 100644
--- a/stdlib/src/memory/maybe_uninitialized.mojo
+++ b/stdlib/src/memory/maybe_uninitialized.mojo
@@ -62,7 +62,7 @@ struct UnsafeMaybeUninitialized[ElementType: AnyType](CollectionElementNew):
fn __init__[
MovableType: Movable
](
- inout self: UnsafeMaybeUninitialized[MovableType],
+ mut self: UnsafeMaybeUninitialized[MovableType],
owned value: MovableType,
):
"""The memory is now considered initialized.
@@ -98,7 +98,7 @@ struct UnsafeMaybeUninitialized[ElementType: AnyType](CollectionElementNew):
fn copy_from[
CopyableType: ExplicitlyCopyable
](
- inout self: UnsafeMaybeUninitialized[CopyableType],
+ mut self: UnsafeMaybeUninitialized[CopyableType],
other: UnsafeMaybeUninitialized[CopyableType],
):
"""Copy another object.
@@ -117,7 +117,7 @@ struct UnsafeMaybeUninitialized[ElementType: AnyType](CollectionElementNew):
@always_inline
fn copy_from[
CopyableType: ExplicitlyCopyable
- ](inout self: UnsafeMaybeUninitialized[CopyableType], other: CopyableType):
+ ](mut self: UnsafeMaybeUninitialized[CopyableType], other: CopyableType):
"""Copy another object.
This function assumes that the current memory is uninitialized.
@@ -152,8 +152,8 @@ struct UnsafeMaybeUninitialized[ElementType: AnyType](CollectionElementNew):
fn move_from[
MovableType: Movable
](
- inout self: UnsafeMaybeUninitialized[MovableType],
- inout other: UnsafeMaybeUninitialized[MovableType],
+ mut self: UnsafeMaybeUninitialized[MovableType],
+ mut other: UnsafeMaybeUninitialized[MovableType],
):
"""Move another object.
@@ -174,7 +174,7 @@ struct UnsafeMaybeUninitialized[ElementType: AnyType](CollectionElementNew):
fn move_from[
MovableType: Movable
](
- inout self: UnsafeMaybeUninitialized[MovableType],
+ mut self: UnsafeMaybeUninitialized[MovableType],
other: UnsafePointer[MovableType],
):
"""Move another object.
@@ -196,7 +196,7 @@ struct UnsafeMaybeUninitialized[ElementType: AnyType](CollectionElementNew):
fn write[
MovableType: Movable
](
- inout self: UnsafeMaybeUninitialized[MovableType],
+ mut self: UnsafeMaybeUninitialized[MovableType],
owned value: MovableType,
):
"""Write a value into an uninitialized memory location.
@@ -235,7 +235,7 @@ struct UnsafeMaybeUninitialized[ElementType: AnyType](CollectionElementNew):
return UnsafePointer.address_of(self._array).bitcast[Self.ElementType]()
@always_inline
- fn assume_initialized_destroy(inout self):
+ fn assume_initialized_destroy(mut self):
"""Runs the destructor of the internal value.
Calling this method assumes that the memory is initialized.
diff --git a/stdlib/src/memory/memory.mojo b/stdlib/src/memory/memory.mojo
index ab215ab5b0..8d3a525cb4 100644
--- a/stdlib/src/memory/memory.mojo
+++ b/stdlib/src/memory/memory.mojo
@@ -20,17 +20,18 @@ from memory import memcmp
"""
+from collections import Optional
+from sys import _libc as libc
from sys import (
alignof,
- llvm_intrinsic,
- sizeof,
- is_gpu,
external_call,
- simdwidthof,
+ is_gpu,
+ llvm_intrinsic,
simdbitwidth,
- _libc as libc,
+ simdwidthof,
+ sizeof,
)
-from collections import Optional
+
from memory.pointer import AddressSpace, _GPUAddressSpace
# ===----------------------------------------------------------------------=== #
@@ -43,15 +44,19 @@ fn _align_down(value: Int, alignment: Int) -> Int:
return value._positive_div(alignment) * alignment
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# memcmp
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
fn _memcmp_impl_unconstrained[
type: DType
-](s1: UnsafePointer[Scalar[type], _], s2: __type_of(s1), count: Int) -> Int:
+](
+ s1: UnsafePointer[Scalar[type], **_],
+ s2: UnsafePointer[Scalar[type], **_],
+ count: Int,
+) -> Int:
alias simd_width = simdwidthof[type]()
if count < simd_width:
for i in range(count):
@@ -95,7 +100,11 @@ fn _memcmp_impl_unconstrained[
@always_inline
fn _memcmp_impl[
type: DType
-](s1: UnsafePointer[Scalar[type], _], s2: __type_of(s1), count: Int) -> Int:
+](
+ s1: UnsafePointer[Scalar[type], **_],
+ s2: UnsafePointer[Scalar[type], **_],
+ count: Int,
+) -> Int:
constrained[type.is_integral(), "the input dtype must be integral"]()
return _memcmp_impl_unconstrained(s1, s2, count)
@@ -104,8 +113,8 @@ fn _memcmp_impl[
fn memcmp[
type: AnyType, address_space: AddressSpace
](
- s1: UnsafePointer[type, address_space],
- s2: UnsafePointer[type, address_space],
+ s1: UnsafePointer[type, address_space=address_space],
+ s2: UnsafePointer[type, address_space=address_space],
count: Int,
) -> Int:
"""Compares two buffers. Both strings are assumed to be of the same length.
@@ -137,14 +146,14 @@ fn memcmp[
return _memcmp_impl(s1.bitcast[Byte](), s2.bitcast[Byte](), byte_count)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# memcpy
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
fn _memcpy_impl(
- dest_data: UnsafePointer[Byte, *_], src_data: __type_of(dest_data), n: Int
+ dest_data: UnsafePointer[Byte, **_], src_data: __type_of(dest_data), n: Int
):
"""Copies a memory area.
@@ -228,8 +237,8 @@ fn _memcpy_impl(
fn memcpy[
T: AnyType
](
- dest: UnsafePointer[T, AddressSpace.GENERIC, *_],
- src: UnsafePointer[T, AddressSpace.GENERIC, *_],
+ dest: UnsafePointer[T, address_space = AddressSpace.GENERIC, **_],
+ src: UnsafePointer[T, address_space = AddressSpace.GENERIC, **_],
count: Int,
):
"""Copies a memory area.
@@ -250,15 +259,19 @@ fn memcpy[
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# memset
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
fn _memset_impl[
address_space: AddressSpace
-](ptr: UnsafePointer[Byte, address_space], value: Byte, count: Int):
+](
+ ptr: UnsafePointer[Byte, address_space=address_space],
+ value: Byte,
+ count: Int,
+):
alias simd_width = simdwidthof[Byte]()
var vector_end = _align_down(count, simd_width)
@@ -272,7 +285,11 @@ fn _memset_impl[
@always_inline
fn memset[
type: AnyType, address_space: AddressSpace
-](ptr: UnsafePointer[type, address_space], value: Byte, count: Int):
+](
+ ptr: UnsafePointer[type, address_space=address_space],
+ value: Byte,
+ count: Int,
+):
"""Fills memory with the given value.
Parameters:
@@ -287,15 +304,15 @@ fn memset[
_memset_impl(ptr.bitcast[Byte](), value, count * sizeof[type]())
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# memset_zero
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
fn memset_zero[
type: AnyType, address_space: AddressSpace, //
-](ptr: UnsafePointer[type, address_space], count: Int):
+](ptr: UnsafePointer[type, address_space=address_space], count: Int):
"""Fills memory with zeros.
Parameters:
@@ -312,7 +329,7 @@ fn memset_zero[
@always_inline
fn memset_zero[
type: DType, address_space: AddressSpace, //, *, count: Int
-](ptr: UnsafePointer[Scalar[type], address_space]):
+](ptr: UnsafePointer[Scalar[type], address_space=address_space]):
"""Fills memory with zeros.
Parameters:
@@ -339,9 +356,9 @@ fn memset_zero[
ptr.store(i, 0)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# stack_allocation
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -351,7 +368,7 @@ fn stack_allocation[
/,
alignment: Int = alignof[type]() if is_gpu() else 1,
address_space: AddressSpace = AddressSpace.GENERIC,
-]() -> UnsafePointer[Scalar[type], address_space]:
+]() -> UnsafePointer[Scalar[type], address_space=address_space]:
"""Allocates data buffer space on the stack given a data type and number of
elements.
@@ -378,7 +395,7 @@ fn stack_allocation[
name: Optional[StringLiteral] = None,
alignment: Int = alignof[type]() if is_gpu() else 1,
address_space: AddressSpace = AddressSpace.GENERIC,
-]() -> UnsafePointer[type, address_space]:
+]() -> UnsafePointer[type, address_space=address_space]:
"""Allocates data buffer space on the stack given a data type and number of
elements.
@@ -402,7 +419,9 @@ fn stack_allocation[
return __mlir_op.`pop.global_alloc`[
name = global_name.value,
count = count.value,
- _type = UnsafePointer[type, address_space]._mlir_type,
+ _type = UnsafePointer[
+ type, address_space=address_space
+ ]._mlir_type,
alignment = alignment.value,
]()
# MSTDL-797: The NVPTX backend requires that `alloca` instructions may
@@ -415,20 +434,22 @@ fn stack_allocation[
alignment = alignment.value,
]()
return __mlir_op.`pop.pointer.bitcast`[
- _type = UnsafePointer[type, address_space]._mlir_type
+ _type = UnsafePointer[
+ type, address_space=address_space
+ ]._mlir_type
](generic_ptr)
# Perofrm a stack allocation of the requested size, alignment, and type.
return __mlir_op.`pop.stack_allocation`[
count = count.value,
- _type = UnsafePointer[type, address_space]._mlir_type,
+ _type = UnsafePointer[type, address_space=address_space]._mlir_type,
alignment = alignment.value,
]()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# malloc
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -438,26 +459,29 @@ fn _malloc[
*,
alignment: Int = alignof[type]() if is_gpu() else 1,
](size: Int, /) -> UnsafePointer[
- type, AddressSpace.GENERIC, alignment=alignment
+ type, address_space = AddressSpace.GENERIC, alignment=alignment
]:
@parameter
if is_gpu():
return external_call[
- "malloc", UnsafePointer[NoneType, AddressSpace.GENERIC]
+ "malloc",
+ UnsafePointer[NoneType, address_space = AddressSpace.GENERIC],
](size).bitcast[type]()
else:
return __mlir_op.`pop.aligned_alloc`[
- _type = UnsafePointer[type, AddressSpace.GENERIC]._mlir_type
+ _type = UnsafePointer[
+ type, address_space = AddressSpace.GENERIC
+ ]._mlir_type
](alignment.value, size.value)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# aligned_free
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
-fn _free(ptr: UnsafePointer[_, AddressSpace.GENERIC, *_]):
+fn _free(ptr: UnsafePointer[_, address_space = AddressSpace.GENERIC, *_, **_]):
@parameter
if is_gpu():
libc.free(ptr.bitcast[NoneType]())
diff --git a/stdlib/src/memory/owned_pointer.mojo b/stdlib/src/memory/owned_pointer.mojo
index 4f00050e89..4dd473023c 100644
--- a/stdlib/src/memory/owned_pointer.mojo
+++ b/stdlib/src/memory/owned_pointer.mojo
@@ -10,7 +10,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# ===----------------------------------------------------------------------=== #
-from memory import UnsafePointer, stack_allocation, memcpy
+from memory import UnsafePointer, memcpy, stack_allocation
struct OwnedPointer[T: AnyType]:
@@ -21,17 +21,20 @@ struct OwnedPointer[T: AnyType]:
system such that no more than one mutable alias for the underlying data
may exist.
+ For a comparison with other pointer types, see [Intro to
+ pointers](/mojo/manual/pointers/) in the Mojo Manual.
+
Parameters:
T: The type to be stored in the OwnedPointer[].
"""
- var _inner: UnsafePointer[T, AddressSpace.GENERIC]
+ var _inner: UnsafePointer[T, address_space = AddressSpace.GENERIC]
# ===-------------------------------------------------------------------===#
# Life cycle methods
# ===-------------------------------------------------------------------===#
- fn __init__[T: Movable](inout self: OwnedPointer[T], owned value: T):
+ fn __init__[T: Movable](mut self: OwnedPointer[T], owned value: T):
"""Construct a new OwnedPointer[] by moving the passed value into a new backing allocation.
Parameters:
@@ -45,7 +48,7 @@ struct OwnedPointer[T: AnyType]:
fn __init__[
T: ExplicitlyCopyable
- ](inout self: OwnedPointer[T], *, copy_value: T):
+ ](mut self: OwnedPointer[T], *, copy_value: T):
"""Construct a new OwnedPointer[] by explicitly copying the passed value into a new backing allocation.
Parameters:
@@ -59,7 +62,7 @@ struct OwnedPointer[T: AnyType]:
fn __init__[
T: Copyable, U: NoneType = None
- ](inout self: OwnedPointer[T], value: T):
+ ](mut self: OwnedPointer[T], value: T):
"""Construct a new OwnedPointer[] by copying the passed value into a new backing allocation.
Parameters:
@@ -74,7 +77,7 @@ struct OwnedPointer[T: AnyType]:
fn __init__[
T: ExplicitlyCopyable
- ](inout self: OwnedPointer[T], *, other: OwnedPointer[T],):
+ ](mut self: OwnedPointer[T], *, other: OwnedPointer[T],):
"""Construct a new OwnedPointer[] by explicitly copying the value from another OwnedPointer[].
Parameters:
@@ -104,8 +107,8 @@ struct OwnedPointer[T: AnyType]:
# ===-------------------------------------------------------------------===#
fn __getitem__(
- ref [_, AddressSpace.GENERIC._value.value]self
- ) -> ref [self, AddressSpace.GENERIC._value.value] T:
+ ref [AddressSpace.GENERIC]self,
+ ) -> ref [self, AddressSpace.GENERIC] T:
"""Returns a reference to the pointers's underlying data with parametric mutability.
Returns:
@@ -116,7 +119,6 @@ struct OwnedPointer[T: AnyType]:
# returned from UnsafePointer to be guarded behind the
# aliasing guarantees of the origin system here.
# All of the magic happens above in the function signature
-
return self._inner[]
# ===-------------------------------------------------------------------===#
@@ -146,7 +148,7 @@ struct OwnedPointer[T: AnyType]:
"""
var r = self._inner.take_pointee()
self._inner.free()
- __mlir_op.`lit.ownership.mark_destroyed`(__get_mvalue_as_litref(self))
+ __disable_del self
return r^
@@ -169,6 +171,6 @@ struct OwnedPointer[T: AnyType]:
var ptr = self._inner
# Prevent the destructor from running on `self`
- __mlir_op.`lit.ownership.mark_destroyed`(__get_mvalue_as_litref(self))
+ __disable_del self
return ptr
diff --git a/stdlib/src/memory/pointer.mojo b/stdlib/src/memory/pointer.mojo
index dfccdc524c..16a4eadd29 100644
--- a/stdlib/src/memory/pointer.mojo
+++ b/stdlib/src/memory/pointer.mojo
@@ -19,11 +19,10 @@ from memory import Pointer
```
"""
-from sys import is_nvidia_gpu
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# AddressSpace
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@value
@@ -275,7 +274,7 @@ struct AddressSpace(EqualityComparable, Stringable, Writable):
return String.write(self)
@always_inline("nodebug")
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""
Formats the address space to the provided Writer.
@@ -291,9 +290,9 @@ struct AddressSpace(EqualityComparable, Stringable, Writable):
writer.write("AddressSpace(", self.value(), ")")
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Pointer
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@value
@@ -301,11 +300,14 @@ struct AddressSpace(EqualityComparable, Stringable, Writable):
struct Pointer[
is_mutable: Bool, //,
type: AnyType,
- origin: Origin[is_mutable].type,
+ origin: Origin[is_mutable],
address_space: AddressSpace = AddressSpace.GENERIC,
](CollectionElementNew, Stringable):
"""Defines a non-nullable safe pointer.
+ For a comparison with other pointer types, see [Intro to
+ pointers](/mojo/manual/pointers/) in the Mojo Manual.
+
Parameters:
is_mutable: Whether the pointee data may be mutated through this.
type: Type of the underlying data.
@@ -317,7 +319,7 @@ struct Pointer[
`!lit.ref<`,
type,
`, `,
- origin,
+ origin._mlir_origin,
`, `,
address_space._value.value,
`>`,
@@ -342,7 +344,7 @@ struct Pointer[
@staticmethod
@always_inline("nodebug")
- fn address_of(ref [origin, address_space._value.value]value: type) -> Self:
+ fn address_of(ref [origin, address_space]value: type) -> Self:
"""Constructs a Pointer from a reference to a value.
Args:
@@ -368,7 +370,7 @@ struct Pointer[
# ===------------------------------------------------------------------===#
@always_inline("nodebug")
- fn __getitem__(self) -> ref [origin, address_space._value.value] type:
+ fn __getitem__(self) -> ref [origin, address_space] type:
"""Enable subscript syntax `ptr[]` to access the element.
Returns:
diff --git a/stdlib/src/utils/span.mojo b/stdlib/src/memory/span.mojo
similarity index 91%
rename from stdlib/src/utils/span.mojo
rename to stdlib/src/memory/span.mojo
index 3ebb316f2d..497a084c88 100644
--- a/stdlib/src/utils/span.mojo
+++ b/stdlib/src/memory/span.mojo
@@ -13,16 +13,16 @@
"""Implements the Span type.
-You can import these APIs from the `utils.span` module. For example:
+You can import these APIs from the `memory` module. For example:
```mojo
-from utils import Span
+from memory import Span
```
"""
from collections import InlineArray
+
from memory import Pointer, UnsafePointer
-from builtin.builtin_list import _lit_mut_cast
trait AsBytes:
@@ -47,7 +47,7 @@ trait AsBytes:
struct _SpanIter[
is_mutable: Bool, //,
T: CollectionElement,
- origin: Origin[is_mutable].type,
+ origin: Origin[is_mutable],
forward: Bool = True,
]:
"""Iterator for Span.
@@ -68,7 +68,7 @@ struct _SpanIter[
@always_inline
fn __next__(
- inout self,
+ mut self,
) -> Pointer[T, origin]:
@parameter
if forward:
@@ -96,7 +96,7 @@ struct _SpanIter[
struct Span[
is_mutable: Bool, //,
T: CollectionElement,
- origin: Origin[is_mutable].type,
+ origin: Origin[is_mutable],
](CollectionElementNew):
"""A non owning view of contiguous data.
@@ -149,7 +149,7 @@ struct Span[
@always_inline
fn __init__[
size: Int, //
- ](inout self, ref [origin]array: InlineArray[T, size]):
+ ](mut self, ref [origin]array: InlineArray[T, size]):
"""Construct a Span from an InlineArray.
Parameters:
@@ -205,16 +205,9 @@ struct Span[
var step: Int
start, end, step = slc.indices(len(self))
- if step < 0:
- step = -step
- var new_len = (start - end + step - 1) // step
- var buff = UnsafePointer[T].alloc(new_len)
- i = 0
- while start > end:
- buff[i] = self._data[start]
- start -= step
- i += 1
- return Span[T, origin](ptr=buff, length=new_len)
+ debug_assert(
+ step == 1, "Slice must be within bounds and step must be 1"
+ )
var res = Self(
ptr=(self._data + start), length=len(range(start, end, step))
@@ -224,13 +217,22 @@ struct Span[
@always_inline
fn __iter__(self) -> _SpanIter[T, origin]:
- """Get an iterator over the elements of the span.
+ """Get an iterator over the elements of the Span.
Returns:
- An iterator over the elements of the span.
+ An iterator over the elements of the Span.
"""
return _SpanIter(0, self)
+ @always_inline
+ fn __reversed__(self) -> _SpanIter[T, origin, forward=False]:
+ """Iterate backwards over the Span.
+
+ Returns:
+ A reversed iterator of the Span elements.
+ """
+ return _SpanIter[forward=False](len(self), self)
+
# ===------------------------------------------------------------------===#
# Trait implementations
# ===------------------------------------------------------------------===#
@@ -357,13 +359,15 @@ struct Span[
for element in self:
element[] = value
- fn get_immutable(self) -> Span[T, _lit_mut_cast[origin, False].result]:
+ fn get_immutable(
+ self,
+ ) -> Span[T, ImmutableOrigin.cast_from[origin].result]:
"""
Return an immutable version of this span.
Returns:
A span covering the same elements, but without mutability.
"""
- return Span[T, _lit_mut_cast[origin, False].result](
+ return Span[T, ImmutableOrigin.cast_from[origin].result](
ptr=self._data, length=self._len
)
diff --git a/stdlib/src/memory/unsafe.mojo b/stdlib/src/memory/unsafe.mojo
index 82e995de53..450c18d199 100644
--- a/stdlib/src/memory/unsafe.mojo
+++ b/stdlib/src/memory/unsafe.mojo
@@ -21,9 +21,9 @@ from memory import bitcast
from sys import bitwidthof
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# bitcast
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
diff --git a/stdlib/src/memory/unsafe_pointer.mojo b/stdlib/src/memory/unsafe_pointer.mojo
index 9c75cc59a6..047bb61ac7 100644
--- a/stdlib/src/memory/unsafe_pointer.mojo
+++ b/stdlib/src/memory/unsafe_pointer.mojo
@@ -19,7 +19,7 @@ from memory import UnsafePointer
```
"""
-from sys import alignof, sizeof, is_nvidia_gpu, is_gpu
+from sys import alignof, is_gpu, is_nvidia_gpu, sizeof
from sys.intrinsics import (
_mlirtype_is_eq,
_type_is_eq,
@@ -32,7 +32,6 @@ from sys.intrinsics import (
from bit import is_power_of_two
from memory.memory import _free, _malloc
-
# ===----------------------------------------------------------------------=== #
# UnsafePointer
# ===----------------------------------------------------------------------=== #
@@ -51,9 +50,10 @@ fn _default_alignment[type: DType, width: Int = 1]() -> Int:
@register_passable("trivial")
struct UnsafePointer[
type: AnyType,
+ *,
address_space: AddressSpace = AddressSpace.GENERIC,
alignment: Int = _default_alignment[type](),
- origin: Origin[True].type = MutableAnyOrigin,
+ origin: Origin[True] = MutableAnyOrigin,
](
ImplicitlyBoolable,
CollectionElement,
@@ -63,7 +63,17 @@ struct UnsafePointer[
Intable,
Comparable,
):
- """This is a pointer type that can point to any generic value that is movable.
+ """UnsafePointer[T] represents an indirect reference to one or more values of
+ type T consecutively in memory, and can refer to uninitialized memory.
+
+ Because it supports referring to uninitialized memory, it provides unsafe
+ methods for initializing and destroying instances of T, as well as methods
+ for accessing the values once they are initialized.
+
+ For more information see [Unsafe
+ pointers](/mojo/manual/pointers/unsafe-pointers) in the Mojo Manual. For a
+ comparison with other pointer types, see [Intro to
+ pointers](/mojo/manual/pointers/).
Parameters:
type: The type the pointer points to.
@@ -84,12 +94,12 @@ struct UnsafePointer[
address_space._value.value,
`>`,
]
+ """The underlying pointer type."""
# ===-------------------------------------------------------------------===#
# Fields
# ===-------------------------------------------------------------------===#
- """The underlying pointer type."""
var address: Self._mlir_type
"""The underlying pointer."""
@@ -106,7 +116,7 @@ struct UnsafePointer[
@always_inline
@implicit
fn __init__(out self, value: Self._mlir_type):
- """Create a pointer with the input value.
+ """Create a pointer from a low-level pointer primitive.
Args:
value: The MLIR value of the pointer to construct with.
@@ -115,7 +125,9 @@ struct UnsafePointer[
@always_inline
@implicit
- fn __init__(out self, other: UnsafePointer[type, address_space, *_, **_]):
+ fn __init__(
+ out self, other: UnsafePointer[type, address_space=address_space, **_]
+ ):
"""Exclusivity parameter cast a pointer.
Args:
@@ -127,7 +139,7 @@ struct UnsafePointer[
@always_inline
fn __init__(out self, *, other: Self):
- """Copy the object.
+ """Copy an existing pointer.
Args:
other: The value to copy.
@@ -141,13 +153,15 @@ struct UnsafePointer[
@staticmethod
@always_inline("nodebug")
fn address_of(
- ref [_, address_space._value.value]arg: type
- ) -> UnsafePointer[
- type,
- address_space,
- 1,
- # TODO: Propagate origin of the argument.
- ] as result:
+ ref [address_space]arg: type,
+ out result: UnsafePointer[
+ type,
+ address_space=address_space,
+ alignment=1,
+ origin=MutableAnyOrigin
+ # TODO: Propagate origin of the argument.
+ ],
+ ):
"""Gets the address of the argument.
Args:
@@ -164,7 +178,9 @@ struct UnsafePointer[
@always_inline
fn alloc(
count: Int,
- ) -> UnsafePointer[type, AddressSpace.GENERIC, alignment]:
+ ) -> UnsafePointer[
+ type, address_space = AddressSpace.GENERIC, alignment=alignment
+ ]:
"""Allocate an array with specified or default alignment.
Args:
@@ -184,7 +200,7 @@ struct UnsafePointer[
@always_inline
fn __getitem__(
self,
- ) -> ref [origin, address_space._value.value] type:
+ ) -> ref [origin, address_space] type:
"""Return a reference to the underlying data.
Returns:
@@ -195,9 +211,12 @@ struct UnsafePointer[
alias _ref_type = Pointer[type, origin, address_space]
return __get_litref_as_mvalue(
__mlir_op.`lit.ref.from_pointer`[_type = _ref_type._mlir_type](
- UnsafePointer[type, address_space, alignment, origin](
- self
- ).address
+ UnsafePointer[
+ type,
+ address_space=address_space,
+ alignment=alignment,
+ origin=origin,
+ ](self).address
)
)
@@ -219,7 +238,7 @@ struct UnsafePointer[
@always_inline
fn __getitem__[
IntLike: IntLike, //
- ](self, offset: IntLike) -> ref [origin, address_space._value.value] type:
+ ](self, offset: IntLike) -> ref [origin, address_space] type:
"""Return a reference to the underlying data, offset by the given index.
Parameters:
@@ -264,7 +283,7 @@ struct UnsafePointer[
return self + (-1 * Int(offset.__mlir_index__()))
@always_inline
- fn __iadd__[T: IntLike, //](inout self, offset: T):
+ fn __iadd__[T: IntLike, //](mut self, offset: T):
"""Add an offset to this pointer.
Parameters:
@@ -276,7 +295,7 @@ struct UnsafePointer[
self = self + offset
@always_inline
- fn __isub__[T: IntLike, //](inout self, offset: T):
+ fn __isub__[T: IntLike, //](mut self, offset: T):
"""Subtract an offset from this pointer.
Parameters:
@@ -412,7 +431,7 @@ struct UnsafePointer[
return hex(int(self))
@no_inline
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""
Formats this pointer address to the provided Writer.
@@ -433,7 +452,9 @@ struct UnsafePointer[
@always_inline("nodebug")
fn as_noalias_ptr(
self,
- ) -> UnsafePointer[type, address_space, alignment, origin]:
+ ) -> UnsafePointer[
+ type, address_space=address_space, alignment=alignment, origin=origin
+ ]:
"""Cast the pointer to a new pointer that is known not to locally alias
any other pointer. In other words, the pointer transitively does not
alias any other memory value declared in the local function context.
@@ -454,7 +475,7 @@ struct UnsafePointer[
alignment: Int = _default_alignment[type, width](),
volatile: Bool = False,
invariant: Bool = False,
- ](self: UnsafePointer[Scalar[type], *_, **_]) -> SIMD[type, width]:
+ ](self: UnsafePointer[Scalar[type], **_]) -> SIMD[type, width]:
"""Loads the value the pointer points to.
Constraints:
@@ -530,7 +551,7 @@ struct UnsafePointer[
alignment: Int = _default_alignment[type, width](),
volatile: Bool = False,
invariant: Bool = False,
- ](self: UnsafePointer[Scalar[type], *_, **_], offset: Scalar) -> SIMD[
+ ](self: UnsafePointer[Scalar[type], **_], offset: Scalar) -> SIMD[
type, width
]:
"""Loads the value the pointer points to with the given offset.
@@ -569,9 +590,7 @@ struct UnsafePointer[
alignment: Int = _default_alignment[type, width](),
volatile: Bool = False,
invariant: Bool = False,
- ](self: UnsafePointer[Scalar[type], *_, **_], offset: T) -> SIMD[
- type, width
- ]:
+ ](self: UnsafePointer[Scalar[type], **_], offset: T) -> SIMD[type, width]:
"""Loads the value the pointer points to with the given offset.
Constraints:
@@ -605,11 +624,7 @@ struct UnsafePointer[
*,
alignment: Int = _default_alignment[type](),
volatile: Bool = False,
- ](
- self: UnsafePointer[Scalar[type], *_, **_],
- offset: T,
- val: Scalar[type],
- ):
+ ](self: UnsafePointer[Scalar[type], **_], offset: T, val: Scalar[type],):
"""Stores a single element value at the given offset.
Constraints:
@@ -637,7 +652,7 @@ struct UnsafePointer[
alignment: Int = _default_alignment[type, width](),
volatile: Bool = False,
](
- self: UnsafePointer[Scalar[type], *_, **_],
+ self: UnsafePointer[Scalar[type], **_],
offset: T,
val: SIMD[type, width],
):
@@ -668,7 +683,7 @@ struct UnsafePointer[
alignment: Int = _default_alignment[type](),
volatile: Bool = False,
](
- self: UnsafePointer[Scalar[type], *_, **_],
+ self: UnsafePointer[Scalar[type], **_],
offset: Scalar[offset_type],
val: Scalar[type],
):
@@ -701,7 +716,7 @@ struct UnsafePointer[
alignment: Int = _default_alignment[type, width](),
volatile: Bool = False,
](
- self: UnsafePointer[Scalar[type], *_, **_],
+ self: UnsafePointer[Scalar[type], **_],
offset: Scalar[offset_type],
val: SIMD[type, width],
):
@@ -732,7 +747,7 @@ struct UnsafePointer[
*,
alignment: Int = _default_alignment[type](),
volatile: Bool = False,
- ](self: UnsafePointer[Scalar[type], *_, **_], val: Scalar[type]):
+ ](self: UnsafePointer[Scalar[type], **_], val: Scalar[type]):
"""Stores a single element value.
Constraints:
@@ -755,7 +770,7 @@ struct UnsafePointer[
*,
alignment: Int = _default_alignment[type, width](),
volatile: Bool = False,
- ](self: UnsafePointer[Scalar[type], *_, **_], val: SIMD[type, width]):
+ ](self: UnsafePointer[Scalar[type], **_], val: SIMD[type, width]):
"""Stores a single element value.
Constraints:
@@ -779,7 +794,7 @@ struct UnsafePointer[
*,
alignment: Int = _default_alignment[type, width](),
volatile: Bool = False,
- ](self: UnsafePointer[Scalar[type], *_, **_], val: SIMD[type, width]):
+ ](self: UnsafePointer[Scalar[type], **_], val: SIMD[type, width]):
constrained[width > 0, "width must be a positive integer value"]()
constrained[
alignment > 0, "alignment must be a positive integer value"
@@ -798,9 +813,7 @@ struct UnsafePointer[
@always_inline("nodebug")
fn strided_load[
type: DType, T: Intable, //, width: Int
- ](self: UnsafePointer[Scalar[type], *_, **_], stride: T) -> SIMD[
- type, width
- ]:
+ ](self: UnsafePointer[Scalar[type], **_], stride: T) -> SIMD[type, width]:
"""Performs a strided load of the SIMD vector.
Parameters:
@@ -822,7 +835,7 @@ struct UnsafePointer[
T: Intable, //,
width: Int,
](
- self: UnsafePointer[Scalar[type], *_, **_],
+ self: UnsafePointer[Scalar[type], **_],
val: SIMD[type, width],
stride: T,
):
@@ -846,7 +859,7 @@ struct UnsafePointer[
width: Int = 1,
alignment: Int = _default_alignment[type, width](),
](
- self: UnsafePointer[Scalar[type], *_, **_],
+ self: UnsafePointer[Scalar[type], **_],
offset: SIMD[_, width],
mask: SIMD[DType.bool, width] = True,
default: SIMD[type, width] = 0,
@@ -901,7 +914,7 @@ struct UnsafePointer[
width: Int = 1,
alignment: Int = _default_alignment[type, width](),
](
- self: UnsafePointer[Scalar[type], *_, **_],
+ self: UnsafePointer[Scalar[type], **_],
offset: SIMD[_, width],
val: SIMD[type, width],
mask: SIMD[DType.bool, width] = True,
@@ -949,7 +962,7 @@ struct UnsafePointer[
scatter(val, base, mask, alignment)
@always_inline
- fn free(self: UnsafePointer[_, AddressSpace.GENERIC, *_, **_]):
+ fn free(self: UnsafePointer[_, address_space = AddressSpace.GENERIC, **_]):
"""Free the memory referenced by the pointer."""
_free(self)
@@ -959,8 +972,10 @@ struct UnsafePointer[
/,
address_space: AddressSpace = Self.address_space,
alignment: Int = Self.alignment,
- origin: Origin[True].type = Self.origin,
- ](self) -> UnsafePointer[T, address_space, alignment, origin]:
+ origin: Origin[True] = Self.origin,
+ ](self) -> UnsafePointer[
+ T, address_space=address_space, alignment=alignment, origin=origin
+ ]:
"""Bitcasts a UnsafePointer to a different type.
Parameters:
@@ -975,13 +990,13 @@ struct UnsafePointer[
"""
return __mlir_op.`pop.pointer.bitcast`[
_type = UnsafePointer[
- T, address_space, alignment=alignment
+ T, address_space=address_space, alignment=alignment
]._mlir_type,
](self.address)
@always_inline
fn destroy_pointee(
- self: UnsafePointer[type, AddressSpace.GENERIC, *_, **_]
+ self: UnsafePointer[type, address_space = AddressSpace.GENERIC, **_]
):
"""Destroy the pointed-to value.
@@ -996,7 +1011,7 @@ struct UnsafePointer[
@always_inline
fn take_pointee[
T: Movable, //,
- ](self: UnsafePointer[T, AddressSpace.GENERIC, *_, **_]) -> T:
+ ](self: UnsafePointer[T, address_space = AddressSpace.GENERIC, **_]) -> T:
"""Move the value at the pointer out, leaving it uninitialized.
The pointer must not be null, and the pointer memory location is assumed
@@ -1019,7 +1034,10 @@ struct UnsafePointer[
@always_inline
fn init_pointee_move[
T: Movable, //,
- ](self: UnsafePointer[T, AddressSpace.GENERIC, *_, **_], owned value: T):
+ ](
+ self: UnsafePointer[T, address_space = AddressSpace.GENERIC, **_],
+ owned value: T,
+ ):
"""Emplace a new value into the pointer location, moving from `value`.
The pointer memory location is assumed to contain uninitialized data,
@@ -1041,7 +1059,10 @@ struct UnsafePointer[
@always_inline
fn init_pointee_copy[
T: Copyable, //,
- ](self: UnsafePointer[T, AddressSpace.GENERIC, *_, **_], value: T):
+ ](
+ self: UnsafePointer[T, address_space = AddressSpace.GENERIC, **_],
+ value: T,
+ ):
"""Emplace a copy of `value` into the pointer location.
The pointer memory location is assumed to contain uninitialized data,
@@ -1063,7 +1084,10 @@ struct UnsafePointer[
@always_inline
fn init_pointee_explicit_copy[
T: ExplicitlyCopyable, //
- ](self: UnsafePointer[T, AddressSpace.GENERIC, *_, **_], value: T):
+ ](
+ self: UnsafePointer[T, address_space = AddressSpace.GENERIC, **_],
+ value: T,
+ ):
"""Emplace a copy of `value` into this pointer location.
The pointer memory location is assumed to contain uninitialized data,
@@ -1087,8 +1111,8 @@ struct UnsafePointer[
fn move_pointee_into[
T: Movable, //,
](
- self: UnsafePointer[T, AddressSpace.GENERIC, *_, **_],
- dst: UnsafePointer[T, AddressSpace.GENERIC, *_, **_],
+ self: UnsafePointer[T, address_space = AddressSpace.GENERIC, **_],
+ dst: UnsafePointer[T, address_space = AddressSpace.GENERIC, **_],
):
"""Moves the value `self` points to into the memory location pointed to by
`dst`.
diff --git a/stdlib/src/os/__init__.mojo b/stdlib/src/os/__init__.mojo
index b55400cad3..c07761b658 100644
--- a/stdlib/src/os/__init__.mojo
+++ b/stdlib/src/os/__init__.mojo
@@ -22,11 +22,11 @@ from .os import (
abort,
getuid,
listdir,
- mkdir,
makedirs,
+ mkdir,
remove,
- rmdir,
removedirs,
+ rmdir,
sep,
unlink,
)
diff --git a/stdlib/src/os/_linux_x86.mojo b/stdlib/src/os/_linux_x86.mojo
index d2872d8a1a..7fec00bfdf 100644
--- a/stdlib/src/os/_linux_x86.mojo
+++ b/stdlib/src/os/_linux_x86.mojo
@@ -11,9 +11,9 @@
# limitations under the License.
# ===----------------------------------------------------------------------=== #
-from time.time import _CTimeSpec
from collections import InlineArray
from sys.ffi import external_call
+from time.time import _CTimeSpec
from .fstat import stat_result
diff --git a/stdlib/src/os/atomic.mojo b/stdlib/src/os/atomic.mojo
index 73a97c09ea..5eaac49644 100644
--- a/stdlib/src/os/atomic.mojo
+++ b/stdlib/src/os/atomic.mojo
@@ -19,18 +19,20 @@ from os import Atomic
```
"""
+from sys.info import is_nvidia_gpu
+
from builtin.dtype import _integral_type_of, _unsigned_integral_type_of
from memory import UnsafePointer, bitcast
-from sys.info import is_nvidia_gpu
-struct Atomic[type: DType]:
+struct Atomic[type: DType, *, scope: StringLiteral = ""]:
"""Represents a value with atomic operations.
The class provides atomic `add` and `sub` methods for mutating the value.
Parameters:
type: DType of the value.
+ scope: The memory synchronization scope.
"""
var value: Scalar[type]
@@ -51,7 +53,7 @@ struct Atomic[type: DType]:
self.value = value
@always_inline
- fn load(inout self) -> Scalar[type]:
+ fn load(mut self) -> Scalar[type]:
"""Loads the current value from the atomic.
Returns:
@@ -62,7 +64,7 @@ struct Atomic[type: DType]:
@staticmethod
@always_inline
fn _fetch_add(
- ptr: UnsafePointer[Scalar[type], *_], rhs: Scalar[type]
+ ptr: UnsafePointer[Scalar[type], **_], rhs: Scalar[type]
) -> Scalar[type]:
"""Performs atomic in-place add.
@@ -82,6 +84,7 @@ struct Atomic[type: DType]:
return __mlir_op.`pop.atomic.rmw`[
bin_op = __mlir_attr.`#pop`,
ordering = __mlir_attr.`#pop`,
+ syncscope = scope.value,
_type = __mlir_type[`!pop.scalar<`, type.value, `>`],
](
ptr.bitcast[__mlir_type[`!pop.scalar<`, type.value, `>`]]().address,
@@ -89,7 +92,7 @@ struct Atomic[type: DType]:
)
@always_inline
- fn fetch_add(inout self, rhs: Scalar[type]) -> Scalar[type]:
+ fn fetch_add(mut self, rhs: Scalar[type]) -> Scalar[type]:
"""Performs atomic in-place add.
Atomically replaces the current value with the result of arithmetic
@@ -108,7 +111,7 @@ struct Atomic[type: DType]:
return Self._fetch_add(value_addr, rhs)
@always_inline
- fn __iadd__(inout self, rhs: Scalar[type]):
+ fn __iadd__(mut self, rhs: Scalar[type]):
"""Performs atomic in-place add.
Atomically replaces the current value with the result of arithmetic
@@ -123,7 +126,7 @@ struct Atomic[type: DType]:
_ = self.fetch_add(rhs)
@always_inline
- fn fetch_sub(inout self, rhs: Scalar[type]) -> Scalar[type]:
+ fn fetch_sub(mut self, rhs: Scalar[type]) -> Scalar[type]:
"""Performs atomic in-place sub.
Atomically replaces the current value with the result of arithmetic
@@ -142,11 +145,12 @@ struct Atomic[type: DType]:
return __mlir_op.`pop.atomic.rmw`[
bin_op = __mlir_attr.`#pop`,
ordering = __mlir_attr.`#pop`,
+ syncscope = scope.value,
_type = __mlir_type[`!pop.scalar<`, type.value, `>`],
](value_addr.address, rhs.value)
@always_inline
- fn __isub__(inout self, rhs: Scalar[type]):
+ fn __isub__(mut self, rhs: Scalar[type]):
"""Performs atomic in-place sub.
Atomically replaces the current value with the result of arithmetic
@@ -162,7 +166,7 @@ struct Atomic[type: DType]:
@always_inline
fn compare_exchange_weak(
- inout self, inout expected: Scalar[type], desired: Scalar[type]
+ mut self, mut expected: Scalar[type], desired: Scalar[type]
) -> Bool:
"""Atomically compares the self value with that of the expected value.
If the values are equal, then the self value is replaced with the
@@ -180,7 +184,7 @@ struct Atomic[type: DType]:
@parameter
if type.is_integral():
- return _compare_exchange_weak_integral_impl(
+ return _compare_exchange_weak_integral_impl[scope=scope](
UnsafePointer.address_of(self.value), expected, desired
)
@@ -194,13 +198,13 @@ struct Atomic[type: DType]:
]()
var expected_integral = bitcast[integral_type](expected)
var desired_integral = bitcast[integral_type](desired)
- return _compare_exchange_weak_integral_impl(
+ return _compare_exchange_weak_integral_impl[scope=scope](
value_integral_addr, expected_integral, desired_integral
)
@staticmethod
@always_inline
- fn max(ptr: UnsafePointer[Scalar[type], *_], rhs: Scalar[type]):
+ fn max(ptr: UnsafePointer[Scalar[type], **_], rhs: Scalar[type]):
"""Performs atomic in-place max on the pointer.
Atomically replaces the current value pointer to by `ptr` by the result
@@ -217,10 +221,10 @@ struct Atomic[type: DType]:
"""
constrained[type.is_numeric(), "the input type must be arithmetic"]()
- _max_impl(ptr, rhs)
+ _max_impl[scope=scope](ptr, rhs)
@always_inline
- fn max(inout self, rhs: Scalar[type]):
+ fn max(mut self, rhs: Scalar[type]):
"""Performs atomic in-place max.
Atomically replaces the current value with the result of max of the
@@ -240,7 +244,7 @@ struct Atomic[type: DType]:
@staticmethod
@always_inline
- fn min(ptr: UnsafePointer[Scalar[type], *_], rhs: Scalar[type]):
+ fn min(ptr: UnsafePointer[Scalar[type], **_], rhs: Scalar[type]):
"""Performs atomic in-place min on the pointer.
Atomically replaces the current value pointer to by `ptr` by the result
@@ -257,10 +261,10 @@ struct Atomic[type: DType]:
"""
constrained[type.is_numeric(), "the input type must be arithmetic"]()
- _min_impl(ptr, rhs)
+ _min_impl[scope=scope](ptr, rhs)
@always_inline
- fn min(inout self, rhs: Scalar[type]):
+ fn min(mut self, rhs: Scalar[type]):
"""Performs atomic in-place min.
Atomically replaces the current value with the result of min of the
@@ -280,17 +284,17 @@ struct Atomic[type: DType]:
Self.min(UnsafePointer.address_of(self.value), rhs)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Utilities
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
fn _compare_exchange_weak_integral_impl[
- type: DType, //
+ type: DType, //, *, scope: StringLiteral
](
- value_addr: UnsafePointer[Scalar[type], *_],
- inout expected: Scalar[type],
+ value_addr: UnsafePointer[Scalar[type], **_],
+ mut expected: Scalar[type],
desired: Scalar[type],
) -> Bool:
constrained[type.is_integral(), "the input type must be integral"]()
@@ -298,6 +302,7 @@ fn _compare_exchange_weak_integral_impl[
bin_op = __mlir_attr.`#pop`,
failure_ordering = __mlir_attr.`#pop`,
success_ordering = __mlir_attr.`#pop`,
+ syncscope = scope.value,
](
value_addr.bitcast[
__mlir_type[`!pop.scalar<`, type.value, `>`]
@@ -317,69 +322,71 @@ fn _compare_exchange_weak_integral_impl[
@always_inline
fn _max_impl_base[
- type: DType, //
-](ptr: UnsafePointer[Scalar[type], *_], rhs: Scalar[type]):
+ type: DType, //, *, scope: StringLiteral
+](ptr: UnsafePointer[Scalar[type], **_], rhs: Scalar[type]):
var value_addr = ptr.bitcast[__mlir_type[`!pop.scalar<`, type.value, `>`]]()
_ = __mlir_op.`pop.atomic.rmw`[
bin_op = __mlir_attr.`#pop`,
ordering = __mlir_attr.`#pop`,
+ syncscope = scope.value,
_type = __mlir_type[`!pop.scalar<`, type.value, `>`],
](value_addr.address, rhs.value)
@always_inline
fn _min_impl_base[
- type: DType, //
-](ptr: UnsafePointer[Scalar[type], *_], rhs: Scalar[type]):
+ type: DType, //, *, scope: StringLiteral
+](ptr: UnsafePointer[Scalar[type], **_], rhs: Scalar[type]):
var value_addr = ptr.bitcast[__mlir_type[`!pop.scalar<`, type.value, `>`]]()
_ = __mlir_op.`pop.atomic.rmw`[
bin_op = __mlir_attr.`#pop`,
ordering = __mlir_attr.`#pop`,
+ syncscope = scope.value,
_type = __mlir_type[`!pop.scalar<`, type.value, `>`],
](value_addr.address, rhs.value)
@always_inline
fn _max_impl[
- type: DType, //
-](ptr: UnsafePointer[Scalar[type], *_], rhs: Scalar[type]):
+ type: DType, //, *, scope: StringLiteral
+](ptr: UnsafePointer[Scalar[type], **_], rhs: Scalar[type]):
@parameter
if is_nvidia_gpu() and type.is_floating_point():
alias integral_type = _integral_type_of[type]()
alias unsigned_integral_type = _unsigned_integral_type_of[type]()
if rhs >= 0:
- _max_impl_base(
+ _max_impl_base[scope=scope](
ptr.bitcast[Scalar[integral_type]](),
bitcast[integral_type](rhs),
)
return
- _min_impl_base(
+ _min_impl_base[scope=scope](
ptr.bitcast[Scalar[unsigned_integral_type]](),
bitcast[unsigned_integral_type](rhs),
)
return
- _max_impl_base(ptr, rhs)
+ _max_impl_base[scope=scope](ptr, rhs)
@always_inline
fn _min_impl[
- type: DType, //
-](ptr: UnsafePointer[Scalar[type], *_], rhs: Scalar[type]):
+ type: DType, //, *, scope: StringLiteral
+](ptr: UnsafePointer[Scalar[type], **_], rhs: Scalar[type]):
@parameter
if is_nvidia_gpu() and type.is_floating_point():
alias integral_type = _integral_type_of[type]()
alias unsigned_integral_type = _unsigned_integral_type_of[type]()
if rhs >= 0:
- _min_impl_base(
+ _min_impl_base[scope=scope](
ptr.bitcast[Scalar[integral_type]](),
bitcast[integral_type](rhs),
)
return
- _max_impl_base(
+ _max_impl_base[scope=scope](
ptr.bitcast[Scalar[unsigned_integral_type]](),
bitcast[unsigned_integral_type](rhs),
)
return
- _min_impl_base(ptr, rhs)
+ _min_impl_base[scope=scope](ptr, rhs)
diff --git a/stdlib/src/os/env.mojo b/stdlib/src/os/env.mojo
index 0556389882..9ffe0eb2d8 100644
--- a/stdlib/src/os/env.mojo
+++ b/stdlib/src/os/env.mojo
@@ -23,6 +23,7 @@ from sys import external_call, os_is_linux, os_is_macos, os_is_windows
from sys.ffi import c_int
from memory import UnsafePointer
+
from utils import StringRef
diff --git a/stdlib/src/os/fstat.mojo b/stdlib/src/os/fstat.mojo
index ba298916d4..83e493bc7a 100644
--- a/stdlib/src/os/fstat.mojo
+++ b/stdlib/src/os/fstat.mojo
@@ -96,7 +96,7 @@ struct stat_result(Stringable, Writable):
"""User defined flags for file."""
fn __init__(
- inout self,
+ mut self,
/,
*,
st_mode: Int,
@@ -151,7 +151,7 @@ struct stat_result(Stringable, Writable):
self.st_flags = st_flags
@no_inline
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""
Formats this path to the provided Writer.
diff --git a/stdlib/src/os/os.mojo b/stdlib/src/os/os.mojo
index d66008b196..86c793fa6b 100644
--- a/stdlib/src/os/os.mojo
+++ b/stdlib/src/os/os.mojo
@@ -19,11 +19,12 @@ from os import listdir
```
"""
-from collections import List, InlineArray
-from sys import os_is_linux, os_is_windows, is_nvidia_gpu, external_call
-from sys.ffi import c_char, OpaquePointer
+from collections import InlineArray, List
+from sys import external_call, is_gpu, os_is_linux, os_is_windows
+from sys.ffi import OpaquePointer, c_char
from memory import UnsafePointer
+
from utils import StringRef
from .path import isdir, split
@@ -265,7 +266,7 @@ fn abort[
"""
@parameter
- if not is_nvidia_gpu():
+ if not is_gpu():
print(message, flush=True)
return abort[result]()
diff --git a/stdlib/src/os/path/__init__.mojo b/stdlib/src/os/path/__init__.mojo
index 68097ee4db..ef6694482a 100644
--- a/stdlib/src/os/path/__init__.mojo
+++ b/stdlib/src/os/path/__init__.mojo
@@ -12,6 +12,7 @@
# ===----------------------------------------------------------------------=== #
from .path import (
+ basename,
dirname,
exists,
expanduser,
@@ -21,6 +22,7 @@ from .path import (
isfile,
islink,
join,
- split,
lexists,
+ split,
+ splitroot,
)
diff --git a/stdlib/src/os/path/path.mojo b/stdlib/src/os/path/path.mojo
index 4bd3930a26..4e65dfbf34 100644
--- a/stdlib/src/os/path/path.mojo
+++ b/stdlib/src/os/path/path.mojo
@@ -19,10 +19,13 @@ from os.path import isdir
```
"""
-from collections import List, InlineArray
+from collections import InlineArray, List
+from pwd import getpwuid
from stat import S_ISDIR, S_ISLNK, S_ISREG
from sys import has_neon, os_is_linux, os_is_macos, os_is_windows
-from utils import Span, StringSlice
+
+from memory import Span
+from utils import StringSlice
from .. import PathLike
from .._linux_aarch64 import _lstat as _lstat_linux_arm
@@ -31,10 +34,9 @@ from .._linux_x86 import _lstat as _lstat_linux_x86
from .._linux_x86 import _stat as _stat_linux_x86
from .._macos import _lstat as _lstat_macos
from .._macos import _stat as _stat_macos
+from ..env import getenv
from ..fstat import stat
from ..os import sep
-from ..env import getenv
-from pwd import getpwuid
# ===----------------------------------------------------------------------=== #
@@ -228,11 +230,10 @@ fn dirname[PathLike: os.PathLike, //](path: PathLike) -> String:
The directory component of a pathname.
"""
var fspath = path.__fspath__()
- alias sep = str(os.sep)
- var i = fspath.rfind(sep) + 1
+ var i = fspath.rfind(os.sep) + 1
var head = fspath[:i]
- if head and head != sep * len(head):
- return head.rstrip(sep)
+ if head and head != os.sep * len(head):
+ return head.rstrip(os.sep)
return head
@@ -364,10 +365,34 @@ def split[PathLike: os.PathLike, //](path: PathLike) -> (String, String):
i = fspath.rfind(os.sep) + 1
head, tail = fspath[:i], fspath[i:]
if head and head != str(os.sep) * len(head):
- head = head.rstrip(sep)
+ head = str(head.rstrip(sep))
return head, tail
+fn basename[PathLike: os.PathLike, //](path: PathLike) -> String:
+ """Returns the tail section of a path.
+
+ ```mojo
+ basename("a/path/foo.txt") # returns "foo.txt"
+ ```
+
+ Parameters:
+ PathLike: The type conforming to the os.PathLike trait.
+
+ Args:
+ path: The path to retrieve the basename from.
+
+ Returns:
+ The basename from the path.
+ """
+ var fspath = path.__fspath__()
+ var i = fspath.rfind(os.sep) + 1
+ var head = fspath[i:]
+ if head and head != os.sep * len(head):
+ return head.rstrip(os.sep)
+ return head
+
+
# TODO uncomment this when unpacking is supported
# fn join[PathLike: os.PathLike](path: PathLike, *paths: PathLike) -> String:
# """Join two or more pathname components, inserting '/' as needed.
@@ -392,6 +417,41 @@ def split[PathLike: os.PathLike, //](path: PathLike) -> (String, String):
# return join(path.__fspath__(), *paths_str)
+# ===----------------------------------------------------------------------=== #
+# splitroot
+# ===----------------------------------------------------------------------=== #
+
+
+fn splitroot[
+ PathLike: os.PathLike, //
+](path: PathLike) -> Tuple[String, String, String]:
+ """Splits `path` into drive, root and tail. The tail contains anything after the root.
+
+ Parameters:
+ PathLike: The type conforming to the os.PathLike trait.
+
+ Args:
+ path: The path to be split.
+
+ Returns:
+ A tuple containing three strings: (drive, root, tail).
+ """
+ var p = path.__fspath__()
+ alias empty = String("")
+
+ # Relative path, e.g.: 'foo'
+ if p[:1] != sep:
+ return empty, empty, p
+
+ # Absolute path, e.g.: '/foo', '///foo', '////foo', etc.
+ elif p[1:2] != sep or p[2:3] == sep:
+ return empty, String(sep), p[1:]
+
+ # Precisely two leading slashes, e.g.: '//foo'. Implementation defined per POSIX, see
+ # https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
+ else:
+ return empty, p[:2], p[2:]
+
# ===----------------------------------------------------------------------=== #
# expandvars
diff --git a/stdlib/src/pathlib/path.mojo b/stdlib/src/pathlib/path.mojo
index 0d4449d405..c6e9016b5e 100644
--- a/stdlib/src/pathlib/path.mojo
+++ b/stdlib/src/pathlib/path.mojo
@@ -15,14 +15,13 @@
import os
from collections import List
+from hashlib._hasher import _HashableWithHasher, _Hasher
from os import PathLike, listdir, stat_result
-from sys import os_is_windows, external_call
+from sys import external_call, os_is_windows
from sys.ffi import c_char
from builtin._location import __call_location, _SourceLocation
-from memory import stack_allocation, UnsafePointer
-
-from hashlib._hasher import _HashableWithHasher, _Hasher
+from memory import UnsafePointer, stack_allocation
from utils import StringRef
@@ -125,7 +124,7 @@ struct Path(
res /= suffix
return res
- fn __itruediv__(inout self, suffix: String):
+ fn __itruediv__(mut self, suffix: String):
"""Joins two paths using the system-defined path separator.
Args:
@@ -154,7 +153,7 @@ struct Path(
"""
return self.path.byte_length() > 0
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""
Formats this path to the provided Writer.
@@ -226,7 +225,7 @@ struct Path(
return hash(self.path)
- fn __hash__[H: _Hasher](self, inout hasher: H):
+ fn __hash__[H: _Hasher](self, mut hasher: H):
"""Updates hasher with the path string value.
Parameters:
diff --git a/stdlib/src/prelude/__init__.mojo b/stdlib/src/prelude/__init__.mojo
index 9eead08fea..8761eba00c 100644
--- a/stdlib/src/prelude/__init__.mojo
+++ b/stdlib/src/prelude/__init__.mojo
@@ -14,8 +14,23 @@
that are automatically imported into every Mojo program.
"""
-from builtin.anytype import AnyType
-from builtin.bool import Boolable, ImplicitlyBoolable, Bool, bool, any, all
+from collections import KeyElement, List
+from collections.string import (
+ String,
+ ascii,
+ atof,
+ atol,
+ chr,
+ isdigit,
+ islower,
+ isprintable,
+ isupper,
+ ord,
+)
+from hashlib.hash import Hashable, hash
+
+from builtin.anytype import AnyType, UnknownDestructibility
+from builtin.bool import Bool, Boolable, ImplicitlyBoolable, all, any, bool
from builtin.breakpoint import breakpoint
from builtin.builtin_list import (
ListLiteral,
@@ -26,38 +41,38 @@ from builtin.builtin_list import (
from builtin.builtin_slice import Slice, slice
from builtin.comparable import Comparable
from builtin.constrained import constrained
-from builtin.coroutine import Coroutine, RaisingCoroutine, AnyCoroutine
+from builtin.coroutine import AnyCoroutine, Coroutine, RaisingCoroutine
from builtin.debug_assert import debug_assert
from builtin.dtype import DType
from builtin.equality_comparable import EqualityComparable
from builtin.error import Error
-from builtin.file import open, FileHandle
+from builtin.file import FileHandle, open
from builtin.file_descriptor import FileDescriptor
from builtin.float_literal import FloatLiteral
from builtin.floatable import Floatable, FloatableRaising, float
from builtin.format_int import bin, hex, oct
from builtin.identifiable import Identifiable, StringableIdentifiable
from builtin.int import (
+ Indexer,
Int,
- IntLike,
Intable,
IntableRaising,
- Indexer,
+ IntLike,
index,
int,
)
from builtin.int_literal import IntLiteral
-from builtin.io import print, input
-from builtin.len import Sized, UIntSized, SizedRaising, len
+from builtin.io import input, print
+from builtin.len import Sized, SizedRaising, UIntSized, len
from builtin.math import (
Absable,
+ Powable,
+ Roundable,
abs,
divmod,
max,
min,
- Powable,
pow,
- Roundable,
round,
)
from builtin.none import NoneType
@@ -66,72 +81,60 @@ from builtin.range import range, iter, next
from builtin.rebind import rebind
from builtin.repr import Representable, repr
from builtin.reversed import ReversibleRange, reversed
-from builtin.sort import sort, partition
+from builtin.simd import (
+ SIMD,
+ BFloat16,
+ Byte,
+ Float8e5m2,
+ Float8e5m2fnuz,
+ Float8e4m3,
+ Float8e4m3fnuz,
+ Float16,
+ Float32,
+ Float64,
+ Int8,
+ Int16,
+ Int32,
+ Int64,
+ Scalar,
+ UInt8,
+ UInt16,
+ UInt32,
+ UInt64,
+)
+from builtin.sort import partition, sort
from builtin.str import Stringable, StringableRaising, str
from builtin.string_literal import StringLiteral
from builtin.swap import swap
-from builtin.tuple import (
- Tuple,
-)
+from builtin.tuple import Tuple
from builtin.type_aliases import (
AnyTrivialRegType,
- ImmutableOrigin,
- MutableOrigin,
ImmutableAnyOrigin,
+ ImmutableOrigin,
MutableAnyOrigin,
- StaticConstantOrigin,
- OriginSet,
+ MutableOrigin,
Origin,
+ OriginSet,
+ StaticConstantOrigin,
)
from builtin.uint import UInt
from builtin.value import (
- Movable,
- Copyable,
- ExplicitlyCopyable,
- Defaultable,
+ BoolableCollectionElement,
+ BoolableKeyElement,
+ BytesCollectionElement,
CollectionElement,
CollectionElementNew,
- BytesCollectionElement,
- StringableCollectionElement,
- EqualityComparableCollectionElement,
ComparableCollectionElement,
+ Copyable,
+ Defaultable,
+ EqualityComparableCollectionElement,
+ ExplicitlyCopyable,
+ Movable,
RepresentableCollectionElement,
- BoolableKeyElement,
- BoolableCollectionElement,
-)
-from builtin.simd import (
- Scalar,
- Int8,
- UInt8,
- Int16,
- UInt16,
- Int32,
- UInt32,
- Int64,
- UInt64,
- BFloat16,
- Float16,
- Float32,
- Float64,
- Byte,
- SIMD,
-)
-from builtin.type_aliases import AnyTrivialRegType
-
-from collections import KeyElement, List
-from collections.string import (
- String,
- ord,
- chr,
- ascii,
- atol,
- atof,
- isdigit,
- isupper,
- islower,
- isprintable,
+ StringableCollectionElement,
)
-from hashlib.hash import hash, Hashable
-from memory import Pointer, AddressSpace
-from utils import AsBytes, Writable, Writer
from documentation import doc_private
+from memory import AddressSpace, Pointer
+
+from memory.span import AsBytes
+from utils import Writable, Writer
diff --git a/stdlib/src/pwd/__init__.mojo b/stdlib/src/pwd/__init__.mojo
index a62388303c..088bffae14 100644
--- a/stdlib/src/pwd/__init__.mojo
+++ b/stdlib/src/pwd/__init__.mojo
@@ -12,4 +12,4 @@
# ===----------------------------------------------------------------------=== #
"""Implements the pwd package."""
-from .pwd import getpwuid, getpwnam
+from .pwd import getpwnam, getpwuid
diff --git a/stdlib/src/pwd/_linux.mojo b/stdlib/src/pwd/_linux.mojo
index d2ed4175a7..2c485aa5e7 100644
--- a/stdlib/src/pwd/_linux.mojo
+++ b/stdlib/src/pwd/_linux.mojo
@@ -10,10 +10,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# ===----------------------------------------------------------------------=== #
-from .pwd import Passwd
-from memory import UnsafePointer
from sys.ffi import c_char, external_call
+from memory import UnsafePointer
+
+from .pwd import Passwd
+
alias uid_t = Int32
alias gid_t = Int32
alias char = UnsafePointer[c_char]
diff --git a/stdlib/src/pwd/_macos.mojo b/stdlib/src/pwd/_macos.mojo
index 9908504d97..5958ab1a58 100644
--- a/stdlib/src/pwd/_macos.mojo
+++ b/stdlib/src/pwd/_macos.mojo
@@ -10,10 +10,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# ===----------------------------------------------------------------------=== #
-from .pwd import Passwd
-from memory import UnsafePointer
from sys.ffi import c_char, external_call
+from memory import UnsafePointer
+
+from .pwd import Passwd
+
alias uid_t = Int32
alias gid_t = Int32
alias time_t = Int
diff --git a/stdlib/src/pwd/pwd.mojo b/stdlib/src/pwd/pwd.mojo
index 0bc26698d1..105b26e7f2 100644
--- a/stdlib/src/pwd/pwd.mojo
+++ b/stdlib/src/pwd/pwd.mojo
@@ -11,12 +11,13 @@
# limitations under the License.
# ===----------------------------------------------------------------------=== #
+from sys import os_is_linux, os_is_macos, os_is_windows
+
# ===----------------------------------------------------------------------=== #
# Passwd
# ===----------------------------------------------------------------------=== #
from ._linux import _getpw_linux
from ._macos import _getpw_macos
-from sys import os_is_windows, os_is_macos, os_is_linux
@value
@@ -39,7 +40,7 @@ struct Passwd(Stringable):
var pw_shell: String
"""Shell program."""
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""Formats this string to the provided Writer.
Parameters:
diff --git a/stdlib/src/python/__init__.mojo b/stdlib/src/python/__init__.mojo
index c91813320c..f8d0d9d73c 100644
--- a/stdlib/src/python/__init__.mojo
+++ b/stdlib/src/python/__init__.mojo
@@ -12,5 +12,5 @@
# ===----------------------------------------------------------------------=== #
"""Implements the python package."""
-from .python_object import PythonObject, TypedPythonObject
from .python import Python
+from .python_object import PythonObject, TypedPythonObject
diff --git a/stdlib/src/python/_bindings.mojo b/stdlib/src/python/_bindings.mojo
index 4046ca5f50..f5e14cd329 100644
--- a/stdlib/src/python/_bindings.mojo
+++ b/stdlib/src/python/_bindings.mojo
@@ -11,38 +11,35 @@
# limitations under the License.
# ===----------------------------------------------------------------------=== #
-from memory import UnsafePointer
-
+from collections import Optional
+from os import abort
from sys.ffi import c_int
from sys.info import sizeof
-from os import abort
-
-from collections import Optional
-
+from memory import UnsafePointer
from python import PythonObject, TypedPythonObject
-from python.python import _get_global_python_itf
from python._cpython import (
+ Py_TPFLAGS_DEFAULT,
+ PyCFunction,
+ PyMethodDef,
PyObject,
PyObjectPtr,
- PyCFunction,
- PyType_Spec,
PyType_Slot,
- PyMethodDef,
- Py_TPFLAGS_DEFAULT,
- newfunc,
+ PyType_Spec,
destructor,
+ newfunc,
)
+from python.python import _get_global_python_itf
trait ConvertibleFromPython(CollectionElement):
- """Denotes a type that can attempt construction from a borrowed Python
+ """Denotes a type that can attempt construction from a read-only Python
object.
"""
@staticmethod
fn try_from_python(obj: PythonObject) raises -> Self:
- """Attempt to construct an instance of this object from a borrowed
+ """Attempt to construct an instance of this object from a read-only
Python value.
Args:
@@ -116,7 +113,7 @@ fn python_type_object[
basicsize: sizeof[PyMojoObject[T]](),
itemsize: 0,
flags: Py_TPFLAGS_DEFAULT,
- # Note: This pointer is only "borrowed" by PyType_FromSpec.
+ # Note: This pointer is only "read-only" by PyType_FromSpec.
slots: slots.unsafe_ptr(),
}
@@ -141,7 +138,7 @@ fn python_type_object[
#
# The latter is the C function signature that the CPython API expects a
# PyObject initializer function to have. The former is an unsafe form of the
-# `fn(inout self)` signature that Mojo types with default constructors provide.
+# `fn(mut self)` signature that Mojo types with default constructors provide.
#
# To support CPython calling a Mojo types default constructor, we need to
# provide a wrapper function (around the Mojo constructor) that has the
@@ -224,22 +221,22 @@ fn py_c_function_wrapper[
# > When a C function is called from Python, it borrows references to its
# > arguments from the caller. The caller owns a reference to the object,
- # > so the borrowed reference’s lifetime is guaranteed until the function
- # > returns. Only when such a borrowed reference must be stored or passed
+ # > so the read-only reference’s lifetime is guaranteed until the function
+ # > returns. Only when such a read-only reference must be stored or passed
# > on, it must be turned into an owned reference by calling Py_INCREF().
# >
# > -- https://docs.python.org/3/extending/extending.html#ownership-rules
# SAFETY:
# Here we illegally (but carefully) construct _owned_ `PythonObject`
- # values from the borrowed object reference arguments. We are careful
+ # values from the read-only object reference arguments. We are careful
# down below to prevent the destructor for these objects from running
# so that we do not illegally decrement the reference count of these
# objects we do not own.
#
- # This is valid to do, because these are passed using the `borrowed`
+ # This is valid to do, because these are passed using the `read-only`
# argument convention to `user_func`, so logically they are treated
- # as Python borrowed references.
+ # as Python read-only references.
var py_self = PythonObject(py_self_ptr)
var args = TypedPythonObject["Tuple"](
unsafe_unchecked_from=PythonObject(args_ptr)
diff --git a/stdlib/src/python/_cpython.mojo b/stdlib/src/python/_cpython.mojo
index ef437a3d06..05426aa8eb 100644
--- a/stdlib/src/python/_cpython.mojo
+++ b/stdlib/src/python/_cpython.mojo
@@ -18,7 +18,7 @@ Documentation for these functions can be found online at:
"""
from collections import InlineArray, Optional
-from os import getenv, setenv, abort
+from os import abort, getenv, setenv
from os.path import dirname
from pathlib import Path
from sys import external_call
@@ -34,14 +34,12 @@ from sys.ffi import (
c_uint,
)
-from python.python import _get_global_python_itf
-from python._bindings import Typed_initproc, PyMojoObject, Pythonable
-
from memory import UnsafePointer
+from python._bindings import PyMojoObject, Pythonable, Typed_initproc
+from python.python import _get_global_python_itf
from utils import StringRef, StringSlice
-
# ===-----------------------------------------------------------------------===#
# Raw Bindings
# ===-----------------------------------------------------------------------===#
@@ -494,7 +492,7 @@ struct PyObject(Stringable, Representable, Writable):
# Methods
# ===-------------------------------------------------------------------===#
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""Formats to the provided Writer.
Parameters:
@@ -582,7 +580,7 @@ struct PyModuleDef_Base(Stringable, Representable, Writable):
# Methods
# ===-------------------------------------------------------------------===#
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""Formats to the provided Writer.
Parameters:
@@ -702,7 +700,7 @@ struct PyModuleDef(Stringable, Representable, Writable):
# Methods
# ===-------------------------------------------------------------------===#
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""Formats to the provided Writer.
Parameters:
@@ -799,7 +797,7 @@ struct CPython:
pass
@staticmethod
- fn destroy(inout existing: CPython):
+ fn destroy(mut existing: CPython):
if existing.logging_enabled:
print("CPython destroy")
var remaining_refs = existing.total_ref_count.take_pointee()
@@ -863,15 +861,15 @@ struct CPython:
# Reference count management
# ===-------------------------------------------------------------------===#
- fn _inc_total_rc(inout self):
+ fn _inc_total_rc(mut self):
var v = self.total_ref_count.take_pointee()
self.total_ref_count.init_pointee_move(v + 1)
- fn _dec_total_rc(inout self):
+ fn _dec_total_rc(mut self):
var v = self.total_ref_count.take_pointee()
self.total_ref_count.init_pointee_move(v - 1)
- fn Py_IncRef(inout self, ptr: PyObjectPtr):
+ fn Py_IncRef(mut self, ptr: PyObjectPtr):
"""[Reference](
https://docs.python.org/3/c-api/refcounting.html#c.Py_IncRef).
"""
@@ -881,7 +879,7 @@ struct CPython:
self.lib.call["Py_IncRef"](ptr)
self._inc_total_rc()
- fn Py_DecRef(inout self, ptr: PyObjectPtr):
+ fn Py_DecRef(mut self, ptr: PyObjectPtr):
"""[Reference](
https://docs.python.org/3/c-api/refcounting.html#c.Py_DecRef).
"""
@@ -895,7 +893,7 @@ struct CPython:
# have to always be the case - but often it is and it's convenient for
# debugging. We shouldn't rely on this function anywhere - its only purpose
# is debugging.
- fn _Py_REFCNT(inout self, ptr: PyObjectPtr) -> Int:
+ fn _Py_REFCNT(mut self, ptr: PyObjectPtr) -> Int:
if ptr._get_ptr_as_int() == 0:
return -1
# NOTE:
@@ -917,19 +915,19 @@ struct CPython:
# Python GIL and threading
# ===-------------------------------------------------------------------===#
- fn PyGILState_Ensure(inout self) -> PyGILState_STATE:
+ fn PyGILState_Ensure(mut self) -> PyGILState_STATE:
"""[Reference](
https://docs.python.org/3/c-api/init.html#c.PyGILState_Ensure).
"""
return self.lib.call["PyGILState_Ensure", PyGILState_STATE]()
- fn PyGILState_Release(inout self, state: PyGILState_STATE):
+ fn PyGILState_Release(mut self, state: PyGILState_STATE):
"""[Reference](
https://docs.python.org/3/c-api/init.html#c.PyGILState_Release).
"""
self.lib.call["PyGILState_Release"](state)
- fn PyEval_SaveThread(inout self) -> UnsafePointer[PyThreadState]:
+ fn PyEval_SaveThread(mut self) -> UnsafePointer[PyThreadState]:
"""[Reference](
https://docs.python.org/3/c-api/init.html#c.PyEval_SaveThread).
"""
@@ -938,7 +936,7 @@ struct CPython:
"PyEval_SaveThread", UnsafePointer[PyThreadState]
]()
- fn PyEval_RestoreThread(inout self, state: UnsafePointer[PyThreadState]):
+ fn PyEval_RestoreThread(mut self, state: UnsafePointer[PyThreadState]):
"""[Reference](
https://docs.python.org/3/c-api/init.html#c.PyEval_RestoreThread).
"""
@@ -948,7 +946,7 @@ struct CPython:
# Python Dict operations
# ===-------------------------------------------------------------------===#
- fn PyDict_New(inout self) -> PyObjectPtr:
+ fn PyDict_New(mut self) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/dict.html#c.PyDict_New).
"""
@@ -966,7 +964,7 @@ struct CPython:
# int PyDict_SetItem(PyObject *p, PyObject *key, PyObject *val)
fn PyDict_SetItem(
- inout self, dict_obj: PyObjectPtr, key: PyObjectPtr, value: PyObjectPtr
+ mut self, dict_obj: PyObjectPtr, key: PyObjectPtr, value: PyObjectPtr
) -> c_int:
"""[Reference](
https://docs.python.org/3/c-api/dict.html#c.PyDict_SetItem).
@@ -984,7 +982,7 @@ struct CPython:
return r
fn PyDict_GetItemWithError(
- inout self, dict_obj: PyObjectPtr, key: PyObjectPtr
+ mut self, dict_obj: PyObjectPtr, key: PyObjectPtr
) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/dict.html#c.PyDict_GetItemWithError).
@@ -996,7 +994,7 @@ struct CPython:
self.log("PyDict_GetItemWithError, key: ", key._get_ptr_as_int())
return r
- fn PyDict_Check(inout self, maybe_dict: PyObjectPtr) -> Bool:
+ fn PyDict_Check(mut self, maybe_dict: PyObjectPtr) -> Bool:
"""[Reference](
https://docs.python.org/3/c-api/dict.html#c.PyDict_Check).
"""
@@ -1008,7 +1006,7 @@ struct CPython:
self.Py_DecRef(my_type)
return result
- fn PyDict_Type(inout self) -> PyObjectPtr:
+ fn PyDict_Type(mut self) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/dict.html#c.PyDict_Type).
"""
@@ -1018,7 +1016,7 @@ struct CPython:
# int PyDict_Next(PyObject *p, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue)
fn PyDict_Next(
- inout self, dictionary: PyObjectPtr, p: Int
+ mut self, dictionary: PyObjectPtr, p: Int
) -> PyKeysValuePair:
"""[Reference](
https://docs.python.org/3/c-api/dict.html#c.PyDict_Next).
@@ -1063,7 +1061,7 @@ struct CPython:
# ===-------------------------------------------------------------------===#
fn PyImport_ImportModule(
- inout self,
+ mut self,
name: StringRef,
) -> PyObjectPtr:
"""[Reference](
@@ -1083,7 +1081,7 @@ struct CPython:
self._inc_total_rc()
return r
- fn PyImport_AddModule(inout self, name: StringRef) -> PyObjectPtr:
+ fn PyImport_AddModule(mut self, name: StringRef) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/import.html#c.PyImport_AddModule).
"""
@@ -1092,7 +1090,7 @@ struct CPython:
)
fn PyModule_Create(
- inout self,
+ mut self,
name: String,
) -> PyObjectPtr:
"""[Reference](
@@ -1120,7 +1118,7 @@ struct CPython:
)
fn PyModule_AddFunctions(
- inout self,
+ mut self,
mod: PyObjectPtr,
functions: UnsafePointer[PyMethodDef],
) -> c_int:
@@ -1130,7 +1128,7 @@ struct CPython:
return self.lib.call["PyModule_AddFunctions", c_int](mod, functions)
fn PyModule_AddObjectRef(
- inout self,
+ mut self,
module: PyObjectPtr,
name: UnsafePointer[c_char],
value: PyObjectPtr,
@@ -1143,7 +1141,7 @@ struct CPython:
module, name, value
)
- fn PyModule_GetDict(inout self, name: PyObjectPtr) -> PyObjectPtr:
+ fn PyModule_GetDict(mut self, name: PyObjectPtr) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/module.html#c.PyModule_GetDict).
"""
@@ -1153,7 +1151,7 @@ struct CPython:
# Python Type operations
# ===-------------------------------------------------------------------===#
- fn Py_TYPE(inout self, ob_raw: PyObjectPtr) -> UnsafePointer[PyTypeObject]:
+ fn Py_TYPE(mut self, ob_raw: PyObjectPtr) -> UnsafePointer[PyTypeObject]:
"""Get the PyTypeObject field of a Python object."""
# Note:
@@ -1167,12 +1165,12 @@ struct CPython:
return ob_raw.unsized_obj_ptr[].object_type
fn PyType_GetName(
- inout self, type: UnsafePointer[PyTypeObject]
+ mut self, type: UnsafePointer[PyTypeObject]
) -> PyObjectPtr:
return self.lib.call["PyType_GetName", PyObjectPtr](type)
fn PyType_FromSpec(
- inout self, spec: UnsafePointer[PyType_Spec]
+ mut self, spec: UnsafePointer[PyType_Spec]
) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/type.html#c.PyType_FromSpec).
@@ -1180,7 +1178,7 @@ struct CPython:
return self.lib.call["PyType_FromSpec", PyObjectPtr](spec)
fn PyType_GenericAlloc(
- inout self,
+ mut self,
type: UnsafePointer[PyTypeObject],
nitems: Py_ssize_t,
) -> PyObjectPtr:
@@ -1190,7 +1188,7 @@ struct CPython:
# Python Evaluation
# ===-------------------------------------------------------------------===#
- fn PyRun_SimpleString(inout self, strref: StringRef) -> Bool:
+ fn PyRun_SimpleString(mut self, strref: StringRef) -> Bool:
"""Executes the given Python code.
Args:
@@ -1209,7 +1207,7 @@ struct CPython:
)
fn PyRun_String(
- inout self,
+ mut self,
strref: StringRef,
globals: PyObjectPtr,
locals: PyObjectPtr,
@@ -1236,7 +1234,7 @@ struct CPython:
return result
fn PyEval_EvalCode(
- inout self,
+ mut self,
co: PyObjectPtr,
globals: PyObjectPtr,
locals: PyObjectPtr,
@@ -1250,14 +1248,14 @@ struct CPython:
self._inc_total_rc()
return result
- fn PyEval_GetBuiltins(inout self) -> PyObjectPtr:
+ fn PyEval_GetBuiltins(mut self) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/reflection.html#c.PyEval_GetBuiltins).
"""
return self.lib.call["PyEval_GetBuiltins", PyObjectPtr]()
fn Py_CompileString(
- inout self,
+ mut self,
strref: StringRef,
filename: StringRef,
compile_mode: Int,
@@ -1277,7 +1275,7 @@ struct CPython:
# ===-------------------------------------------------------------------===#
fn Py_Is(
- inout self,
+ mut self,
rhs: PyObjectPtr,
lhs: PyObjectPtr,
) -> Bool:
@@ -1291,7 +1289,7 @@ struct CPython:
else:
return rhs == lhs
- fn PyObject_Type(inout self, obj: PyObjectPtr) -> PyObjectPtr:
+ fn PyObject_Type(mut self, obj: PyObjectPtr) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/object.html#c.PyObject_Type).
"""
@@ -1300,7 +1298,7 @@ struct CPython:
self._inc_total_rc()
return p
- fn PyObject_Str(inout self, obj: PyObjectPtr) -> PyObjectPtr:
+ fn PyObject_Str(mut self, obj: PyObjectPtr) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/object.html#c.PyObject_Str).
"""
@@ -1310,7 +1308,7 @@ struct CPython:
return p
fn PyObject_GetItem(
- inout self, obj: PyObjectPtr, key: PyObjectPtr
+ mut self, obj: PyObjectPtr, key: PyObjectPtr
) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/object.html#c.PyObject_GetItem).
@@ -1332,7 +1330,7 @@ struct CPython:
return r
fn PyObject_SetItem(
- inout self, obj: PyObjectPtr, key: PyObjectPtr, value: PyObjectPtr
+ mut self, obj: PyObjectPtr, key: PyObjectPtr, value: PyObjectPtr
) -> c_int:
"""[Reference](
https://docs.python.org/3/c-api/object.html#c.PyObject_SetItem).
@@ -1350,11 +1348,20 @@ struct CPython:
", parent obj:",
obj._get_ptr_as_int(),
)
+ return r
+ fn PyObject_HasAttrString(
+ mut self,
+ obj: PyObjectPtr,
+ name: StringRef,
+ ) -> Int:
+ var r = self.lib.get_function[
+ fn (PyObjectPtr, UnsafePointer[UInt8]) -> Int
+ ]("PyObject_HasAttrString")(obj, name.data)
return r
fn PyObject_GetAttrString(
- inout self,
+ mut self,
obj: PyObjectPtr,
name: StringRef,
) -> PyObjectPtr:
@@ -1380,7 +1387,7 @@ struct CPython:
return r
fn PyObject_SetAttrString(
- inout self, obj: PyObjectPtr, name: StringRef, new_value: PyObjectPtr
+ mut self, obj: PyObjectPtr, name: StringRef, new_value: PyObjectPtr
) -> c_int:
"""[Reference](
https://docs.python.org/3/c-api/object.html#c.PyObject_SetAttrString).
@@ -1404,7 +1411,7 @@ struct CPython:
return r
fn PyObject_CallObject(
- inout self,
+ mut self,
callable_obj: PyObjectPtr,
args: PyObjectPtr,
) -> PyObjectPtr:
@@ -1428,7 +1435,7 @@ struct CPython:
return r
fn PyObject_Call(
- inout self,
+ mut self,
callable_obj: PyObjectPtr,
args: PyObjectPtr,
kwargs: PyObjectPtr,
@@ -1452,26 +1459,26 @@ struct CPython:
self._inc_total_rc()
return r
- fn PyObject_IsTrue(inout self, obj: PyObjectPtr) -> c_int:
+ fn PyObject_IsTrue(mut self, obj: PyObjectPtr) -> c_int:
"""[Reference](
https://docs.python.org/3/c-api/object.html#c.PyObject_IsTrue).
"""
return self.lib.call["PyObject_IsTrue", c_int](obj)
- fn PyObject_Length(inout self, obj: PyObjectPtr) -> Int:
+ fn PyObject_Length(mut self, obj: PyObjectPtr) -> Int:
"""[Reference](
https://docs.python.org/3/c-api/object.html#c.PyObject_Length).
"""
return int(self.lib.call["PyObject_Length", Int](obj))
- fn PyObject_Hash(inout self, obj: PyObjectPtr) -> Int:
+ fn PyObject_Hash(mut self, obj: PyObjectPtr) -> Int:
"""[Reference](
https://docs.python.org/3/c-api/object.html#c.PyObject_Hash).
"""
return int(self.lib.call["PyObject_Hash", Int](obj))
fn PyObject_GetIter(
- inout self, traversablePyObject: PyObjectPtr
+ mut self, traversablePyObject: PyObjectPtr
) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/object.html#c.PyObject_GetIter).
@@ -1498,7 +1505,7 @@ struct CPython:
# Python Tuple operations
# ===-------------------------------------------------------------------===#
- fn PyTuple_New(inout self, count: Int) -> PyObjectPtr:
+ fn PyTuple_New(mut self, count: Int) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/tuple.html#c.PyTuple_New).
"""
@@ -1517,7 +1524,7 @@ struct CPython:
return r
fn PyTuple_GetItem(
- inout self, tuple: PyObjectPtr, pos: Py_ssize_t
+ mut self, tuple: PyObjectPtr, pos: Py_ssize_t
) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/tuple.html#c.PyTuple_GetItem).
@@ -1525,7 +1532,7 @@ struct CPython:
return self.lib.call["PyTuple_GetItem", PyObjectPtr](tuple, pos)
fn PyTuple_SetItem(
- inout self, tuple_obj: PyObjectPtr, index: Int, element: PyObjectPtr
+ mut self, tuple_obj: PyObjectPtr, index: Int, element: PyObjectPtr
) -> c_int:
"""[Reference](
https://docs.python.org/3/c-api/tuple.html#c.PyTuple_SetItem).
@@ -1542,7 +1549,7 @@ struct CPython:
# Python List operations
# ===-------------------------------------------------------------------===#
- fn PyList_New(inout self, length: Int) -> PyObjectPtr:
+ fn PyList_New(mut self, length: Int) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/list.html#c.PyList_New).
"""
@@ -1561,7 +1568,7 @@ struct CPython:
return r
fn PyList_SetItem(
- inout self, list_obj: PyObjectPtr, index: Int, value: PyObjectPtr
+ mut self, list_obj: PyObjectPtr, index: Int, value: PyObjectPtr
) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/list.html#c.PyList_SetItem).
@@ -1575,7 +1582,7 @@ struct CPython:
)
fn PyList_GetItem(
- inout self, list_obj: PyObjectPtr, index: Int
+ mut self, list_obj: PyObjectPtr, index: Int
) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/list.html#c.PyList_GetItem).
@@ -1587,7 +1594,7 @@ struct CPython:
# ref: https://docs.python.org/3/c-api/concrete.html
# ===-------------------------------------------------------------------===#
- fn Py_None(inout self) -> PyObjectPtr:
+ fn Py_None(mut self) -> PyObjectPtr:
"""Get a None value, of type NoneType. [Reference](
https://docs.python.org/3/c-api/none.html#c.Py_None)."""
@@ -1609,7 +1616,7 @@ struct CPython:
# Boolean Objects
# ===-------------------------------------------------------------------===#
- fn PyBool_FromLong(inout self, value: c_long) -> PyObjectPtr:
+ fn PyBool_FromLong(mut self, value: c_long) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/bool.html#c.PyBool_FromLong).
"""
@@ -1631,7 +1638,7 @@ struct CPython:
# Integer Objects
# ===-------------------------------------------------------------------===#
- fn PyLong_FromSsize_t(inout self, value: c_ssize_t) -> PyObjectPtr:
+ fn PyLong_FromSsize_t(mut self, value: c_ssize_t) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/long.html#c.PyLong_FromSsize_t).
"""
@@ -1649,7 +1656,7 @@ struct CPython:
self._inc_total_rc()
return r
- fn PyLong_FromSize_t(inout self, value: c_size_t) -> PyObjectPtr:
+ fn PyLong_FromSize_t(mut self, value: c_size_t) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/long.html#c.PyLong_FromSize_t).
"""
@@ -1667,7 +1674,7 @@ struct CPython:
self._inc_total_rc()
return r
- fn PyLong_AsSsize_t(inout self, py_object: PyObjectPtr) -> c_ssize_t:
+ fn PyLong_AsSsize_t(mut self, py_object: PyObjectPtr) -> c_ssize_t:
"""[Reference](
https://docs.python.org/3/c-api/long.html#c.PyLong_AsSsize_t).
"""
@@ -1677,7 +1684,7 @@ struct CPython:
# Floating-Point Objects
# ===-------------------------------------------------------------------===#
- fn PyFloat_FromDouble(inout self, value: Float64) -> PyObjectPtr:
+ fn PyFloat_FromDouble(mut self, value: Float64) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/float.html#c.PyFloat_FromDouble).
"""
@@ -1695,7 +1702,7 @@ struct CPython:
self._inc_total_rc()
return r
- fn PyFloat_AsDouble(inout self, py_object: PyObjectPtr) -> Float64:
+ fn PyFloat_AsDouble(mut self, py_object: PyObjectPtr) -> Float64:
"""[Reference](
https://docs.python.org/3/c-api/float.html#c.PyFloat_AsDouble).
"""
@@ -1705,7 +1712,7 @@ struct CPython:
# Unicode Objects
# ===-------------------------------------------------------------------===#
- fn PyUnicode_DecodeUTF8(inout self, strref: StringRef) -> PyObjectPtr:
+ fn PyUnicode_DecodeUTF8(mut self, strref: StringRef) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/unicode.html#c.PyUnicode_DecodeUTF8).
"""
@@ -1727,7 +1734,7 @@ struct CPython:
self._inc_total_rc()
return r
- fn PyUnicode_DecodeUTF8(inout self, strslice: StringSlice) -> PyObjectPtr:
+ fn PyUnicode_DecodeUTF8(mut self, strslice: StringSlice) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/unicode.html#c.PyUnicode_DecodeUTF8).
"""
@@ -1748,7 +1755,7 @@ struct CPython:
self._inc_total_rc()
return r
- fn PySlice_FromSlice(inout self, slice: Slice) -> PyObjectPtr:
+ fn PySlice_FromSlice(mut self, slice: Slice) -> PyObjectPtr:
# Convert Mojo Slice to Python slice parameters
# Note: Deliberately avoid using `span.indices()` here and instead pass
# the Slice parameters directly to Python. Python's C implementation
@@ -1775,7 +1782,7 @@ struct CPython:
return py_slice
- fn PyUnicode_AsUTF8AndSize(inout self, py_object: PyObjectPtr) -> StringRef:
+ fn PyUnicode_AsUTF8AndSize(mut self, py_object: PyObjectPtr) -> StringRef:
"""[Reference](
https://docs.python.org/3/c-api/unicode.html#c.PyUnicode_AsUTF8AndSize).
"""
@@ -1790,19 +1797,19 @@ struct CPython:
# Python Error operations
# ===-------------------------------------------------------------------===#
- fn PyErr_Clear(inout self):
+ fn PyErr_Clear(mut self):
"""[Reference](
https://docs.python.org/3/c-api/exceptions.html#c.PyErr_Clear).
"""
self.lib.call["PyErr_Clear"]()
- fn PyErr_Occurred(inout self) -> Bool:
+ fn PyErr_Occurred(mut self) -> Bool:
"""[Reference](
https://docs.python.org/3/c-api/exceptions.html#c.PyErr_Occurred).
"""
return not self.lib.call["PyErr_Occurred", PyObjectPtr]().is_null()
- fn PyErr_Fetch(inout self) -> PyObjectPtr:
+ fn PyErr_Fetch(mut self) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/exceptions.html#c.PyErr_Fetch).
"""
@@ -1829,14 +1836,14 @@ struct CPython:
_ = traceback
return r
- fn PyErr_SetNone(inout self, type: PyObjectPtr):
+ fn PyErr_SetNone(mut self, type: PyObjectPtr):
"""[Reference](
https://docs.python.org/3/c-api/exceptions.html#c.PyErr_SetNone).
"""
self.lib.call["PyErr_SetNone"](type)
fn PyErr_SetString(
- inout self,
+ mut self,
type: PyObjectPtr,
message: UnsafePointer[c_char],
):
@@ -1850,10 +1857,10 @@ struct CPython:
# ===-------------------------------------------------------------------===#
fn get_error_global(
- inout self,
+ mut self,
global_name: StringLiteral,
) -> PyObjectPtr:
- """Get a Python borrowed reference to the specified global exception
+ """Get a Python read-only reference to the specified global exception
object.
"""
@@ -1874,7 +1881,7 @@ struct CPython:
# Python Iterator operations
# ===-------------------------------------------------------------------===#
- fn PyIter_Next(inout self, iterator: PyObjectPtr) -> PyObjectPtr:
+ fn PyIter_Next(mut self, iterator: PyObjectPtr) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/iter.html#c.PyIter_Next).
"""
@@ -1895,13 +1902,13 @@ struct CPython:
self._inc_total_rc()
return next_obj
- fn PyIter_Check(inout self, obj: PyObjectPtr) -> Bool:
+ fn PyIter_Check(mut self, obj: PyObjectPtr) -> Bool:
"""[Reference](
https://docs.python.org/3/c-api/iter.html#c.PyIter_Check).
"""
return self.lib.call["PyIter_Check", c_int](obj) != 0
- fn PySequence_Check(inout self, obj: PyObjectPtr) -> Bool:
+ fn PySequence_Check(mut self, obj: PyObjectPtr) -> Bool:
"""[Reference](
https://docs.python.org/3/c-api/sequence.html#c.PySequence_Check).
"""
@@ -1912,7 +1919,7 @@ struct CPython:
# ===-------------------------------------------------------------------===#
fn PySlice_New(
- inout self, start: PyObjectPtr, stop: PyObjectPtr, step: PyObjectPtr
+ mut self, start: PyObjectPtr, stop: PyObjectPtr, step: PyObjectPtr
) -> PyObjectPtr:
"""[Reference](
https://docs.python.org/3/c-api/slice.html#c.PySlice_New).
diff --git a/stdlib/src/python/python.mojo b/stdlib/src/python/python.mojo
index 990daaf583..8771e54c6f 100644
--- a/stdlib/src/python/python.mojo
+++ b/stdlib/src/python/python.mojo
@@ -28,14 +28,14 @@ from memory import UnsafePointer
from utils import StringRef
-from .python_object import PythonObject, TypedPythonObject
from ._cpython import (
CPython,
Py_eval_input,
Py_file_input,
- PyMethodDef,
Py_ssize_t,
+ PyMethodDef,
)
+from .python_object import PythonObject, TypedPythonObject
alias _PYTHON_GLOBAL = _Global["Python", _PythonGlobal, _init_python_global]
@@ -47,10 +47,10 @@ fn _init_python_global() -> _PythonGlobal:
struct _PythonGlobal:
var cpython: CPython
- fn __moveinit__(inout self, owned other: Self):
+ fn __moveinit__(mut self, owned other: Self):
self.cpython = other.cpython^
- fn __init__(inout self):
+ fn __init__(mut self):
self.cpython = CPython()
fn __del__(owned self):
@@ -99,7 +99,7 @@ struct Python:
"""
self.impl = existing.impl
- fn eval(inout self, code: StringRef) -> Bool:
+ fn eval(mut self, code: StringRef) -> Bool:
"""Executes the given Python code.
Args:
@@ -127,7 +127,7 @@ struct Python:
`PythonObject` containing the result of the evaluation.
"""
var cpython = _get_global_python_itf().cpython()
- # PyImport_AddModule returns a borrowed reference.
+ # PyImport_AddModule returns a read-only reference.
var module = PythonObject.from_borrowed_ptr(
cpython.PyImport_AddModule(name)
)
@@ -265,7 +265,7 @@ struct Python:
@staticmethod
fn add_functions(
- inout module: TypedPythonObject["Module"],
+ mut module: TypedPythonObject["Module"],
owned functions: List[PyMethodDef],
) raises:
"""Adds functions to a PyModule object.
@@ -287,7 +287,7 @@ struct Python:
@staticmethod
fn unsafe_add_methods(
- inout module: TypedPythonObject["Module"],
+ mut module: TypedPythonObject["Module"],
functions: UnsafePointer[PyMethodDef],
) raises:
"""Adds methods to a PyModule object.
@@ -314,7 +314,7 @@ struct Python:
@staticmethod
fn add_object(
- inout module: TypedPythonObject["Module"],
+ mut module: TypedPythonObject["Module"],
name: StringLiteral,
value: PythonObject,
) raises:
@@ -366,7 +366,7 @@ struct Python:
return PythonObject([])
@no_inline
- fn __str__(inout self, str_obj: PythonObject) -> StringRef:
+ fn __str__(mut self, str_obj: PythonObject) -> StringRef:
"""Return a string representing the given Python object.
Args:
@@ -379,7 +379,7 @@ struct Python:
return cpython.PyUnicode_AsUTF8AndSize(str_obj.py_object)
@staticmethod
- fn throw_python_exception_if_error_state(inout cpython: CPython) raises:
+ fn throw_python_exception_if_error_state(mut cpython: CPython) raises:
"""Raise an exception if CPython interpreter is in an error state.
Args:
@@ -389,7 +389,7 @@ struct Python:
raise Python.unsafe_get_python_exception(cpython)
@staticmethod
- fn unsafe_get_python_exception(inout cpython: CPython) -> Error:
+ fn unsafe_get_python_exception(mut cpython: CPython) -> Error:
"""Get the `Error` object corresponding to the current CPython
interpreter error state.
diff --git a/stdlib/src/python/python_object.mojo b/stdlib/src/python/python_object.mojo
index 151336f510..a6b3a8a45f 100644
--- a/stdlib/src/python/python_object.mojo
+++ b/stdlib/src/python/python_object.mojo
@@ -19,17 +19,17 @@ from python import PythonObject
```
"""
+from collections import Dict
+from hashlib._hasher import _HashableWithHasher, _Hasher
+from sys.ffi import c_ssize_t
from sys.intrinsics import _type_is_eq
from memory import UnsafePointer
-from collections import Dict
-from utils import StringRef
-from hashlib._hasher import _HashableWithHasher, _Hasher
+from utils import StringRef
from ._cpython import CPython, PyObjectPtr
from .python import Python, _get_global_python_itf
-from sys.ffi import c_ssize_t
struct _PyIter(Sized):
@@ -87,7 +87,7 @@ struct _PyIter(Sized):
# Trait implementations
# ===-------------------------------------------------------------------===#
- fn __next__(inout self: _PyIter) -> PythonObject:
+ fn __next__(mut self: _PyIter) -> PythonObject:
"""Return the next item and update to point to subsequent item.
Returns:
@@ -222,7 +222,7 @@ struct TypedPythonObject[type_hint: StringLiteral](
raise Python.unsafe_get_python_exception(cpython)
# TODO(MSTDL-911): Avoid unnecessary owned reference counts when
- # returning borrowed PythonObject values.
+ # returning read-only PythonObject values.
return PythonObject.from_borrowed_ptr(item)
@@ -276,7 +276,7 @@ struct PythonObject(
@staticmethod
fn from_borrowed_ptr(borrowed_ptr: PyObjectPtr) -> Self:
- """Initialize this object from a borrowed reference-counted Python
+ """Initialize this object from a read-only reference-counted Python
object pointer.
The reference count of the pointee object will be incremented, and
@@ -294,7 +294,7 @@ struct PythonObject(
pointer returned by 'Borrowed reference'-type objects.
Args:
- borrowed_ptr: A borrowed reference counted pointer to a Python
+ borrowed_ptr: A read-only reference counted pointer to a Python
object.
Returns:
@@ -303,7 +303,7 @@ struct PythonObject(
var cpython = _get_global_python_itf().cpython()
# SAFETY:
- # We were passed a Python 'borrowed reference', so for it to be
+ # We were passed a Python 'read-only reference', so for it to be
# safe to store this reference, we must increment the reference
# count to convert this to a 'strong reference'.
cpython.Py_IncRef(borrowed_ptr)
@@ -374,7 +374,7 @@ struct PythonObject(
self.py_object = cpython.PyLong_FromSsize_t(integer)
@implicit
- fn __init__[dt: DType](inout self, value: SIMD[dt, 1]):
+ fn __init__[dt: DType](mut self, value: SIMD[dt, 1]):
"""Initialize the object with a generic scalar value. If the scalar
value type is bool, it is converted to a boolean. Otherwise, it is
converted to the appropriate integer or floating point type.
@@ -427,7 +427,7 @@ struct PythonObject(
self.py_object = cpython.PyUnicode_DecodeUTF8(string.as_string_slice())
@implicit
- fn __init__[*Ts: CollectionElement](inout self, value: ListLiteral[*Ts]):
+ fn __init__[*Ts: CollectionElement](mut self, value: ListLiteral[*Ts]):
"""Initialize the object from a list literal.
Parameters:
@@ -470,7 +470,7 @@ struct PythonObject(
_ = cpython.PyList_SetItem(self.py_object, i, obj.py_object)
@implicit
- fn __init__[*Ts: CollectionElement](inout self, value: Tuple[*Ts]):
+ fn __init__[*Ts: CollectionElement](mut self, value: Tuple[*Ts]):
"""Initialize the object from a tuple literal.
Parameters:
@@ -715,7 +715,7 @@ struct PythonObject(
Python.throw_python_exception_if_error_state(cpython)
return PythonObject(result)
- fn __setitem__(inout self, *args: PythonObject, value: PythonObject) raises:
+ fn __setitem__(mut self, *args: PythonObject, value: PythonObject) raises:
"""Set the value with the given key or keys.
Args:
@@ -782,7 +782,7 @@ struct PythonObject(
return PythonObject(result_obj)
fn _call_single_arg_inplace_method(
- inout self, method_name: StringRef, rhs: PythonObject
+ mut self, method_name: StringRef, rhs: PythonObject
) raises:
var cpython = _get_global_python_itf().cpython()
var tuple_obj = cpython.PyTuple_New(1)
@@ -831,7 +831,7 @@ struct PythonObject(
"""
return self._call_single_arg_method("__rmul__", lhs)
- fn __imul__(inout self, rhs: PythonObject) raises:
+ fn __imul__(mut self, rhs: PythonObject) raises:
"""In-place multiplication.
Calls the underlying object's `__imul__` method.
@@ -868,7 +868,7 @@ struct PythonObject(
"""
return self._call_single_arg_method("__radd__", lhs)
- fn __iadd__(inout self, rhs: PythonObject) raises:
+ fn __iadd__(mut self, rhs: PythonObject) raises:
"""Immediate addition and concatenation.
Args:
@@ -902,7 +902,7 @@ struct PythonObject(
"""
return self._call_single_arg_method("__rsub__", lhs)
- fn __isub__(inout self, rhs: PythonObject) raises:
+ fn __isub__(mut self, rhs: PythonObject) raises:
"""Immediate subtraction.
Args:
@@ -939,7 +939,7 @@ struct PythonObject(
"""
return self._call_single_arg_method("__rfloordiv__", lhs)
- fn __ifloordiv__(inout self, rhs: PythonObject) raises:
+ fn __ifloordiv__(mut self, rhs: PythonObject) raises:
"""Immediate floor division.
Args:
@@ -973,7 +973,7 @@ struct PythonObject(
"""
return self._call_single_arg_method("__rtruediv__", lhs)
- fn __itruediv__(inout self, rhs: PythonObject) raises:
+ fn __itruediv__(mut self, rhs: PythonObject) raises:
"""Immediate division.
Args:
@@ -1007,7 +1007,7 @@ struct PythonObject(
"""
return self._call_single_arg_method("__rmod__", lhs)
- fn __imod__(inout self, rhs: PythonObject) raises:
+ fn __imod__(mut self, rhs: PythonObject) raises:
"""Immediate modulo.
Args:
@@ -1039,7 +1039,7 @@ struct PythonObject(
"""
return self._call_single_arg_method("__rxor__", lhs)
- fn __ixor__(inout self, rhs: PythonObject) raises:
+ fn __ixor__(mut self, rhs: PythonObject) raises:
"""Immediate exclusive OR.
Args:
@@ -1072,7 +1072,7 @@ struct PythonObject(
"""
return self._call_single_arg_method("__ror__", lhs)
- fn __ior__(inout self, rhs: PythonObject) raises:
+ fn __ior__(mut self, rhs: PythonObject) raises:
"""Immediate bitwise OR.
Args:
@@ -1105,7 +1105,7 @@ struct PythonObject(
"""
return self._call_single_arg_method("__rand__", lhs)
- fn __iand__(inout self, rhs: PythonObject) raises:
+ fn __iand__(mut self, rhs: PythonObject) raises:
"""Immediate bitwise AND.
Args:
@@ -1138,7 +1138,7 @@ struct PythonObject(
"""
return self._call_single_arg_method("__rrshift__", lhs)
- fn __irshift__(inout self, rhs: PythonObject) raises:
+ fn __irshift__(mut self, rhs: PythonObject) raises:
"""Immediate bitwise right shift.
Args:
@@ -1171,7 +1171,7 @@ struct PythonObject(
"""
return self._call_single_arg_method("__rlshift__", lhs)
- fn __ilshift__(inout self, rhs: PythonObject) raises:
+ fn __ilshift__(mut self, rhs: PythonObject) raises:
"""Immediate bitwise left shift.
Args:
@@ -1202,7 +1202,7 @@ struct PythonObject(
"""
return self._call_single_arg_method("__rpow__", lhs)
- fn __ipow__(inout self, rhs: PythonObject) raises:
+ fn __ipow__(mut self, rhs: PythonObject) raises:
"""Immediate power of.
Args:
@@ -1325,6 +1325,27 @@ struct PythonObject(
"""
return self._call_zero_arg_method("__invert__")
+ fn __contains__(self, rhs: PythonObject) raises -> Bool:
+ """Contains dunder.
+
+ Calls the underlying object's `__contains__` method.
+
+ Args:
+ rhs: Right hand value.
+
+ Returns:
+ True if rhs is in self.
+ """
+ # TODO: replace/optimize with c-python function.
+ # TODO: implement __getitem__ step for cpython membership test operator.
+ var cpython = _get_global_python_itf().cpython()
+ if cpython.PyObject_HasAttrString(self.py_object, "__contains__"):
+ return self._call_single_arg_method("__contains__", rhs).__bool__()
+ for v in self:
+ if v == rhs:
+ return True
+ return False
+
# see https://github.com/python/cpython/blob/main/Objects/call.c
# for decrement rules
fn __call__(
@@ -1412,7 +1433,7 @@ struct PythonObject(
debug_assert(result != -1, "object is not hashable")
return result
- fn __hash__[H: _Hasher](self, inout hasher: H):
+ fn __hash__[H: _Hasher](self, mut hasher: H):
"""Updates hasher with this python object hash value.
Parameters:
@@ -1480,7 +1501,7 @@ struct PythonObject(
_ = python_str
return mojo_str
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""
Formats this Python object to the provided Writer.
diff --git a/stdlib/src/random/__init__.mojo b/stdlib/src/random/__init__.mojo
index d71e458454..231b4a115f 100644
--- a/stdlib/src/random/__init__.mojo
+++ b/stdlib/src/random/__init__.mojo
@@ -21,4 +21,5 @@ from .random import (
random_si64,
random_ui64,
seed,
+ shuffle,
)
diff --git a/stdlib/src/random/random.mojo b/stdlib/src/random/random.mojo
index 840e353f7a..8ac75d5a8f 100644
--- a/stdlib/src/random/random.mojo
+++ b/stdlib/src/random/random.mojo
@@ -19,14 +19,14 @@ from random import seed
```
"""
+import math
+from collections import List, Optional
+from math import floor
from sys import bitwidthof, external_call
from sys.ffi import OpaquePointer
from time import perf_counter_ns
-from collections import Optional
from memory import UnsafePointer
-from math import floor
-import math
fn _get_random_state() -> OpaquePointer:
@@ -122,7 +122,7 @@ fn randint[
fn rand[
type: DType
](
- ptr: UnsafePointer[Scalar[type], *_],
+ ptr: UnsafePointer[Scalar[type], **_],
size: Int,
/,
*,
@@ -222,3 +222,19 @@ fn randn[
for i in range(size):
ptr[i] = randn_float64(mean, variance).cast[type]()
return
+
+
+fn shuffle[T: CollectionElement, //](mut list: List[T]):
+ """Shuffles the elements of the list randomly.
+
+ Performs an in-place Fisher-Yates shuffle on the provided list.
+
+ Args:
+ list: The list to modify.
+
+ Parameters:
+ T: The type of element in the List.
+ """
+ for i in reversed(range(len(list))):
+ var j = int(random_ui64(0, i))
+ list.swap_elements(i, j)
diff --git a/stdlib/src/sys/__init__.mojo b/stdlib/src/sys/__init__.mojo
index 632dde283e..b0777f5c6e 100644
--- a/stdlib/src/sys/__init__.mojo
+++ b/stdlib/src/sys/__init__.mojo
@@ -19,6 +19,8 @@ from .ffi import DEFAULT_RTLD, RTLD, DLHandle, external_call
from .info import (
alignof,
bitwidthof,
+ has_accelerator,
+ has_amd_gpu_accelerator,
has_avx,
has_avx2,
has_avx512f,
@@ -27,15 +29,19 @@ from .info import (
has_neon,
has_neon_int8_dotprod,
has_neon_int8_matmul,
+ has_nvidia_gpu_accelerator,
has_sse4,
has_vnni,
+ is_amd_gpu,
is_apple_m1,
is_apple_m2,
is_apple_m3,
is_apple_silicon,
is_big_endian,
+ is_gpu,
is_little_endian,
is_neoverse_n1,
+ is_nvidia_gpu,
is_x86,
num_logical_cores,
num_performance_cores,
@@ -47,9 +53,6 @@ from .info import (
simdbytewidth,
simdwidthof,
sizeof,
- is_nvidia_gpu,
- is_amd_gpu,
- is_gpu,
)
from .intrinsics import (
PrefetchCache,
@@ -67,5 +70,5 @@ from .intrinsics import (
strided_load,
strided_store,
)
-from .param_env import env_get_int, env_get_string, env_get_bool, is_defined
+from .param_env import env_get_bool, env_get_int, env_get_string, is_defined
from .terminate import exit
diff --git a/stdlib/src/sys/_assembly.mojo b/stdlib/src/sys/_assembly.mojo
index 6cb2123393..2074afde29 100644
--- a/stdlib/src/sys/_assembly.mojo
+++ b/stdlib/src/sys/_assembly.mojo
@@ -14,9 +14,9 @@
from sys.intrinsics import _mlirtype_is_eq
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# 0-arg
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
diff --git a/stdlib/src/sys/_libc.mojo b/stdlib/src/sys/_libc.mojo
index a76a1e47d1..ca0104d19c 100644
--- a/stdlib/src/sys/_libc.mojo
+++ b/stdlib/src/sys/_libc.mojo
@@ -17,14 +17,14 @@ C standard library counterparts. These are used to implement higher level
functionality in the rest of the Mojo standard library.
"""
-from memory import UnsafePointer
from sys import os_is_windows
-from sys.ffi import c_char, c_int, OpaquePointer
+from sys.ffi import OpaquePointer, c_char, c_int
+from memory import UnsafePointer
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# stdlib.h — core C standard library operations
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -37,9 +37,9 @@ fn exit(status: c_int):
external_call["exit", NoneType](status)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# stdio.h — input/output operations
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
alias FILE_ptr = OpaquePointer
@@ -74,9 +74,9 @@ fn pclose(stream: FILE_ptr) -> c_int:
return external_call["pclose", c_int](stream)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# unistd.h
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -86,9 +86,9 @@ fn dup(oldfd: c_int) -> c_int:
return external_call[name, c_int](oldfd)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# dlfcn.h — dynamic library operations
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
diff --git a/stdlib/src/sys/ffi.mojo b/stdlib/src/sys/ffi.mojo
index cdfbcfb18f..2d6926568d 100644
--- a/stdlib/src/sys/ffi.mojo
+++ b/stdlib/src/sys/ffi.mojo
@@ -13,15 +13,15 @@
"""Implements a foreign functions interface (FFI)."""
from os import abort
+from sys._libc import dlclose, dlerror, dlopen, dlsym
+
from memory import UnsafePointer
from utils import StringRef
-from .info import os_is_linux, os_is_windows, is_64bit, os_is_macos
+from .info import is_64bit, os_is_linux, os_is_macos, os_is_windows
from .intrinsics import _mlirtype_is_eq
-from sys._libc import dlerror, dlopen, dlclose, dlsym
-
# ===-----------------------------------------------------------------------===#
# Primitive C type aliases
# ===-----------------------------------------------------------------------===#
@@ -176,7 +176,7 @@ struct DLHandle(CollectionElement, CollectionElementNew, Boolable):
# TODO(#15590): Implement support for windows and remove the always_inline.
@always_inline
- fn close(inout self):
+ fn close(mut self):
"""Delete the DLHandle object unloading the associated dynamic library.
"""
@@ -404,9 +404,9 @@ fn _get_dylib_function[
return new_func
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Globals
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
struct _Global[
@@ -462,9 +462,9 @@ fn _get_global_or_null[name: StringLiteral]() -> OpaquePointer:
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# external_call
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
@@ -502,9 +502,9 @@ fn external_call[
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# _external_call_const
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
diff --git a/stdlib/src/sys/info.mojo b/stdlib/src/sys/info.mojo
index 9930fe79a0..ee149ca72a 100644
--- a/stdlib/src/sys/info.mojo
+++ b/stdlib/src/sys/info.mojo
@@ -19,9 +19,10 @@ from sys import is_x86
```
"""
-from .ffi import _external_call_const, external_call, OpaquePointer
from memory import UnsafePointer
+from .ffi import OpaquePointer, _external_call_const, external_call
+
@always_inline("nodebug")
fn _current_target() -> __mlir_type.`!kgen.target`:
@@ -33,15 +34,13 @@ fn _accelerator_arch() -> StringLiteral:
return __mlir_attr.`#kgen.param.expr : !kgen.string`
-fn _get_arch[target: __mlir_type.`!kgen.target`]() -> String:
- return String(
- __mlir_attr[
- `#kgen.param.expr : !kgen.string`,
- ]
- )
+fn _get_arch[target: __mlir_type.`!kgen.target`]() -> StringLiteral:
+ return __mlir_attr[
+ `#kgen.param.expr : !kgen.string`,
+ ]
@always_inline("nodebug")
@@ -863,3 +862,38 @@ fn _macos_version() raises -> Tuple[Int, Int, Int]:
patch = int(osver[: osver.find(".")])
return (major, minor, patch)
+
+
+# ===-----------------------------------------------------------------------===#
+# Detect GPU on host side
+# ===-----------------------------------------------------------------------===#
+
+
+@always_inline("nodebug")
+fn has_accelerator() -> Bool:
+ """Returns True if the host system has an accelerator and False otherwise.
+
+ Returns:
+ True if the host system has an accelerator.
+ """
+ return _accelerator_arch() != ""
+
+
+@always_inline("nodebug")
+fn has_amd_gpu_accelerator() -> Bool:
+ """Returns True if the host system has an AMD GPU and False otherwise.
+
+ Returns:
+ True if the host system has an AMD GPU.
+ """
+ return "amd" in _accelerator_arch()
+
+
+@always_inline("nodebug")
+fn has_nvidia_gpu_accelerator() -> Bool:
+ """Returns True if the host system has an NVIDIA GPU and False otherwise.
+
+ Returns:
+ True if the host system has an NVIDIA GPU.
+ """
+ return "nvidia" in _accelerator_arch()
diff --git a/stdlib/src/sys/intrinsics.mojo b/stdlib/src/sys/intrinsics.mojo
index 38f6ae8e5b..3eb81a505a 100644
--- a/stdlib/src/sys/intrinsics.mojo
+++ b/stdlib/src/sys/intrinsics.mojo
@@ -19,15 +19,16 @@ from sys import PrefetchLocality
```
"""
-from .info import sizeof, is_nvidia_gpu
-from ._assembly import inlined_assembly
import math
from memory import AddressSpace, UnsafePointer
-# ===----------------------------------------------------------------------===#
+from ._assembly import inlined_assembly
+from .info import is_nvidia_gpu, sizeof
+
+# ===-----------------------------------------------------------------------===#
# llvm_intrinsic
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
@@ -89,9 +90,9 @@ fn llvm_intrinsic[
](loaded_pack)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# _gather
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# NOTE: Converting from a scalar to a pointer is unsafe! The resulting pointer
@@ -175,9 +176,9 @@ fn gather[
return result
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# _scatter
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
@@ -253,9 +254,9 @@ fn scatter[
_ = base
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# prefetch
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@register_passable("trivial")
@@ -468,7 +469,7 @@ struct PrefetchOptions:
@always_inline("nodebug")
fn prefetch[
type: DType, //, params: PrefetchOptions = PrefetchOptions()
-](addr: UnsafePointer[Scalar[type], *_]):
+](addr: UnsafePointer[Scalar[type], **_]):
"""Prefetches an instruction or data into cache before it is used.
The prefetch function provides prefetching hints for the target
@@ -499,16 +500,16 @@ fn prefetch[
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# masked load
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
fn masked_load[
type: DType, //, size: Int
](
- addr: UnsafePointer[Scalar[type], *_],
+ addr: UnsafePointer[Scalar[type], **_],
mask: SIMD[DType.bool, size],
passthrough: SIMD[type, size],
alignment: Int = 1,
@@ -545,9 +546,9 @@ fn masked_load[
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# masked store
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
@@ -555,7 +556,7 @@ fn masked_store[
size: Int
](
value: SIMD,
- addr: UnsafePointer[Scalar[value.type], *_],
+ addr: UnsafePointer[Scalar[value.type], **_],
mask: SIMD[DType.bool, size],
alignment: Int = 1,
):
@@ -587,9 +588,9 @@ fn masked_store[
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# compressed store
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
@@ -597,7 +598,7 @@ fn compressed_store[
type: DType, size: Int
](
value: SIMD[type, size],
- addr: UnsafePointer[Scalar[type], *_],
+ addr: UnsafePointer[Scalar[type], **_],
mask: SIMD[DType.bool, size],
):
"""Compresses the lanes of `value`, skipping `mask` lanes, and stores
@@ -627,16 +628,16 @@ fn compressed_store[
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# strided load
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
fn strided_load[
type: DType, //, simd_width: Int
](
- addr: UnsafePointer[Scalar[type], *_],
+ addr: UnsafePointer[Scalar[type], **_],
stride: Int,
mask: SIMD[DType.bool, simd_width] = True,
) -> SIMD[type, simd_width]:
@@ -667,9 +668,9 @@ fn strided_load[
return gather(offset, mask, passthrough)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# strided store
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline("nodebug")
@@ -677,7 +678,7 @@ fn strided_store[
type: DType, //, simd_width: Int
](
value: SIMD[type, simd_width],
- addr: UnsafePointer[Scalar[type], *_],
+ addr: UnsafePointer[Scalar[type], **_],
stride: Int,
mask: SIMD[DType.bool, simd_width] = True,
):
diff --git a/stdlib/src/sys/terminate.mojo b/stdlib/src/sys/terminate.mojo
index 48e5fd8455..69fae08ca4 100644
--- a/stdlib/src/sys/terminate.mojo
+++ b/stdlib/src/sys/terminate.mojo
@@ -13,8 +13,8 @@
"""This module includes the exit functions."""
-from sys.ffi import c_int
from sys import _libc as libc
+from sys.ffi import c_int
fn exit():
diff --git a/stdlib/src/tempfile/tempfile.mojo b/stdlib/src/tempfile/tempfile.mojo
index 7f3c2dd09d..48ccb1ddcd 100644
--- a/stdlib/src/tempfile/tempfile.mojo
+++ b/stdlib/src/tempfile/tempfile.mojo
@@ -21,9 +21,11 @@ from tempfile import gettempdir
import os
import sys
-from collections import Optional, List
+from collections import List, Optional
from pathlib import Path
-from utils import Span, write_buffered
+
+from memory import Span
+from utils import write_buffered
alias TMP_MAX = 10_000
@@ -211,7 +213,7 @@ struct TemporaryDirectory:
"""Whether to ignore cleanup errors."""
fn __init__(
- inout self,
+ mut self,
suffix: String = "",
prefix: String = "tmp",
dir: Optional[String] = None,
@@ -289,7 +291,7 @@ struct NamedTemporaryFile:
"""Name of the file."""
fn __init__(
- inout self,
+ mut self,
mode: String = "w",
name: Optional[String] = None,
suffix: String = "",
@@ -344,7 +346,7 @@ struct NamedTemporaryFile:
except:
pass
- fn close(inout self) raises:
+ fn close(mut self) raises:
"""Closes the file handle."""
self._file_handle.close()
if self._delete:
@@ -402,7 +404,7 @@ struct NamedTemporaryFile:
"""
return self._file_handle.seek(offset, whence)
- fn write[*Ts: Writable](inout self, *args: *Ts):
+ fn write[*Ts: Writable](mut self, *args: *Ts):
"""Write a sequence of Writable arguments to the provided Writer.
Parameters:
@@ -415,7 +417,7 @@ struct NamedTemporaryFile:
write_buffered[buffer_size=4096](file, args)
@always_inline
- fn write_bytes(inout self, bytes: Span[Byte, _]):
+ fn write_bytes(mut self, bytes: Span[Byte, _]):
"""
Write a span of bytes to the file.
diff --git a/stdlib/src/testing/__init__.mojo b/stdlib/src/testing/__init__.mojo
index 23636b5081..79c2180d4d 100644
--- a/stdlib/src/testing/__init__.mojo
+++ b/stdlib/src/testing/__init__.mojo
@@ -17,9 +17,9 @@ from .testing import (
assert_almost_equal,
assert_equal,
assert_false,
+ assert_is,
+ assert_is_not,
assert_not_equal,
assert_raises,
assert_true,
- assert_is,
- assert_is_not,
)
diff --git a/stdlib/src/testing/testing.mojo b/stdlib/src/testing/testing.mojo
index 5dff04c458..20173be736 100644
--- a/stdlib/src/testing/testing.mojo
+++ b/stdlib/src/testing/testing.mojo
@@ -35,7 +35,6 @@ from math import isclose
from builtin._location import __call_location, _SourceLocation
-
# ===----------------------------------------------------------------------=== #
# Assertions
# ===----------------------------------------------------------------------=== #
@@ -537,7 +536,7 @@ struct assert_raises:
@always_inline
fn __init__(
- inout self,
+ mut self,
*,
contains: String,
location: Optional[_SourceLocation] = None,
diff --git a/stdlib/src/time/__init__.mojo b/stdlib/src/time/__init__.mojo
index de8f50f95e..6e5097653a 100644
--- a/stdlib/src/time/__init__.mojo
+++ b/stdlib/src/time/__init__.mojo
@@ -13,10 +13,9 @@
"""Implements the time package."""
from .time import (
- now,
+ monotonic,
perf_counter,
perf_counter_ns,
sleep,
time_function,
- monotonic,
)
diff --git a/stdlib/src/time/time.mojo b/stdlib/src/time/time.mojo
index a8a38b5841..0167c26548 100644
--- a/stdlib/src/time/time.mojo
+++ b/stdlib/src/time/time.mojo
@@ -15,27 +15,28 @@
You can import these APIs from the `time` package. For example:
```mojo
-from time import now
+from time import perf_counter_ns
```
"""
+from math import floor
from os import abort
from sys import (
external_call,
- os_is_linux,
- os_is_windows,
is_amd_gpu,
is_nvidia_gpu,
+ is_gpu,
llvm_intrinsic,
+ os_is_linux,
+ os_is_windows,
)
from sys._assembly import inlined_assembly
-from math import floor
from memory import UnsafePointer
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Utilities
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Enums used in time.h 's glibc
alias _CLOCK_REALTIME = 0
@@ -46,7 +47,7 @@ alias _CLOCK_MONOTONIC_RAW = 4
# Constants
alias _NSEC_PER_USEC = 1000
-alias _NSEC_PER_MSEC = 1000000
+alias _NSEC_PER_MSEC = 1_000_000
alias _USEC_PER_MSEC = 1000
alias _MSEC_PER_SEC = 1000
alias _NSEC_PER_SEC = _NSEC_PER_USEC * _USEC_PER_MSEC * _MSEC_PER_SEC
@@ -68,7 +69,7 @@ struct _CTimeSpec(Stringable):
self.tv_sec = 0
self.tv_subsec = 0
- fn as_nanoseconds(self) -> Int:
+ fn as_nanoseconds(self) -> UInt:
@parameter
if os_is_linux():
return self.tv_sec * _NSEC_PER_SEC + self.tv_subsec
@@ -90,7 +91,7 @@ struct _FILETIME:
self.dwLowDateTime = 0
self.dwHighDateTime = 0
- fn as_nanoseconds(self) -> Int:
+ fn as_nanoseconds(self) -> UInt:
# AFTER subtracting windows offset the return value fits in a signed int64
# BEFORE subtracting windows offset the return value does not fit in a signed int64
# Taken from https://github.com/microsoft/STL/blob/c8d1efb6d504f6392acf8f6d01fd703f7c8826c0/stl/src/xtime.cpp#L50
@@ -115,7 +116,7 @@ fn _clock_gettime(clockid: Int) -> _CTimeSpec:
@always_inline
-fn _gettime_as_nsec_unix(clockid: Int) -> Int:
+fn _gettime_as_nsec_unix(clockid: Int) -> UInt:
if os_is_linux():
var ts = _clock_gettime(clockid)
return ts.as_nanoseconds()
@@ -126,17 +127,26 @@ fn _gettime_as_nsec_unix(clockid: Int) -> Int:
@always_inline
-fn _realtime_nanoseconds() -> Int:
+fn _gpu_clock() -> UInt:
+ """Returns a 64-bit unsigned cycle counter."""
+ alias asm = "llvm.nvvm.read.ptx.sreg.clock64" if is_nvidia_gpu() else "llvm.amdgcn.s.memtime"
+ return int(llvm_intrinsic[asm, Int64]())
+
+
+@always_inline
+fn _realtime_nanoseconds() -> UInt:
"""Returns the current realtime time in nanoseconds"""
return _gettime_as_nsec_unix(_CLOCK_REALTIME)
@always_inline
-fn _monotonic_nanoseconds() -> Int:
+fn _monotonic_nanoseconds() -> UInt:
"""Returns the current monotonic time in nanoseconds"""
@parameter
- if os_is_windows():
+ if is_gpu():
+ return _gpu_clock()
+ elif os_is_windows():
var ft = _FILETIME()
external_call["GetSystemTimePreciseAsFileTime", NoneType](
Pointer.address_of(ft)
@@ -148,29 +158,28 @@ fn _monotonic_nanoseconds() -> Int:
@always_inline
-fn _monotonic_raw_nanoseconds() -> Int:
+fn _monotonic_raw_nanoseconds() -> UInt:
"""Returns the current monotonic time in nanoseconds"""
-
return _gettime_as_nsec_unix(_CLOCK_MONOTONIC_RAW)
@always_inline
-fn _process_cputime_nanoseconds() -> Int:
+fn _process_cputime_nanoseconds() -> UInt:
"""Returns the high-resolution per-process timer from the CPU"""
return _gettime_as_nsec_unix(_CLOCK_PROCESS_CPUTIME_ID)
@always_inline
-fn _thread_cputime_nanoseconds() -> Int:
+fn _thread_cputime_nanoseconds() -> UInt:
"""Returns the thread-specific CPU-time clock"""
return _gettime_as_nsec_unix(_CLOCK_THREAD_CPUTIME_ID)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# perf_counter
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -187,13 +196,13 @@ fn perf_counter() -> Float64:
return Float64(_monotonic_nanoseconds()) / _NSEC_PER_SEC
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# perf_counter_ns
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
-fn perf_counter_ns() -> Int:
+fn perf_counter_ns() -> UInt:
"""Return the value (in nanoseconds) of a performance counter, i.e.
a clock with the highest available resolution to measure a short duration.
It does include time elapsed during sleep and is system-wide. The reference
@@ -203,44 +212,16 @@ fn perf_counter_ns() -> Int:
Returns:
The current time in ns.
"""
-
- @parameter
- if is_nvidia_gpu():
- return int(
- inlined_assembly[
- "mov.u64 $0, %globaltimer;", UInt64, constraints="=l"
- ]()
- )
return _monotonic_nanoseconds()
-# ===----------------------------------------------------------------------===#
-# now
-# ===----------------------------------------------------------------------===#
-
-
-@always_inline
-fn now() -> Int:
- """Deprecated: Please use time.perf_counter_ns instead.
-
- Returns the current monotonic time time in nanoseconds. This function
- queries the current platform's monotonic clock, making it useful for
- measuring time differences, but the significance of the returned value
- varies depending on the underlying implementation.
-
- Returns:
- The current time in ns.
- """
- return perf_counter_ns()
-
-
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# monotonic
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
-fn monotonic() -> Int:
+fn monotonic() -> UInt:
"""
Returns the current monotonic time time in nanoseconds. This function
queries the current platform's monotonic clock, making it useful for
@@ -253,16 +234,16 @@ fn monotonic() -> Int:
return perf_counter_ns()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# time_function
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@parameter
fn _time_function_windows[
func: fn () raises capturing [_] -> None
-]() raises -> Int:
+]() raises -> UInt:
"""Calculates elapsed time in Windows"""
var ticks_per_sec: _WINDOWS_LARGE_INTEGER = 0
@@ -293,7 +274,7 @@ fn _time_function_windows[
@always_inline
@parameter
-fn time_function[func: fn () raises capturing [_] -> None]() raises -> Int:
+fn time_function[func: fn () raises capturing [_] -> None]() raises -> UInt:
"""Measures the time spent in the function.
Parameters:
@@ -315,7 +296,7 @@ fn time_function[func: fn () raises capturing [_] -> None]() raises -> Int:
@always_inline
@parameter
-fn time_function[func: fn () capturing [_] -> None]() -> Int:
+fn time_function[func: fn () capturing [_] -> None]() -> UInt:
"""Measures the time spent in the function.
Parameters:
@@ -332,12 +313,12 @@ fn time_function[func: fn () capturing [_] -> None]() -> Int:
try:
return time_function[raising_func]()
except err:
- return abort[Int](err)
+ return abort[UInt](err)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# sleep
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
fn sleep(sec: Float64):
@@ -348,17 +329,10 @@ fn sleep(sec: Float64):
"""
@parameter
- if is_nvidia_gpu():
+ if is_gpu():
var nsec = sec * 1.0e9
- llvm_intrinsic["llvm.nvvm.nanosleep", NoneType](
- nsec.cast[DType.int32]()
- )
- return
- elif is_amd_gpu():
- var nsec = sec * 1.0e9
- llvm_intrinsic["llvm.amdgcn.s.sleep", NoneType](
- nsec.cast[DType.int32]()
- )
+ alias intrinsic = "llvm.nvvm.nanosleep" if is_nvidia_gpu() else "llvm.amdgcn.s.sleep"
+ llvm_intrinsic[intrinsic, NoneType](nsec.cast[DType.int32]())
return
alias NANOSECONDS_IN_SECOND = 1_000_000_000
@@ -375,7 +349,7 @@ fn sleep(sec: Float64):
_ = rem
-fn sleep(sec: Int):
+fn sleep(sec: UInt):
"""Suspends the current thread for the seconds specified.
Args:
@@ -383,7 +357,7 @@ fn sleep(sec: Int):
"""
@parameter
- if is_nvidia_gpu() or is_amd_gpu():
+ if is_gpu():
return sleep(Float64(sec))
@parameter
diff --git a/stdlib/src/utils/__init__.mojo b/stdlib/src/utils/__init__.mojo
index d319cf884a..fa6129cc1c 100644
--- a/stdlib/src/utils/__init__.mojo
+++ b/stdlib/src/utils/__init__.mojo
@@ -14,11 +14,10 @@
from .index import Index, IndexList, product
from .inline_string import InlineString
+from .lock import BlockingScopedLock, BlockingSpinLock, SpinWaiter
from .loop import unroll
-from .span import AsBytes, Span
from .static_tuple import StaticTuple
-from .stringref import StringRef
from .string_slice import StaticString, StringSlice
+from .stringref import StringRef
from .variant import Variant
-from .lock import SpinWaiter, BlockingSpinLock, BlockingScopedLock
-from .write import Writer, Writable, write_args, write_buffered
+from .write import Writable, Writer, write_args, write_buffered
diff --git a/stdlib/src/utils/_serialize.mojo b/stdlib/src/utils/_serialize.mojo
index 5eadeb4788..1cc0eea138 100644
--- a/stdlib/src/utils/_serialize.mojo
+++ b/stdlib/src/utils/_serialize.mojo
@@ -13,7 +13,7 @@
from pathlib import Path
-from memory import AddressSpace, bitcast, UnsafePointer
+from memory import AddressSpace, UnsafePointer, bitcast
alias _kStartTensorMarker = "["
alias _kEndTensorMarker = "]"
@@ -25,7 +25,7 @@ alias _kCompactElemPerSide = _kCompactMaxElemsToPrint // 2
fn _serialize_elements_compact[
type: DType, //,
serialize_fn: fn[T: Writable] (elem: T) capturing [_] -> None,
-](ptr: UnsafePointer[Scalar[type], _], len: Int):
+](ptr: UnsafePointer[Scalar[type], **_], len: Int):
serialize_fn(_kStartTensorMarker)
if len < _kCompactMaxElemsToPrint:
_serialize_elements_complete[serialize_fn=serialize_fn](ptr, len)
@@ -46,7 +46,7 @@ fn _serialize_elements_compact[
fn _serialize_elements_complete[
type: DType, //,
serialize_fn: fn[T: Writable] (elem: T) capturing [_] -> None,
-](ptr: UnsafePointer[Scalar[type], _], len: Int):
+](ptr: UnsafePointer[Scalar[type], **_], len: Int):
if len == 0:
return
serialize_fn(ptr.load())
@@ -59,7 +59,7 @@ fn _serialize_elements[
type: DType, //,
serialize_fn: fn[T: Writable] (elem: T) capturing [_] -> None,
compact: Bool = False,
-](ptr: UnsafePointer[Scalar[type], _], len: Int):
+](ptr: UnsafePointer[Scalar[type], **_], len: Int):
@parameter
if compact:
_serialize_elements_compact[serialize_fn=serialize_fn](ptr, len)
@@ -73,7 +73,7 @@ fn _serialize[
serialize_dtype: Bool = True,
serialize_shape: Bool = True,
serialize_end_line: Bool = True,
-](ptr: UnsafePointer[Scalar[type], _], shape: List[Int, *_]):
+](ptr: UnsafePointer[Scalar[type], **_], shape: List[Int, *_]):
var rank = len(shape)
if rank == 0:
if serialize_end_line:
diff --git a/stdlib/src/utils/_unicode.mojo b/stdlib/src/utils/_unicode.mojo
index 079bd7e180..fb61a24cd9 100644
--- a/stdlib/src/utils/_unicode.mojo
+++ b/stdlib/src/utils/_unicode.mojo
@@ -11,7 +11,8 @@
# limitations under the License.
# ===----------------------------------------------------------------------=== #
from bit import count_leading_zeros
-from memory import memcpy, UnsafePointer
+from memory import UnsafePointer, memcpy
+
from ._unicode_lookups import *
diff --git a/stdlib/src/utils/_utf8_validation.mojo b/stdlib/src/utils/_utf8_validation.mojo
index 800ed5626b..eb514733ca 100644
--- a/stdlib/src/utils/_utf8_validation.mojo
+++ b/stdlib/src/utils/_utf8_validation.mojo
@@ -25,9 +25,10 @@ Code adapted from:
https://github.com/simdutf/SimdUnicode/blob/main/src/UTF8.cs
"""
-from memory import UnsafePointer
+from base64._b64encode import _sub_with_saturation
from sys.intrinsics import llvm_intrinsic
-from builtin.simd import _sub_with_saturation
+
+from memory import UnsafePointer, Span
alias TOO_SHORT: UInt8 = 1 << 0
alias TOO_LONG: UInt8 = 1 << 1
diff --git a/stdlib/src/utils/format.mojo b/stdlib/src/utils/format.mojo
new file mode 100644
index 0000000000..752a34898d
--- /dev/null
+++ b/stdlib/src/utils/format.mojo
@@ -0,0 +1,715 @@
+# ===----------------------------------------------------------------------=== #
+# Copyright (c) 2024, Modular Inc. All rights reserved.
+#
+# Licensed under the Apache License v2.0 with LLVM Exceptions:
+# https://llvm.org/LICENSE.txt
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ===----------------------------------------------------------------------=== #
+"""Implements Formatting utilities."""
+
+from collections import Optional
+
+from memory import UnsafePointer
+
+# TODO: _FormatCurlyEntry and _FormatSpec should be public in the future for
+# people who want to write their own templating engines. This is not yet done
+# because the implementation is incomplete and we are missing crucial features.
+
+# ===-----------------------------------------------------------------------===#
+# Formatter
+# ===-----------------------------------------------------------------------===#
+
+
+# NOTE(#3765): an interesting idea would be to allow custom start and end
+# characters for formatting (passed as parameters to Formatter), this would be
+# useful for people developing custom templating engines as it would allow
+# detemining e.g. `` [...] `` html tags.
+# And going a step further it might even be worth it adding custom format
+# specification start character, and custom format specs themselves (by defining
+# a trait that all format specifications conform to)
+@value
+struct _FormatCurlyEntry(CollectionElement, CollectionElementNew):
+ """The struct that handles string formatting by curly braces entries.
+ This is internal for the types: `String`, `StringLiteral` and `StringSlice`.
+ """
+
+ var first_curly: Int
+ """The index of an opening brace around a substitution field."""
+ var last_curly: Int
+ """The index of a closing brace around a substitution field."""
+ # TODO: ord("a") conversion flag not supported yet
+ var conversion_flag: UInt8
+ """The type of conversion for the entry: {ord("s"), ord("r")}."""
+ var format_spec: Optional[_FormatSpec]
+ """The format specifier."""
+ # TODO: ord("a") conversion flag not supported yet
+ alias supported_conversion_flags = SIMD[DType.uint8, 2](ord("s"), ord("r"))
+ """Currently supported conversion flags: `__str__` and `__repr__`."""
+ alias _FieldVariantType = Variant[String, Int, NoneType, Bool]
+ """Purpose of the `Variant` `Self.field`:
+
+ - `Int` for manual indexing: (value field contains `0`).
+ - `NoneType` for automatic indexing: (value field contains `None`).
+ - `String` for **kwargs indexing: (value field contains `foo`).
+ - `Bool` for escaped curlies: (value field contains False for `{` or True
+ for `}`).
+ """
+ var field: Self._FieldVariantType
+ """Store the substitution field. See `Self._FieldVariantType` docstrings for
+ more details."""
+ alias _args_t = VariadicPack[element_trait=_CurlyEntryFormattable, *_]
+ """Args types that are formattable by curly entry."""
+
+ fn __init__(out self, *, other: Self):
+ """Construct a format entry by copying another.
+
+ Args:
+ other: The other format entry.
+ """
+ self.first_curly = other.first_curly
+ self.last_curly = other.last_curly
+ self.conversion_flag = other.conversion_flag
+ self.field = Self._FieldVariantType(other=other.field)
+ self.format_spec = other.format_spec
+
+ fn __init__(
+ mut self,
+ first_curly: Int,
+ last_curly: Int,
+ field: Self._FieldVariantType,
+ conversion_flag: UInt8 = 0,
+ format_spec: Optional[_FormatSpec] = None,
+ ):
+ """Construct a format entry.
+
+ Args:
+ first_curly: The index of an opening brace around a substitution
+ field.
+ last_curly: The index of a closing brace around a substitution
+ field.
+ field: Store the substitution field.
+ conversion_flag: The type of conversion for the entry.
+ format_spec: The format specifier.
+ """
+ self.first_curly = first_curly
+ self.last_curly = last_curly
+ self.field = field
+ self.conversion_flag = conversion_flag
+ self.format_spec = format_spec
+
+ @always_inline
+ fn is_escaped_brace(ref self) -> Bool:
+ """Whether the field is escaped_brace.
+
+ Returns:
+ The result.
+ """
+ return self.field.isa[Bool]()
+
+ @always_inline
+ fn is_kwargs_field(ref self) -> Bool:
+ """Whether the field is kwargs_field.
+
+ Returns:
+ The result.
+ """
+ return self.field.isa[String]()
+
+ @always_inline
+ fn is_automatic_indexing(ref self) -> Bool:
+ """Whether the field is automatic_indexing.
+
+ Returns:
+ The result.
+ """
+ return self.field.isa[NoneType]()
+
+ @always_inline
+ fn is_manual_indexing(ref self) -> Bool:
+ """Whether the field is manual_indexing.
+
+ Returns:
+ The result.
+ """
+ return self.field.isa[Int]()
+
+ @staticmethod
+ fn format(fmt_src: StringSlice, args: Self._args_t) raises -> String:
+ """Format the entries.
+
+ Args:
+ fmt_src: The format source.
+ args: The arguments.
+
+ Returns:
+ The result.
+ """
+ alias len_pos_args = __type_of(args).__len__()
+ entries, size_estimation = Self._create_entries(fmt_src, len_pos_args)
+ var fmt_len = fmt_src.byte_length()
+ var buf = String._buffer_type(capacity=fmt_len + size_estimation)
+ buf.size = 1
+ buf.unsafe_set(0, 0)
+ var res = String(buf^)
+ var offset = 0
+ var ptr = fmt_src.unsafe_ptr()
+ alias S = StringSlice[StaticConstantOrigin]
+
+ @always_inline("nodebug")
+ fn _build_slice(p: UnsafePointer[UInt8], start: Int, end: Int) -> S:
+ return S(ptr=p + start, length=end - start)
+
+ var auto_arg_index = 0
+ for e in entries:
+ debug_assert(offset < fmt_len, "offset >= fmt_src.byte_length()")
+ res += _build_slice(ptr, offset, e[].first_curly)
+ e[]._format_entry[len_pos_args](res, args, auto_arg_index)
+ offset = e[].last_curly + 1
+
+ res += _build_slice(ptr, offset, fmt_len)
+ return res^
+
+ @staticmethod
+ fn _create_entries(
+ fmt_src: StringSlice, len_pos_args: Int
+ ) raises -> (List[Self], Int):
+ """Returns a list of entries and its total estimated entry byte width.
+ """
+ var manual_indexing_count = 0
+ var automatic_indexing_count = 0
+ var raised_manual_index = Optional[Int](None)
+ var raised_automatic_index = Optional[Int](None)
+ var raised_kwarg_field = Optional[String](None)
+ alias `}` = UInt8(ord("}"))
+ alias `{` = UInt8(ord("{"))
+ alias l_err = "there is a single curly { left unclosed or unescaped"
+ alias r_err = "there is a single curly } left unclosed or unescaped"
+
+ var entries = List[Self]()
+ var start = Optional[Int](None)
+ var skip_next = False
+ var fmt_ptr = fmt_src.unsafe_ptr()
+ var fmt_len = fmt_src.byte_length()
+ var total_estimated_entry_byte_width = 0
+
+ for i in range(fmt_len):
+ if skip_next:
+ skip_next = False
+ continue
+ if fmt_ptr[i] == `{`:
+ if not start:
+ start = i
+ continue
+ if i - start.value() != 1:
+ raise Error(l_err)
+ # python escapes double curlies
+ entries.append(Self(start.value(), i, field=False))
+ start = None
+ continue
+ elif fmt_ptr[i] == `}`:
+ if not start and (i + 1) < fmt_len:
+ # python escapes double curlies
+ if fmt_ptr[i + 1] == `}`:
+ entries.append(Self(i, i + 1, field=True))
+ total_estimated_entry_byte_width += 2
+ skip_next = True
+ continue
+ elif not start: # if it is not an escaped one, it is an error
+ raise Error(r_err)
+
+ var start_value = start.value()
+ var current_entry = Self(start_value, i, field=NoneType())
+
+ if i - start_value != 1:
+ if current_entry._handle_field_and_break(
+ fmt_src,
+ len_pos_args,
+ i,
+ start_value,
+ automatic_indexing_count,
+ raised_automatic_index,
+ manual_indexing_count,
+ raised_manual_index,
+ raised_kwarg_field,
+ total_estimated_entry_byte_width,
+ ):
+ break
+ else: # automatic indexing
+ if automatic_indexing_count >= len_pos_args:
+ raised_automatic_index = automatic_indexing_count
+ break
+ automatic_indexing_count += 1
+ total_estimated_entry_byte_width += 8 # guessing
+ entries.append(current_entry^)
+ start = None
+
+ if raised_automatic_index:
+ raise Error("Automatic indexing require more args in *args")
+ elif raised_kwarg_field:
+ var val = raised_kwarg_field.value()
+ raise Error("Index " + val + " not in kwargs")
+ elif manual_indexing_count and automatic_indexing_count:
+ raise Error("Cannot both use manual and automatic indexing")
+ elif raised_manual_index:
+ var val = str(raised_manual_index.value())
+ raise Error("Index " + val + " not in *args")
+ elif start:
+ raise Error(l_err)
+ return entries^, total_estimated_entry_byte_width
+
+ fn _handle_field_and_break(
+ mut self,
+ fmt_src: StringSlice,
+ len_pos_args: Int,
+ i: Int,
+ start_value: Int,
+ mut automatic_indexing_count: Int,
+ mut raised_automatic_index: Optional[Int],
+ mut manual_indexing_count: Int,
+ mut raised_manual_index: Optional[Int],
+ mut raised_kwarg_field: Optional[String],
+ mut total_estimated_entry_byte_width: Int,
+ ) raises -> Bool:
+ alias S = StringSlice[StaticConstantOrigin]
+
+ @always_inline("nodebug")
+ fn _build_slice(p: UnsafePointer[UInt8], start: Int, end: Int) -> S:
+ return S(ptr=p + start, length=end - start)
+
+ var field = _build_slice(fmt_src.unsafe_ptr(), start_value + 1, i)
+ var field_ptr = field.unsafe_ptr()
+ var field_len = i - (start_value + 1)
+ var exclamation_index = -1
+ var idx = 0
+ while idx < field_len:
+ if field_ptr[idx] == ord("!"):
+ exclamation_index = idx
+ break
+ idx += 1
+ var new_idx = exclamation_index + 1
+ if exclamation_index != -1:
+ if new_idx == field_len:
+ raise Error("Empty conversion flag.")
+ var conversion_flag = field_ptr[new_idx]
+ if field_len - new_idx > 1 or (
+ conversion_flag not in Self.supported_conversion_flags
+ ):
+ var f = String(_build_slice(field_ptr, new_idx, field_len))
+ _ = field
+ raise Error('Conversion flag "' + f + '" not recognised.')
+ self.conversion_flag = conversion_flag
+ field = _build_slice(field_ptr, 0, exclamation_index)
+ else:
+ new_idx += 1
+
+ var extra = int(new_idx < field_len)
+ var fmt_field = _build_slice(field_ptr, new_idx + extra, field_len)
+ self.format_spec = _FormatSpec.parse(fmt_field)
+ var w = int(self.format_spec.value().width) if self.format_spec else 0
+ # fully guessing the byte width here to be at least 8 bytes per entry
+ # minus the length of the whole format specification
+ total_estimated_entry_byte_width += 8 * int(w > 0) + w - (field_len + 2)
+
+ if field.byte_length() == 0:
+ # an empty field, so it's automatic indexing
+ if automatic_indexing_count >= len_pos_args:
+ raised_automatic_index = automatic_indexing_count
+ return True
+ automatic_indexing_count += 1
+ else:
+ try:
+ # field is a number for manual indexing:
+ # TODO: add support for "My name is {0.name}".format(Person(name="Fred"))
+ # TODO: add support for "My name is {0[name]}".format({"name": "Fred"})
+ var number = int(field)
+ self.field = number
+ if number >= len_pos_args or number < 0:
+ raised_manual_index = number
+ return True
+ manual_indexing_count += 1
+ except e:
+ alias unexp = "Not the expected error from atol"
+ debug_assert("not convertible to integer" in str(e), unexp)
+ # field is a keyword for **kwargs:
+ # TODO: add support for "My name is {person.name}".format(person=Person(name="Fred"))
+ # TODO: add support for "My name is {person[name]}".format(person={"name": "Fred"})
+ var f = str(field)
+ self.field = f
+ raised_kwarg_field = f
+ return True
+ return False
+
+ fn _format_entry[
+ len_pos_args: Int
+ ](self, mut res: String, args: Self._args_t, mut auto_idx: Int) raises:
+ # TODO(#3403 and/or #3252): this function should be able to use
+ # Writer syntax when the type implements it, since it will give great
+ # performance benefits. This also needs to be able to check if the given
+ # args[i] conforms to the trait needed by the conversion_flag to avoid
+ # needing to constraint that every type needs to conform to every trait.
+ alias `r` = UInt8(ord("r"))
+ alias `s` = UInt8(ord("s"))
+ # alias `a` = UInt8(ord("a")) # TODO
+
+ @parameter
+ fn _format(idx: Int) raises:
+ @parameter
+ for i in range(len_pos_args):
+ if i == idx:
+ var type_impls_repr = True # TODO
+ var type_impls_str = True # TODO
+ var type_impls_write_repr = True # TODO
+ var type_impls_write_str = True # TODO
+ var flag = self.conversion_flag
+ var empty = flag == 0 and not self.format_spec
+
+ var data: String
+ if empty and type_impls_write_str:
+ data = str(args[i]) # TODO: use writer and return
+ elif empty and type_impls_str:
+ data = str(args[i])
+ elif flag == `s` and type_impls_write_str:
+ if empty:
+ # TODO: use writer and return
+ pass
+ data = str(args[i])
+ elif flag == `s` and type_impls_str:
+ data = str(args[i])
+ elif flag == `r` and type_impls_write_repr:
+ if empty:
+ # TODO: use writer and return
+ pass
+ data = repr(args[i])
+ elif flag == `r` and type_impls_repr:
+ data = repr(args[i])
+ elif self.format_spec:
+ self.format_spec.value().format(res, args[i])
+ return
+ else:
+ alias argnum = "Argument number: "
+ alias does_not = " does not implement the trait "
+ alias needed = "needed for conversion_flag: "
+ var flg = String(List[UInt8](flag, 0))
+ raise Error(argnum + str(i) + does_not + needed + flg)
+
+ if self.format_spec:
+ self.format_spec.value().format(
+ res, data.as_string_slice()
+ )
+ else:
+ res += data
+
+ if self.is_escaped_brace():
+ res += "}" if self.field[Bool] else "{"
+ elif self.is_manual_indexing():
+ _format(self.field[Int])
+ elif self.is_automatic_indexing():
+ _format(auto_idx)
+ auto_idx += 1
+
+
+# ===-----------------------------------------------------------------------===#
+# Format Specification
+# ===-----------------------------------------------------------------------===#
+
+
+trait _CurlyEntryFormattable(Stringable, Representable):
+ """This trait is used by the `format()` method to support format specifiers.
+ Currently, it is a composition of both `Stringable` and `Representable`
+ traits i.e. a type to be formatted must implement both. In the future this
+ will be less constrained.
+ """
+
+ ...
+
+
+# TODO: trait _FormattableStr: fn __format__(self, spec: FormatSpec) -> String:
+# TODO: trait _FormattableWrite: fn __format__(self, spec: FormatSpec, *, writer: Writer):
+# TODO: add usage of these traits before trying to coerce to repr/str/int/float
+
+
+@value
+@register_passable("trivial")
+struct _FormatSpec:
+ """Store every field of the format specifier in a byte (e.g., ord("+") for
+ sign). It is stored in a byte because every [format specifier](
+ https://docs.python.org/3/library/string.html#formatspec) is an ASCII
+ character.
+ """
+
+ var fill: UInt8
+ """If a valid align value is specified, it can be preceded by a fill
+ character that can be any character and defaults to a space if omitted.
+ """
+ var align: UInt8
+ """The meaning of the various alignment options is as follows:
+
+ | Option | Meaning|
+ |:------:|:-------|
+ |'<' | Forces the field to be left-aligned within the available space \
+ (this is the default for most objects).|
+ |'>' | Forces the field to be right-aligned within the available space \
+ (this is the default for numbers).|
+ |'=' | Forces the padding to be placed after the sign (if any) but before \
+ the digits. This is used for printing fields in the form `+000000120`. This\
+ alignment option is only valid for numeric types. It becomes the default\
+ for numbers when `0` immediately precedes the field width.|
+ |'^' | Forces the field to be centered within the available space.|
+ """
+ var sign: UInt8
+ """The sign option is only valid for number types, and can be one of the
+ following:
+
+ | Option | Meaning|
+ |:------:|:-------|
+ |'+' | indicates that a sign should be used for both positive as well as\
+ negative numbers.|
+ |'-' | indicates that a sign should be used only for negative numbers (this\
+ is the default behavior).|
+ |space | indicates that a leading space should be used on positive numbers,\
+ and a minus sign on negative numbers.|
+ """
+ var coerce_z: Bool
+ """The 'z' option coerces negative zero floating-point values to positive
+ zero after rounding to the format precision. This option is only valid for
+ floating-point presentation types.
+ """
+ var alternate_form: Bool
+ """The alternate form is defined differently for different types. This
+ option is only valid for types that implement the trait `# TODO: define
+ trait`. For integers, when binary, octal, or hexadecimal output is used,
+ this option adds the respective prefix '0b', '0o', '0x', or '0X' to the
+ output value. For float and complex the alternate form causes the result of
+ the conversion to always contain a decimal-point character, even if no
+ digits follow it.
+ """
+ var width: UInt8
+ """A decimal integer defining the minimum total field width, including any
+ prefixes, separators, and other formatting characters. If not specified,
+ then the field width will be determined by the content. When no explicit
+ alignment is given, preceding the width field by a zero ('0') character
+ enables sign-aware zero-padding for numeric types. This is equivalent to a
+ fill character of '0' with an alignment type of '='.
+ """
+ var grouping_option: UInt8
+ """The ',' option signals the use of a comma for a thousands separator. For
+ a locale aware separator, use the 'n' integer presentation type instead. The
+ '_' option signals the use of an underscore for a thousands separator for
+ floating-point presentation types and for integer presentation type 'd'. For
+ integer presentation types 'b', 'o', 'x', and 'X', underscores will be
+ inserted every 4 digits. For other presentation types, specifying this
+ option is an error.
+ """
+ var precision: UInt8
+ """The precision is a decimal integer indicating how many digits should be
+ displayed after the decimal point for presentation types 'f' and 'F', or
+ before and after the decimal point for presentation types 'g' or 'G'. For
+ string presentation types the field indicates the maximum field size - in
+ other words, how many characters will be used from the field content. The
+ precision is not allowed for integer presentation types.
+ """
+ var type: UInt8
+ """Determines how the data should be presented.
+
+ The available integer presentation types are:
+
+ | Option | Meaning|
+ |:------:|:-------|
+ |'b' |Binary format. Outputs the number in base 2.|
+ |'c' |Character. Converts the integer to the corresponding unicode\
+ character before printing.|
+ |'d' |Decimal Integer. Outputs the number in base 10.|
+ |'o' |Octal format. Outputs the number in base 8.|
+ |'x' |Hex format. Outputs the number in base 16, using lower-case letters\
+ for the digits above 9.|
+ |'X' |Hex format. Outputs the number in base 16, using upper-case letters\
+ for the digits above 9. In case '#' is specified, the prefix '0x' will be\
+ upper-cased to '0X' as well.|
+ |'n' |Number. This is the same as 'd', except that it uses the current\
+ locale setting to insert the appropriate number separator characters.|
+ |None | The same as 'd'.|
+
+ In addition to the above presentation types, integers can be formatted with
+ the floating-point presentation types listed below (except 'n' and None).
+ When doing so, float() is used to convert the integer to a floating-point
+ number before formatting.
+
+ The available presentation types for float and Decimal values are:
+
+ | Option | Meaning|
+ |:------:|:-------|
+ |'e' |Scientific notation. For a given precision p, formats the number in\
+ scientific notation with the letter `e` separating the coefficient from the\
+ exponent. The coefficient has one digit before and p digits after the\
+ decimal point, for a total of p + 1 significant digits. With no precision\
+ given, uses a precision of 6 digits after the decimal point for float, and\
+ shows all coefficient digits for Decimal. If no digits follow the decimal\
+ point, the decimal point is also removed unless the # option is used.|
+ |'E' |Scientific notation. Same as 'e' except it uses an upper case `E` as\
+ the separator character.|
+ |'f' |Fixed-point notation. For a given precision p, formats the number as\
+ a decimal number with exactly p digits following the decimal point. With no\
+ precision given, uses a precision of 6 digits after the decimal point for\
+ float, and uses a precision large enough to show all coefficient digits for\
+ Decimal. If no digits follow the decimal point, the decimal point is also\
+ removed unless the '#' option is used.|
+ |'F' |Fixed-point notation. Same as 'f', but converts nan to NAN and inf to\
+ INF.|
+ |'g' |General format. For a given precision p >= 1, this rounds the number\
+ to p significant digits and then formats the result in either fixed-point\
+ format or in scientific notation, depending on its magnitude. A precision\
+ of 0 is treated as equivalent to a precision of 1.\
+ The precise rules are as follows: suppose that the result formatted with\
+ presentation type 'e' and precision p-1 would have exponent exp. Then, if\
+ m <= exp < p, where m is -4 for floats and -6 for Decimals, the number is\
+ formatted with presentation type 'f' and precision p-1-exp. Otherwise, the\
+ number is formatted with presentation type 'e' and precision p-1. In both\
+ cases insignificant trailing zeros are removed from the significand, and\
+ the decimal point is also removed if there are no remaining digits\
+ following it, unless the '#' option is used.\
+ With no precision given, uses a precision of 6 significant digits for\
+ float. For Decimal, the coefficient of the result is formed from the\
+ coefficient digits of the value; scientific notation is used for values\
+ smaller than 1e-6 in absolute value and values where the place value of the\
+ least significant digit is larger than 1, and fixed-point notation is used\
+ otherwise.\
+ Positive and negative infinity, positive and negative zero, and nans, are\
+ formatted as inf, -inf, 0, -0 and nan respectively, regardless of the\
+ precision.|
+ |'G' |General format. Same as 'g' except switches to 'E' if the number gets\
+ too large. The representations of infinity and NaN are uppercased, too.|
+ |'n' |Number. This is the same as 'g', except that it uses the current\
+ locale setting to insert the appropriate number separator characters.|
+ |'%' |Percentage. Multiplies the number by 100 and displays in fixed ('f')\
+ format, followed by a percent sign.|
+ |None |For float this is like the 'g' type, except that when fixed-point\
+ notation is used to format the result, it always includes at least one\
+ digit past the decimal point, and switches to the scientific notation when\
+ exp >= p - 1. When the precision is not specified, the latter will be as\
+ large as needed to represent the given value faithfully.\
+ For Decimal, this is the same as either 'g' or 'G' depending on the value\
+ of context.capitals for the current decimal context.\
+ The overall effect is to match the output of str() as altered by the other\
+ format modifiers.|
+ """
+
+ fn __init__(
+ mut self,
+ fill: UInt8 = ord(" "),
+ align: UInt8 = 0,
+ sign: UInt8 = ord("-"),
+ coerce_z: Bool = False,
+ alternate_form: Bool = False,
+ width: UInt8 = 0,
+ grouping_option: UInt8 = 0,
+ precision: UInt8 = 0,
+ type: UInt8 = 0,
+ ):
+ """Construct a FormatSpec instance.
+
+ Args:
+ fill: Defaults to space.
+ align: Defaults to `0` which is adjusted to the default for the arg
+ type.
+ sign: Defaults to `-`.
+ coerce_z: Defaults to False.
+ alternate_form: Defaults to False.
+ width: Defaults to `0` which is adjusted to the default for the arg
+ type.
+ grouping_option: Defaults to `0` which is adjusted to the default for
+ the arg type.
+ precision: Defaults to `0` which is adjusted to the default for the
+ arg type.
+ type: Defaults to `0` which is adjusted to the default for the arg
+ type.
+ """
+ self.fill = fill
+ self.align = align
+ self.sign = sign
+ self.coerce_z = coerce_z
+ self.alternate_form = alternate_form
+ self.width = width
+ self.grouping_option = grouping_option
+ self.precision = precision
+ self.type = type
+
+ @staticmethod
+ fn parse(fmt_str: StringSlice) -> Optional[Self]:
+ """Parses the format spec string.
+
+ Args:
+ fmt_str: The StringSlice with the format spec.
+
+ Returns:
+ An instance of FormatSpec.
+ """
+
+ # FIXME: the need for the following dynamic characteristics will
+ # probably mean the parse method will have to be called at the
+ # formatting stage in cases where it's dynamic.
+ # TODO: add support for "{0:{1}}".format(123, "10")
+ # TODO: add support for more complex cases as well
+ # >>> width = 10
+ # >>> precision = 4
+ # >>> value = decimal.Decimal('12.34567')
+ # >>> 'result: {value:{width}.{precision}}'.format(...)
+ alias `:` = UInt8(ord(":"))
+ var f_len = fmt_str.byte_length()
+ var f_ptr = fmt_str.unsafe_ptr()
+ var colon_idx = -1
+ var idx = 0
+ while idx < f_len:
+ if f_ptr[idx] == `:`:
+ exclamation_index = idx
+ break
+ idx += 1
+
+ if colon_idx == -1:
+ return None
+
+ # TODO: Future implementation of format specifiers
+ return None
+
+ # TODO: this should be in StringSlice.__format__(self, spec: FormatSpec, *, writer: Writer):
+ fn format(self, mut res: String, item: StringSlice) raises:
+ """Transform a String according to its format specification.
+
+ Args:
+ res: The resulting String.
+ item: The item to format.
+ """
+
+ # TODO: align, fill, etc.
+ res += item
+
+ fn format[T: _CurlyEntryFormattable](self, mut res: String, item: T) raises:
+ """Stringify a type according to its format specification.
+
+ Args:
+ res: The resulting String.
+ item: The item to stringify.
+ """
+ var type_implements_format_write = True # TODO
+ var type_implements_format_write_raising = True # TODO
+ var type_implements_format = True # TODO
+ var type_implements_format_raising = True # TODO
+ var type_implements_float = True # TODO
+ var type_implements_float_raising = True # TODO
+ var type_implements_int = True # TODO
+ var type_implements_int_raising = True # TODO
+
+ # TODO: send to the type's __format__ method if it has one
+ # TODO: transform to int/float depending on format spec
+ # TODO: send to float/int 's __format__ method
+ # their methods should stringify as hex/bin/oct etc.
+ res += str(item)
+
+
+# ===-----------------------------------------------------------------------===#
+# Utils
+# ===-----------------------------------------------------------------------===#
diff --git a/stdlib/src/utils/index.mojo b/stdlib/src/utils/index.mojo
index ff6ada51d1..0ea7685fe4 100644
--- a/stdlib/src/utils/index.mojo
+++ b/stdlib/src/utils/index.mojo
@@ -20,17 +20,18 @@ from utils import IndexList
```
"""
+from collections.string import _calc_initial_buffer_size
from sys import bitwidthof
+
from builtin.dtype import _int_type_of_width, _uint_type_of_width
from builtin.io import _get_dtype_printf_format, _snprintf
-from collections.string import _calc_initial_buffer_size
from . import unroll
from .static_tuple import StaticTuple
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Utilities
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -47,10 +48,10 @@ fn _reduce_and_fn(a: Bool, b: Bool) -> Bool:
return a and b
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Integer and Bool Tuple Utilities:
# Utilities to operate on tuples of integers or tuples of bools.
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -146,9 +147,9 @@ fn _bool_tuple_reduce[
return c
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# IndexList:
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
fn _type_of_width[bitwidth: Int, unsigned: Bool]() -> DType:
@@ -403,7 +404,7 @@ struct IndexList[
return int(self.data[idx])
@always_inline("nodebug")
- fn __setitem__[index: Int](inout self, val: Int):
+ fn __setitem__[index: Int](mut self, val: Int):
"""Sets an element in the tuple at the given static index.
Parameters:
@@ -415,7 +416,7 @@ struct IndexList[
self.data.__setitem__[index](val)
@always_inline("nodebug")
- fn __setitem__[index: Int](inout self, val: Self._int_type):
+ fn __setitem__[index: Int](mut self, val: Self._int_type):
"""Sets an element in the tuple at the given static index.
Parameters:
@@ -427,7 +428,7 @@ struct IndexList[
self.data.__setitem__[index](val)
@always_inline("nodebug")
- fn __setitem__(inout self, idx: Int, val: Int):
+ fn __setitem__(mut self, idx: Int, val: Int):
"""Sets an element in the tuple at the given index.
Args:
@@ -453,9 +454,10 @@ struct IndexList[
@always_inline("nodebug")
fn canonicalize(
self,
- ) -> IndexList[
- size, element_bitwidth = bitwidthof[Int](), unsigned=False
- ] as result:
+ out result: IndexList[
+ size, element_bitwidth = bitwidthof[Int](), unsigned=False
+ ],
+ ):
"""Canonicalizes the IndexList.
Returns:
@@ -754,7 +756,7 @@ struct IndexList[
return buf^
@no_inline
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""
Formats this int tuple to the provided Writer.
@@ -771,11 +773,14 @@ struct IndexList[
@always_inline
fn cast[
type: DType
- ](self) -> IndexList[
- size,
- element_bitwidth = bitwidthof[type](),
- unsigned = _is_unsigned[type](),
- ] as result:
+ ](
+ self,
+ out result: IndexList[
+ size,
+ element_bitwidth = bitwidthof[type](),
+ unsigned = _is_unsigned[type](),
+ ],
+ ):
"""Casts to the target DType.
Parameters:
@@ -802,9 +807,12 @@ struct IndexList[
*,
element_bitwidth: Int = Self.element_bitwidth,
unsigned: Bool = Self.unsigned,
- ](self) -> IndexList[
- size, element_bitwidth=element_bitwidth, unsigned=unsigned
- ] as result:
+ ](
+ self,
+ out result: IndexList[
+ size, element_bitwidth=element_bitwidth, unsigned=unsigned
+ ],
+ ):
"""Casts to the target DType.
Parameters:
@@ -827,18 +835,21 @@ struct IndexList[
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Factory functions for creating index.
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
fn Index[
T0: Intable, //,
*,
element_bitwidth: Int = bitwidthof[Int](),
unsigned: Bool = False,
-](x: T0) -> IndexList[
- 1, element_bitwidth=element_bitwidth, unsigned=unsigned
-] as result:
+](
+ x: T0,
+ out result: IndexList[
+ 1, element_bitwidth=element_bitwidth, unsigned=unsigned
+ ],
+):
"""Constructs a 1-D Index from the given value.
Parameters:
@@ -858,9 +869,12 @@ fn Index[
@always_inline
fn Index[
*, element_bitwidth: Int = bitwidthof[Int](), unsigned: Bool = False
-](x: UInt) -> IndexList[
- 1, element_bitwidth=element_bitwidth, unsigned=unsigned
-] as result:
+](
+ x: UInt,
+ out result: IndexList[
+ 1, element_bitwidth=element_bitwidth, unsigned=unsigned
+ ],
+):
"""Constructs a 1-D Index from the given value.
Parameters:
@@ -883,9 +897,13 @@ fn Index[
*,
element_bitwidth: Int = bitwidthof[Int](),
unsigned: Bool = False,
-](x: T0, y: T1) -> IndexList[
- 2, element_bitwidth=element_bitwidth, unsigned=unsigned
-] as result:
+](
+ x: T0,
+ y: T1,
+ out result: IndexList[
+ 2, element_bitwidth=element_bitwidth, unsigned=unsigned
+ ],
+):
"""Constructs a 2-D Index from the given values.
Parameters:
@@ -907,9 +925,13 @@ fn Index[
@always_inline
fn Index[
*, element_bitwidth: Int = bitwidthof[Int](), unsigned: Bool = False
-](x: UInt, y: UInt) -> IndexList[
- 2, element_bitwidth=element_bitwidth, unsigned=unsigned
-] as result:
+](
+ x: UInt,
+ y: UInt,
+ out result: IndexList[
+ 2, element_bitwidth=element_bitwidth, unsigned=unsigned
+ ],
+):
"""Constructs a 2-D Index from the given values.
Parameters:
@@ -934,9 +956,14 @@ fn Index[
*,
element_bitwidth: Int = bitwidthof[Int](),
unsigned: Bool = False,
-](x: T0, y: T1, z: T2) -> IndexList[
- 3, element_bitwidth=element_bitwidth, unsigned=unsigned
-] as result:
+](
+ x: T0,
+ y: T1,
+ z: T2,
+ out result: IndexList[
+ 3, element_bitwidth=element_bitwidth, unsigned=unsigned
+ ],
+):
"""Constructs a 3-D Index from the given values.
Parameters:
@@ -966,9 +993,15 @@ fn Index[
*,
element_bitwidth: Int = bitwidthof[Int](),
unsigned: Bool = False,
-](x: T0, y: T1, z: T2, w: T3) -> IndexList[
- 4, element_bitwidth=element_bitwidth, unsigned=unsigned
-] as result:
+](
+ x: T0,
+ y: T1,
+ z: T2,
+ w: T3,
+ out result: IndexList[
+ 4, element_bitwidth=element_bitwidth, unsigned=unsigned
+ ],
+):
"""Constructs a 4-D Index from the given values.
Parameters:
@@ -1001,9 +1034,16 @@ fn Index[
*,
element_bitwidth: Int = bitwidthof[Int](),
unsigned: Bool = False,
-](x: T0, y: T1, z: T2, w: T3, v: T4) -> IndexList[
- 5, element_bitwidth=element_bitwidth, unsigned=unsigned
-] as result:
+](
+ x: T0,
+ y: T1,
+ z: T2,
+ w: T3,
+ v: T4,
+ out result: IndexList[
+ 5, element_bitwidth=element_bitwidth, unsigned=unsigned
+ ],
+):
"""Constructs a 5-D Index from the given values.
Parameters:
@@ -1028,9 +1068,9 @@ fn Index[
return __type_of(result)(int(x), int(y), int(z), int(w), int(v))
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Utils
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
diff --git a/stdlib/src/utils/inline_string.mojo b/stdlib/src/utils/inline_string.mojo
index 3f8d5d52f0..8c6cfb3166 100644
--- a/stdlib/src/utils/inline_string.mojo
+++ b/stdlib/src/utils/inline_string.mojo
@@ -15,18 +15,17 @@
avoids heap allocations for short strings.
"""
-from collections import InlineArray
+from collections import InlineArray, Optional
from os import abort
-from collections import Optional
from sys import sizeof
-from memory import UnsafePointer, memcpy
+from memory import UnsafePointer, memcpy, Span
from utils import StringSlice, Variant
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# InlineString
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@value
@@ -104,7 +103,7 @@ struct InlineString(Sized, Stringable, CollectionElement, CollectionElementNew):
# Operator dunders
# ===------------------------------------------------------------------=== #
- fn __iadd__(inout self, literal: StringLiteral):
+ fn __iadd__(mut self, literal: StringLiteral):
"""Appends another string to this string.
Args:
@@ -112,7 +111,7 @@ struct InlineString(Sized, Stringable, CollectionElement, CollectionElementNew):
"""
self.__iadd__(StringRef(literal))
- fn __iadd__(inout self, string: String):
+ fn __iadd__(mut self, string: String):
"""Appends another string to this string.
Args:
@@ -120,7 +119,7 @@ struct InlineString(Sized, Stringable, CollectionElement, CollectionElementNew):
"""
self.__iadd__(string.as_string_slice())
- fn __iadd__(inout self, str_slice: StringSlice[_]):
+ fn __iadd__(mut self, str_slice: StringSlice[_]):
"""Appends another string to this string.
Args:
@@ -297,9 +296,9 @@ struct InlineString(Sized, Stringable, CollectionElement, CollectionElementNew):
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# __FixedString
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@value
@@ -396,7 +395,7 @@ struct _FixedString[CAP: Int](
# Operator dunders
# ===------------------------------------------------------------------=== #
- fn __iadd__(inout self, literal: StringLiteral) raises:
+ fn __iadd__(mut self, literal: StringLiteral) raises:
"""Appends another string to this string.
Args:
@@ -404,7 +403,7 @@ struct _FixedString[CAP: Int](
"""
self.__iadd__(literal.as_string_slice())
- fn __iadd__(inout self, string: String) raises:
+ fn __iadd__(mut self, string: String) raises:
"""Appends another string to this string.
Args:
@@ -413,7 +412,7 @@ struct _FixedString[CAP: Int](
self.__iadd__(string.as_string_slice())
@always_inline
- fn __iadd__(inout self, str_slice: StringSlice[_]) raises:
+ fn __iadd__(mut self, str_slice: StringSlice[_]) raises:
"""Appends another string to this string.
Args:
@@ -439,7 +438,7 @@ struct _FixedString[CAP: Int](
# ===------------------------------------------------------------------=== #
fn _iadd_non_raising(
- inout self,
+ mut self,
bytes: Span[Byte, _],
) -> Optional[Error]:
var total_len = len(self) + len(bytes)
@@ -468,11 +467,11 @@ struct _FixedString[CAP: Int](
return None
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
writer.write_bytes(self.as_bytes())
@always_inline
- fn write_bytes(inout self, bytes: Span[Byte, _]):
+ fn write_bytes(mut self, bytes: Span[Byte, _]):
"""
Write a byte span to this String.
@@ -482,7 +481,7 @@ struct _FixedString[CAP: Int](
"""
_ = self._iadd_non_raising(bytes)
- fn write[*Ts: Writable](inout self, *args: *Ts):
+ fn write[*Ts: Writable](mut self, *args: *Ts):
"""Write a sequence of Writable arguments to the provided Writer.
Parameters:
diff --git a/stdlib/src/utils/lock.mojo b/stdlib/src/utils/lock.mojo
index 9737dc2178..6459952b4e 100644
--- a/stdlib/src/utils/lock.mojo
+++ b/stdlib/src/utils/lock.mojo
@@ -11,16 +11,16 @@
# limitations under the License.
# ===----------------------------------------------------------------------=== #
-from memory import UnsafePointer
from os import Atomic
-from time import sleep
from sys import external_call
from sys.ffi import OpaquePointer
+from time import sleep
+from memory import UnsafePointer
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# SpinWaiter
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
struct SpinWaiter:
@@ -65,7 +65,7 @@ struct BlockingSpinLock:
self.counter = Atomic[DType.int64](Self.UNLOCKED)
- fn lock(inout self, owner: Int):
+ fn lock(mut self, owner: Int):
"""Acquires the lock.
Args:
@@ -79,7 +79,7 @@ struct BlockingSpinLock:
waiter.wait()
expected = Self.UNLOCKED
- fn unlock(inout self, owner: Int) -> Bool:
+ fn unlock(mut self, owner: Int) -> Bool:
"""Releases the lock.
Args:
@@ -108,7 +108,7 @@ struct BlockingScopedLock:
"""The underlying lock instance."""
fn __init__(
- inout self,
+ mut self,
lock: UnsafePointer[Self.LockType],
):
"""Primary constructor.
@@ -120,8 +120,8 @@ struct BlockingScopedLock:
self.lock = lock
fn __init__(
- inout self,
- inout lock: Self.LockType,
+ mut self,
+ mut lock: Self.LockType,
):
"""Secondary constructor.
@@ -132,14 +132,14 @@ struct BlockingScopedLock:
self.lock = UnsafePointer.address_of(lock)
@no_inline
- fn __enter__(inout self):
+ fn __enter__(mut self):
"""Acquire the lock on entry.
This is done by setting the owner of the lock to own address."""
var address = UnsafePointer[Self].address_of(self)
self.lock[].lock(int(address))
@no_inline
- fn __exit__(inout self):
+ fn __exit__(mut self):
"""Release the lock on exit.
Reset the address on the underlying lock."""
var address = UnsafePointer[Self].address_of(self)
diff --git a/stdlib/src/utils/loop.mojo b/stdlib/src/utils/loop.mojo
index efef81a73f..1d61112379 100644
--- a/stdlib/src/utils/loop.mojo
+++ b/stdlib/src/utils/loop.mojo
@@ -11,7 +11,7 @@
# limitations under the License.
# ===----------------------------------------------------------------------=== #
-from builtin.range import _ZeroStartingRange, _SequentialRange, _StridedRange
+from builtin.range import _SequentialRange, _StridedRange, _ZeroStartingRange
"""Implements higher-order functions.
@@ -23,9 +23,9 @@ from utils import unroll
"""
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# unroll
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -51,9 +51,9 @@ fn unroll[
func[i, j]()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# unroll
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -84,9 +84,9 @@ fn unroll[
func[i, j, k]()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# unroll _ZeroStartingRange
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -125,9 +125,9 @@ fn unroll[
func[i]()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# unroll _SequentialRange
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
fn unroll[
func: fn[idx: Int] () capturing [_] -> None,
@@ -164,9 +164,9 @@ fn unroll[
func[i]()
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# unroll _StridedRange
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
fn unroll[
func: fn[idx: Int] () capturing [_] -> None,
diff --git a/stdlib/src/utils/numerics.mojo b/stdlib/src/utils/numerics.mojo
index 05db78d5f5..e1ec498345 100644
--- a/stdlib/src/utils/numerics.mojo
+++ b/stdlib/src/utils/numerics.mojo
@@ -67,9 +67,9 @@ struct FPUtils[
"""
@parameter
- if type is DType.float8e4m3:
+ if type in (DType.float8e4m3, DType.float8e4m3fnuz):
return 3
- elif type is DType.float8e5m2:
+ elif type in (DType.float8e5m2, DType.float8e5m2fnuz):
return 2
elif type is DType.float16:
return 10
@@ -84,48 +84,25 @@ struct FPUtils[
@staticmethod
@always_inline("nodebug")
fn max_exponent() -> IntLiteral:
- """Returns the max exponent of a floating point type, taking into
- account special reserved cases such infinity and nan.
+ """Returns the max exponent of a floating point type without accounting
+ for inf representations. This is not
+ the maximum representable exponent, which is generally equal to
+ the exponent_bias.
Returns:
The max exponent.
"""
@parameter
- if type is DType.float8e4m3:
- return 7
- elif type is DType.float8e5m2:
- return 15
- elif type is DType.float16:
- return 15
- elif type is DType.float32 or type is DType.bfloat16:
- return 127
- else:
- constrained[type is DType.float64, "unsupported float type"]()
- return 1023
-
- @staticmethod
- @always_inline("nodebug")
- fn min_exponent() -> IntLiteral:
- """Returns the min exponent of a floating point type, taking into
- account special reserved cases such as infinity and nan.
-
- Returns:
- The min exponent.
- """
-
- @parameter
- if type is DType.float8e4m3:
- return -6
- elif type is DType.float8e5m2:
- return -14
- elif type is DType.float16:
- return -14
- elif type is DType.float32 or type is DType.bfloat16:
- return -126
+ if type in (DType.float8e4m3, DType.float8e4m3fnuz):
+ return 8
+ elif type in (DType.float8e5m2, DType.float8e5m2fnuz, DType.float16):
+ return 16
+ elif type in (DType.bfloat16, DType.float32):
+ return 128
else:
constrained[type is DType.float64, "unsupported float type"]()
- return -1022
+ return 1024
@staticmethod
@always_inline("nodebug")
@@ -137,13 +114,11 @@ struct FPUtils[
"""
@parameter
- if type is DType.float8e4m3:
+ if type in (DType.float8e4m3, DType.float8e4m3fnuz):
return 4
- elif type is DType.float8e5m2:
+ elif type in (DType.float8e5m2, DType.float8e5m2fnuz, DType.float16):
return 5
- elif type is DType.float16:
- return 5
- elif type is DType.float32 or type is DType.bfloat16:
+ elif type in (DType.float32, DType.bfloat16):
return 8
else:
constrained[type is DType.float64, "unsupported float type"]()
@@ -167,7 +142,12 @@ struct FPUtils[
Returns:
The exponent bias.
"""
- return Self.max_exponent()
+
+ @parameter
+ if type in (DType.float8e4m3fnuz, DType.float8e5m2fnuz):
+ return Self.max_exponent()
+ else:
+ return Self.max_exponent() - 1
@staticmethod
@always_inline
@@ -313,14 +293,15 @@ struct FPUtils[
@staticmethod
@always_inline
- fn get_exponent_without_bias(value: Scalar[type]) -> Int:
- """Returns the exponent bits of the floating-point value.
+ fn get_exponent_biased(value: Scalar[type]) -> Int:
+ """Returns the biased exponent of the floating-point value as an Int,
+ this is how the value is stored before subtracting the exponent bias.
Args:
value: The floating-point value.
Returns:
- Returns the exponent bits.
+ The biased exponent as an Int.
"""
return int(
Self.bitcast_to_uint(value) >> Self.mantissa_width()
@@ -537,6 +518,15 @@ fn nan[type: DType]() -> Scalar[type]:
value = __mlir_attr[`#pop.simd<"nan"> : !pop.scalar`],
]()
)
+ elif type is DType.float8e5m2fnuz:
+ return rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
+ __mlir_op.`kgen.param.constant`[
+ _type = __mlir_type[`!pop.scalar`],
+ value = __mlir_attr[
+ `#pop.simd<"nan"> : !pop.scalar`
+ ],
+ ]()
+ )
elif type is DType.float8e4m3:
return rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
__mlir_op.`kgen.param.constant`[
@@ -544,6 +534,15 @@ fn nan[type: DType]() -> Scalar[type]:
value = __mlir_attr[`#pop.simd<"nan"> : !pop.scalar`],
]()
)
+ elif type is DType.float8e4m3fnuz:
+ return rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
+ __mlir_op.`kgen.param.constant`[
+ _type = __mlir_type[`!pop.scalar`],
+ value = __mlir_attr[
+ `#pop.simd<"nan"> : !pop.scalar`
+ ],
+ ]()
+ )
elif type is DType.float16:
return rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
__mlir_op.`kgen.param.constant`[
@@ -600,7 +599,10 @@ fn isnan[
"""
@parameter
- if not type.is_floating_point():
+ if not type.is_floating_point() or type in (
+ DType.float8e4m3fnuz,
+ DType.float8e5m2fnuz,
+ ):
return False
alias int_dtype = _integral_type_of[type]()
@@ -654,6 +656,15 @@ fn inf[type: DType]() -> Scalar[type]:
value = __mlir_attr[`#pop.simd<"inf"> : !pop.scalar`],
]()
)
+ elif type is DType.float8e5m2fnuz:
+ return rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
+ __mlir_op.`kgen.param.constant`[
+ _type = __mlir_type[`!pop.scalar`],
+ value = __mlir_attr[
+ `#pop.simd<"inf"> : !pop.scalar`
+ ],
+ ]()
+ )
elif type is DType.float8e4m3:
return rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
__mlir_op.`kgen.param.constant`[
@@ -661,6 +672,15 @@ fn inf[type: DType]() -> Scalar[type]:
value = __mlir_attr[`#pop.simd<"inf"> : !pop.scalar`],
]()
)
+ elif type is DType.float8e4m3fnuz:
+ return rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
+ __mlir_op.`kgen.param.constant`[
+ _type = __mlir_type[`!pop.scalar`],
+ value = __mlir_attr[
+ `#pop.simd<"inf"> : !pop.scalar`
+ ],
+ ]()
+ )
elif type is DType.float16:
return rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
__mlir_op.`kgen.param.constant`[
@@ -721,6 +741,15 @@ fn neg_inf[type: DType]() -> Scalar[type]:
value = __mlir_attr[`#pop.simd<"-inf"> : !pop.scalar`],
]()
)
+ elif type is DType.float8e5m2fnuz:
+ return rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
+ __mlir_op.`kgen.param.constant`[
+ _type = __mlir_type[`!pop.scalar`],
+ value = __mlir_attr[
+ `#pop.simd<"-inf"> : !pop.scalar`
+ ],
+ ]()
+ )
elif type is DType.float8e4m3:
return rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
__mlir_op.`kgen.param.constant`[
@@ -728,6 +757,15 @@ fn neg_inf[type: DType]() -> Scalar[type]:
value = __mlir_attr[`#pop.simd<"-inf"> : !pop.scalar`],
]()
)
+ elif type is DType.float8e4m3fnuz:
+ return rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
+ __mlir_op.`kgen.param.constant`[
+ _type = __mlir_type[`!pop.scalar`],
+ value = __mlir_attr[
+ `#pop.simd<"-inf"> : !pop.scalar`
+ ],
+ ]()
+ )
elif type is DType.float16:
return rebind[__mlir_type[`!pop.scalar<`, type.value, `>`]](
__mlir_op.`kgen.param.constant`[
@@ -801,7 +839,9 @@ fn max_finite[type: DType]() -> Scalar[type]:
return 18446744073709551615
elif type is DType.float8e4m3:
return 448
- elif type is DType.float8e5m2:
+ elif type is DType.float8e4m3fnuz:
+ return 240
+ elif type in (DType.float8e5m2, DType.float8e5m2fnuz):
return 57344
elif type is DType.float16:
return 65504
@@ -932,9 +972,11 @@ fn isinf[
"""
@parameter
- if not type.is_floating_point():
+ if not type.is_floating_point() or type in (
+ DType.float8e4m3fnuz,
+ DType.float8e5m2fnuz,
+ ):
return False
-
elif type is DType.float8e5m2:
# For the float8e5m2 both 7C and FC are infinity.
alias int_dtype = _integral_type_of[type]()
@@ -1001,7 +1043,9 @@ fn get_accum_type[type: DType]() -> DType:
DType.float32 if type is a half-precision float, type otherwise.
"""
- return DType.float32 if type.is_half_float() else type
+ return DType.float32 if (
+ type.is_half_float() or type in (DType.float8e4m3, DType.float8e5m2)
+ ) else type
# ===----------------------------------------------------------------------=== #
@@ -1085,10 +1129,11 @@ fn ulp[
constrained[type.is_floating_point(), "the type must be floating point"]()
+ alias inf_val = SIMD[type, simd_width](inf[type]())
+
var nan_mask = isnan(x)
var xabs = abs(x)
var inf_mask = isinf(xabs)
- alias inf_val = SIMD[type, simd_width](inf[type]())
var x2 = nextafter(xabs, inf_val)
var x2_inf_mask = isinf(x2)
diff --git a/stdlib/src/utils/static_tuple.mojo b/stdlib/src/utils/static_tuple.mojo
index 9a14c36e24..0788b54b43 100644
--- a/stdlib/src/utils/static_tuple.mojo
+++ b/stdlib/src/utils/static_tuple.mojo
@@ -21,9 +21,9 @@ from utils import StaticTuple
from memory import UnsafePointer
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Utilities
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
@@ -93,9 +93,9 @@ fn _create_array[
return array
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# StaticTuple
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
fn _static_tuple_construction_checks[size: Int]():
@@ -218,20 +218,15 @@ struct StaticTuple[element_type: AnyTrivialRegType, size: Int](Sized):
debug_assert(
int(idx.__mlir_index__()) < size, "index must be within bounds"
)
- # Copy the array so we can get its address, because we can't take the
- # address of 'self' in a non-mutating method.
- var arrayCopy = self.array
var ptr = __mlir_op.`pop.array.gep`(
- UnsafePointer.address_of(arrayCopy).address, idx.__mlir_index__()
+ UnsafePointer.address_of(self.array).address, idx.__mlir_index__()
)
- var result = UnsafePointer(ptr)[]
- _ = arrayCopy
- return result
+ return UnsafePointer(ptr)[]
@always_inline("nodebug")
fn __setitem__[
IntLike: IntLike, //
- ](inout self, idx: IntLike, val: Self.element_type):
+ ](mut self, idx: IntLike, val: Self.element_type):
"""Stores a single value into the tuple at the specified dynamic index.
Parameters:
@@ -252,7 +247,7 @@ struct StaticTuple[element_type: AnyTrivialRegType, size: Int](Sized):
self = tmp
@always_inline("nodebug")
- fn __setitem__[index: Int](inout self, val: Self.element_type):
+ fn __setitem__[index: Int](mut self, val: Self.element_type):
"""Stores a single value into the tuple at the specified index.
Parameters:
@@ -262,6 +257,4 @@ struct StaticTuple[element_type: AnyTrivialRegType, size: Int](Sized):
val: The value to store.
"""
constrained[index < size]()
- var tmp = self
- _set_array_elem[index, size, Self.element_type](val, tmp.array)
- self = tmp
+ _set_array_elem[index, size, Self.element_type](val, self.array)
diff --git a/stdlib/src/utils/string_slice.mojo b/stdlib/src/utils/string_slice.mojo
index 62ec51878b..a61ed5d13a 100644
--- a/stdlib/src/utils/string_slice.mojo
+++ b/stdlib/src/utils/string_slice.mojo
@@ -10,7 +10,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# ===----------------------------------------------------------------------=== #
-
"""Implements the StringSlice type.
You can import these APIs from the `utils.string_slice` module.
@@ -22,14 +21,17 @@ from utils import StringSlice
```
"""
-from bit import count_leading_zeros
-from utils import Span
-from collections.string import _isspace, _atol, _atof
from collections import List, Optional
-from memory import memcmp, UnsafePointer, memcpy
-from sys import simdwidthof, bitwidthof
+from collections.string import _atof, _atol, _isspace
+from sys import bitwidthof, simdwidthof
from sys.intrinsics import unlikely
+
+from bit import count_leading_zeros
+from memory import UnsafePointer, memcmp, memcpy, Span
from memory.memory import _memcmp_impl_unconstrained
+
+from utils.format import _CurlyEntryFormattable, _FormatCurlyEntry
+
from ._utf8_validation import _is_valid_utf8
alias StaticString = StringSlice[StaticConstantOrigin]
@@ -77,13 +79,9 @@ fn _utf8_first_byte_sequence_length(b: Byte) -> Int:
debug_assert(
(b & 0b1100_0000) != 0b1000_0000,
- (
- "Function `_utf8_first_byte_sequence_length()` does not work"
- " correctly if given a continuation byte."
- ),
+ "Function does not work correctly if given a continuation byte.",
)
- var flipped = ~b
- return int(count_leading_zeros(flipped) + (flipped >> 7))
+ return int(count_leading_zeros(~b)) + int(b < 0b1000_0000)
fn _shift_unicode_to_utf8(ptr: UnsafePointer[UInt8], c: Int, num_bytes: Int):
@@ -171,7 +169,7 @@ fn _memrmem[
@value
struct _StringSliceIter[
is_mutable: Bool, //,
- origin: Origin[is_mutable].type,
+ origin: Origin[is_mutable],
forward: Bool = True,
]:
"""Iterator for `StringSlice` over unicode characters.
@@ -183,46 +181,28 @@ struct _StringSliceIter[
"""
var index: Int
- var continuation_bytes: Int
- var ptr: UnsafePointer[UInt8]
+ var ptr: UnsafePointer[Byte]
var length: Int
- fn __init__(
- inout self, *, unsafe_pointer: UnsafePointer[UInt8], length: Int
- ):
+ fn __init__(mut self, *, unsafe_pointer: UnsafePointer[Byte], length: Int):
self.index = 0 if forward else length
self.ptr = unsafe_pointer
self.length = length
- alias S = Span[Byte, StaticConstantOrigin]
- var s = S(ptr=self.ptr, length=self.length)
- self.continuation_bytes = _count_utf8_continuation_bytes(s)
fn __iter__(self) -> Self:
return self
- fn __next__(inout self) -> StringSlice[origin]:
+ fn __next__(mut self) -> StringSlice[origin]:
@parameter
if forward:
- var byte_len = 1
- if self.continuation_bytes > 0:
- var byte_type = _utf8_byte_type(self.ptr[self.index])
- if byte_type != 0:
- byte_len = int(byte_type)
- self.continuation_bytes -= byte_len - 1
+ byte_len = _utf8_first_byte_sequence_length(self.ptr[self.index])
+ i = self.index
self.index += byte_len
- return StringSlice[origin](
- ptr=self.ptr + (self.index - byte_len), length=byte_len
- )
+ return StringSlice[origin](ptr=self.ptr + i, length=byte_len)
else:
- var byte_len = 1
- if self.continuation_bytes > 0:
- var byte_type = _utf8_byte_type(self.ptr[self.index - 1])
- if byte_type != 0:
- while byte_type == 1:
- byte_len += 1
- var b = self.ptr[self.index - byte_len]
- byte_type = _utf8_byte_type(b)
- self.continuation_bytes -= byte_len - 1
+ byte_len = 1
+ while _utf8_byte_type(self.ptr[self.index - byte_len]) == 1:
+ byte_len += 1
self.index -= byte_len
return StringSlice[origin](
ptr=self.ptr + self.index, length=byte_len
@@ -230,19 +210,31 @@ struct _StringSliceIter[
@always_inline
fn __has_next__(self) -> Bool:
- return self.__len__() > 0
+ @parameter
+ if forward:
+ return self.index < self.length
+ else:
+ return self.index > 0
fn __len__(self) -> Int:
@parameter
if forward:
- return self.length - self.index - self.continuation_bytes
+ remaining = self.length - self.index
+ cont = _count_utf8_continuation_bytes(
+ Span[Byte, ImmutableAnyOrigin](
+ ptr=self.ptr + self.index, length=remaining
+ )
+ )
+ return remaining - cont
else:
- return self.index - self.continuation_bytes
+ return self.index - _count_utf8_continuation_bytes(
+ Span[Byte, ImmutableAnyOrigin](ptr=self.ptr, length=self.index)
+ )
@value
@register_passable("trivial")
-struct StringSlice[is_mutable: Bool, //, origin: Origin[is_mutable].type,](
+struct StringSlice[is_mutable: Bool, //, origin: Origin[is_mutable]](
Stringable,
Sized,
Writable,
@@ -353,7 +345,7 @@ struct StringSlice[is_mutable: Bool, //, origin: Origin[is_mutable].type,](
@implicit
fn __init__[
O: ImmutableOrigin, //
- ](inout self: StringSlice[O], ref [O]value: String):
+ ](mut self: StringSlice[O], ref [O]value: String):
"""Construct an immutable StringSlice.
Parameters:
@@ -392,7 +384,7 @@ struct StringSlice[is_mutable: Bool, //, origin: Origin[is_mutable].type,](
var s = S(ptr=self.unsafe_ptr(), length=b_len)
return b_len - _count_utf8_continuation_bytes(s)
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""Formats this string slice to the provided `Writer`.
Parameters:
@@ -623,13 +615,33 @@ struct StringSlice[is_mutable: Bool, //, origin: Origin[is_mutable].type,](
# ===------------------------------------------------------------------===#
@always_inline
- fn strip(self) -> StringSlice[origin]:
- """Gets a StringRef with leading and trailing whitespaces removed.
- This only takes ASCII whitespace into account:
- `" \\t\\n\\v\\f\\r\\x1c\\x1d\\x1e"`.
+ fn strip(self, chars: StringSlice) -> Self:
+ """Return a copy of the string with leading and trailing characters
+ removed.
+
+ Args:
+ chars: A set of characters to be removed. Defaults to whitespace.
Returns:
- A StringRef with leading and trailing whitespaces removed.
+ A copy of the string with no leading or trailing characters.
+
+ Examples:
+
+ ```mojo
+ print("himojohi".strip("hi")) # "mojo"
+ ```
+ .
+ """
+
+ return self.lstrip(chars).rstrip(chars)
+
+ @always_inline
+ fn strip(self) -> Self:
+ """Return a copy of the string with leading and trailing whitespaces
+ removed.
+
+ Returns:
+ A copy of the string with no leading or trailing whitespaces.
Examples:
@@ -638,15 +650,103 @@ struct StringSlice[is_mutable: Bool, //, origin: Origin[is_mutable].type,](
```
.
"""
- # FIXME: this can already do full isspace support with iterator
- var start: Int = 0
- var end: Int = len(self)
- var ptr = self.unsafe_ptr()
- while start < end and _isspace(ptr[start]):
- start += 1
- while end > start and _isspace(ptr[end - 1]):
- end -= 1
- return StringSlice[origin](ptr=ptr + start, length=end - start)
+ return self.lstrip().rstrip()
+
+ @always_inline
+ fn rstrip(self, chars: StringSlice) -> Self:
+ """Return a copy of the string with trailing characters removed.
+
+ Args:
+ chars: A set of characters to be removed. Defaults to whitespace.
+
+ Returns:
+ A copy of the string with no trailing characters.
+
+ Examples:
+
+ ```mojo
+ print("mojohi".strip("hi")) # "mojo"
+ ```
+ .
+ """
+
+ var r_idx = self.byte_length()
+ while r_idx > 0 and self[r_idx - 1] in chars:
+ r_idx -= 1
+
+ return Self(unsafe_from_utf8=self.as_bytes()[:r_idx])
+
+ @always_inline
+ fn rstrip(self) -> Self:
+ """Return a copy of the string with trailing whitespaces removed.
+
+ Returns:
+ A copy of the string with no trailing whitespaces.
+
+ Examples:
+
+ ```mojo
+ print("mojo ".strip()) # "mojo"
+ ```
+ .
+ """
+ var r_idx = self.byte_length()
+ # TODO (#933): should use this once llvm intrinsics can be used at comp time
+ # for s in self.__reversed__():
+ # if not s.isspace():
+ # break
+ # r_idx -= 1
+ while r_idx > 0 and _isspace(self.as_bytes()[r_idx - 1]):
+ r_idx -= 1
+ return Self(unsafe_from_utf8=self.as_bytes()[:r_idx])
+
+ @always_inline
+ fn lstrip(self, chars: StringSlice) -> Self:
+ """Return a copy of the string with leading characters removed.
+
+ Args:
+ chars: A set of characters to be removed. Defaults to whitespace.
+
+ Returns:
+ A copy of the string with no leading characters.
+
+ Examples:
+
+ ```mojo
+ print("himojo".strip("hi")) # "mojo"
+ ```
+ .
+ """
+
+ var l_idx = 0
+ while l_idx < self.byte_length() and self[l_idx] in chars:
+ l_idx += 1
+
+ return Self(unsafe_from_utf8=self.as_bytes()[l_idx:])
+
+ @always_inline
+ fn lstrip(self) -> Self:
+ """Return a copy of the string with leading whitespaces removed.
+
+ Returns:
+ A copy of the string with no leading whitespaces.
+
+ Examples:
+
+ ```mojo
+ print(" mojo".strip()) # "mojo"
+ ```
+ .
+ """
+ var l_idx = 0
+ # TODO (#933): should use this once llvm intrinsics can be used at comp time
+ # for s in self:
+ # if not s.isspace():
+ # break
+ # l_idx += 1
+ while l_idx < self.byte_length() and _isspace(self.as_bytes()[l_idx]):
+ l_idx += 1
+ return Self(unsafe_from_utf8=self.as_bytes()[l_idx:])
@always_inline
fn as_bytes(self) -> Span[Byte, origin]:
@@ -1017,33 +1117,9 @@ struct StringSlice[is_mutable: Bool, //, origin: Origin[is_mutable].type,](
return output^
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Utils
-# ===----------------------------------------------------------------------===#
-
-
-trait Stringlike:
- """Trait intended to be used only with `String`, `StringLiteral` and
- `StringSlice`."""
-
- fn byte_length(self) -> Int:
- """Get the string length in bytes.
-
- Returns:
- The length of this string in bytes.
-
- Notes:
- This does not include the trailing null terminator in the count.
- """
- ...
-
- fn unsafe_ptr(self) -> UnsafePointer[UInt8]:
- """Get raw pointer to the underlying data.
-
- Returns:
- The raw pointer to the data.
- """
- ...
+# ===-----------------------------------------------------------------------===#
fn __iter__(ref [_]self) -> _StringSliceIter[__origin_of(self)]:
"""Iterate over the string unicode characters.
@@ -1131,613 +1207,3 @@ fn _to_string_list[
return len(v)
return _to_string_list[items.T, len_fn, unsafe_ptr_fn](items)
-
-
-# ===----------------------------------------------------------------------===#
-# Format method structures
-# ===----------------------------------------------------------------------===#
-
-
-trait _CurlyEntryFormattable(Stringable, Representable):
- """This trait is used by the `format()` method to support format specifiers.
- Currently, it is a composition of both `Stringable` and `Representable`
- traits i.e. a type to be formatted must implement both. In the future this
- will be less constrained.
- """
-
- ...
-
-
-@value
-struct _FormatCurlyEntry(CollectionElement, CollectionElementNew):
- """The struct that handles `Stringlike` formatting by curly braces entries.
- This is internal for the types: `String`, `StringLiteral` and `StringSlice`.
- """
-
- var first_curly: Int
- """The index of an opening brace around a substitution field."""
- var last_curly: Int
- """The index of a closing brace around a substitution field."""
- # TODO: ord("a") conversion flag not supported yet
- var conversion_flag: UInt8
- """The type of conversion for the entry: {ord("s"), ord("r")}."""
- var format_spec: Optional[_FormatSpec]
- """The format specifier."""
- # TODO: ord("a") conversion flag not supported yet
- alias supported_conversion_flags = SIMD[DType.uint8, 2](ord("s"), ord("r"))
- """Currently supported conversion flags: `__str__` and `__repr__`."""
- alias _FieldVariantType = Variant[String, Int, NoneType, Bool]
- """Purpose of the `Variant` `Self.field`:
-
- - `Int` for manual indexing: (value field contains `0`).
- - `NoneType` for automatic indexing: (value field contains `None`).
- - `String` for **kwargs indexing: (value field contains `foo`).
- - `Bool` for escaped curlies: (value field contains False for `{` or True
- for `}`).
- """
- var field: Self._FieldVariantType
- """Store the substitution field. See `Self._FieldVariantType` docstrings for
- more details."""
- alias _args_t = VariadicPack[element_trait=_CurlyEntryFormattable, *_]
- """Args types that are formattable by curly entry."""
-
- fn __init__(out self, *, other: Self):
- self.first_curly = other.first_curly
- self.last_curly = other.last_curly
- self.conversion_flag = other.conversion_flag
- self.field = Self._FieldVariantType(other=other.field)
- self.format_spec = other.format_spec
-
- fn __init__(
- inout self,
- first_curly: Int,
- last_curly: Int,
- field: Self._FieldVariantType,
- conversion_flag: UInt8 = 0,
- format_spec: Optional[_FormatSpec] = None,
- ):
- self.first_curly = first_curly
- self.last_curly = last_curly
- self.field = field
- self.conversion_flag = conversion_flag
- self.format_spec = format_spec
-
- @always_inline
- fn is_escaped_brace(ref self) -> Bool:
- return self.field.isa[Bool]()
-
- @always_inline
- fn is_kwargs_field(ref self) -> Bool:
- return self.field.isa[String]()
-
- @always_inline
- fn is_automatic_indexing(ref self) -> Bool:
- return self.field.isa[NoneType]()
-
- @always_inline
- fn is_manual_indexing(ref self) -> Bool:
- return self.field.isa[Int]()
-
- @staticmethod
- fn format[T: Stringlike](fmt_src: T, args: Self._args_t) raises -> String:
- alias len_pos_args = __type_of(args).__len__()
- entries, size_estimation = Self._create_entries(fmt_src, len_pos_args)
- var fmt_len = fmt_src.byte_length()
- var buf = String._buffer_type(capacity=fmt_len + size_estimation)
- buf.size = 1
- buf.unsafe_set(0, 0)
- var res = String(buf^)
- var offset = 0
- var ptr = fmt_src.unsafe_ptr()
- alias S = StringSlice[StaticConstantOrigin]
-
- @always_inline("nodebug")
- fn _build_slice(p: UnsafePointer[UInt8], start: Int, end: Int) -> S:
- return S(ptr=p + start, length=end - start)
-
- var auto_arg_index = 0
- for e in entries:
- debug_assert(offset < fmt_len, "offset >= fmt_src.byte_length()")
- res += _build_slice(ptr, offset, e[].first_curly)
- e[]._format_entry[len_pos_args](res, args, auto_arg_index)
- offset = e[].last_curly + 1
-
- res += _build_slice(ptr, offset, fmt_len)
- return res^
-
- @staticmethod
- fn _create_entries[
- T: Stringlike
- ](fmt_src: T, len_pos_args: Int) raises -> (List[Self], Int):
- """Returns a list of entries and its total estimated entry byte width.
- """
- var manual_indexing_count = 0
- var automatic_indexing_count = 0
- var raised_manual_index = Optional[Int](None)
- var raised_automatic_index = Optional[Int](None)
- var raised_kwarg_field = Optional[String](None)
- alias `}` = UInt8(ord("}"))
- alias `{` = UInt8(ord("{"))
- alias l_err = "there is a single curly { left unclosed or unescaped"
- alias r_err = "there is a single curly } left unclosed or unescaped"
-
- var entries = List[Self]()
- var start = Optional[Int](None)
- var skip_next = False
- var fmt_ptr = fmt_src.unsafe_ptr()
- var fmt_len = fmt_src.byte_length()
- var total_estimated_entry_byte_width = 0
-
- for i in range(fmt_len):
- if skip_next:
- skip_next = False
- continue
- if fmt_ptr[i] == `{`:
- if not start:
- start = i
- continue
- if i - start.value() != 1:
- raise Error(l_err)
- # python escapes double curlies
- entries.append(Self(start.value(), i, field=False))
- start = None
- continue
- elif fmt_ptr[i] == `}`:
- if not start and (i + 1) < fmt_len:
- # python escapes double curlies
- if fmt_ptr[i + 1] == `}`:
- entries.append(Self(i, i + 1, field=True))
- total_estimated_entry_byte_width += 2
- skip_next = True
- continue
- elif not start: # if it is not an escaped one, it is an error
- raise Error(r_err)
-
- var start_value = start.value()
- var current_entry = Self(start_value, i, field=NoneType())
-
- if i - start_value != 1:
- if current_entry._handle_field_and_break(
- fmt_src,
- len_pos_args,
- i,
- start_value,
- automatic_indexing_count,
- raised_automatic_index,
- manual_indexing_count,
- raised_manual_index,
- raised_kwarg_field,
- total_estimated_entry_byte_width,
- ):
- break
- else: # automatic indexing
- if automatic_indexing_count >= len_pos_args:
- raised_automatic_index = automatic_indexing_count
- break
- automatic_indexing_count += 1
- total_estimated_entry_byte_width += 8 # guessing
- entries.append(current_entry^)
- start = None
-
- if raised_automatic_index:
- raise Error("Automatic indexing require more args in *args")
- elif raised_kwarg_field:
- var val = raised_kwarg_field.value()
- raise Error("Index " + val + " not in kwargs")
- elif manual_indexing_count and automatic_indexing_count:
- raise Error("Cannot both use manual and automatic indexing")
- elif raised_manual_index:
- var val = str(raised_manual_index.value())
- raise Error("Index " + val + " not in *args")
- elif start:
- raise Error(l_err)
- return entries^, total_estimated_entry_byte_width
-
- fn _handle_field_and_break[
- T: Stringlike
- ](
- inout self,
- fmt_src: T,
- len_pos_args: Int,
- i: Int,
- start_value: Int,
- inout automatic_indexing_count: Int,
- inout raised_automatic_index: Optional[Int],
- inout manual_indexing_count: Int,
- inout raised_manual_index: Optional[Int],
- inout raised_kwarg_field: Optional[String],
- inout total_estimated_entry_byte_width: Int,
- ) raises -> Bool:
- alias S = StringSlice[StaticConstantOrigin]
-
- @always_inline("nodebug")
- fn _build_slice(p: UnsafePointer[UInt8], start: Int, end: Int) -> S:
- return S(ptr=p + start, length=end - start)
-
- var field = _build_slice(fmt_src.unsafe_ptr(), start_value + 1, i)
- var field_ptr = field.unsafe_ptr()
- var field_len = i - (start_value + 1)
- var exclamation_index = -1
- var idx = 0
- while idx < field_len:
- if field_ptr[idx] == ord("!"):
- exclamation_index = idx
- break
- idx += 1
- var new_idx = exclamation_index + 1
- if exclamation_index != -1:
- if new_idx == field_len:
- raise Error("Empty conversion flag.")
- var conversion_flag = field_ptr[new_idx]
- if field_len - new_idx > 1 or (
- conversion_flag not in Self.supported_conversion_flags
- ):
- var f = String(_build_slice(field_ptr, new_idx, field_len))
- _ = field
- raise Error('Conversion flag "' + f + '" not recognised.')
- self.conversion_flag = conversion_flag
- field = _build_slice(field_ptr, 0, exclamation_index)
- else:
- new_idx += 1
-
- var extra = int(new_idx < field_len)
- var fmt_field = _build_slice(field_ptr, new_idx + extra, field_len)
- self.format_spec = _FormatSpec.parse(fmt_field)
- var w = int(self.format_spec.value().width) if self.format_spec else 0
- # fully guessing the byte width here to be at least 8 bytes per entry
- # minus the length of the whole format specification
- total_estimated_entry_byte_width += 8 * int(w > 0) + w - (field_len + 2)
-
- if field.byte_length() == 0:
- # an empty field, so it's automatic indexing
- if automatic_indexing_count >= len_pos_args:
- raised_automatic_index = automatic_indexing_count
- return True
- automatic_indexing_count += 1
- else:
- try:
- # field is a number for manual indexing:
- var number = int(field)
- self.field = number
- if number >= len_pos_args or number < 0:
- raised_manual_index = number
- return True
- manual_indexing_count += 1
- except e:
- alias unexp = "Not the expected error from atol"
- debug_assert("not convertible to integer" in str(e), unexp)
- # field is a keyword for **kwargs:
- var f = str(field)
- self.field = f
- raised_kwarg_field = f
- return True
- return False
-
- fn _format_entry[
- len_pos_args: Int
- ](self, inout res: String, args: Self._args_t, inout auto_idx: Int) raises:
- # TODO(#3403 and/or #3252): this function should be able to use
- # Formatter syntax when the type implements it, since it will give great
- # performance benefits. This also needs to be able to check if the given
- # args[i] conforms to the trait needed by the conversion_flag to avoid
- # needing to constraint that every type needs to conform to every trait.
- alias `r` = UInt8(ord("r"))
- alias `s` = UInt8(ord("s"))
- # alias `a` = UInt8(ord("a")) # TODO
-
- @parameter
- fn _format(idx: Int) raises:
- @parameter
- for i in range(len_pos_args):
- if i == idx:
- var type_impls_repr = True # TODO
- var type_impls_str = True # TODO
- var type_impls_formatter_repr = True # TODO
- var type_impls_formatter_str = True # TODO
- var flag = self.conversion_flag
- var empty = flag == 0 and not self.format_spec
-
- var data: String
- if empty and type_impls_formatter_str:
- data = str(args[i]) # TODO: use writer and return
- elif empty and type_impls_str:
- data = str(args[i])
- elif flag == `s` and type_impls_formatter_str:
- if empty:
- # TODO: use writer and return
- pass
- data = str(args[i])
- elif flag == `s` and type_impls_str:
- data = str(args[i])
- elif flag == `r` and type_impls_formatter_repr:
- if empty:
- # TODO: use writer and return
- pass
- data = repr(args[i])
- elif flag == `r` and type_impls_repr:
- data = repr(args[i])
- elif self.format_spec:
- self.format_spec.value().stringify(res, args[i])
- return
- else:
- alias argnum = "Argument number: "
- alias does_not = " does not implement the trait "
- alias needed = "needed for conversion_flag: "
- var flg = String(List[UInt8](flag, 0))
- raise Error(argnum + str(i) + does_not + needed + flg)
-
- if self.format_spec:
- self.format_spec.value().format_string(res, data)
- else:
- res += data
-
- if self.is_escaped_brace():
- res += "}" if self.field[Bool] else "{"
- elif self.is_manual_indexing():
- _format(self.field[Int])
- elif self.is_automatic_indexing():
- _format(auto_idx)
- auto_idx += 1
-
-
-@value
-@register_passable("trivial")
-struct _FormatSpec:
- """Store every field of the format specifier in a byte (e.g., ord("+") for
- sign). It is stored in a byte because every [format specifier](
- https://docs.python.org/3/library/string.html#formatspec) is an ASCII
- character.
- """
-
- var fill: UInt8
- """If a valid align value is specified, it can be preceded by a fill
- character that can be any character and defaults to a space if omitted.
- """
- var align: UInt8
- """The meaning of the various alignment options is as follows:
-
- | Option | Meaning|
- |:------:|:-------|
- |'<' | Forces the field to be left-aligned within the available space \
- (this is the default for most objects).|
- |'>' | Forces the field to be right-aligned within the available space \
- (this is the default for numbers).|
- |'=' | Forces the padding to be placed after the sign (if any) but before \
- the digits. This is used for printing fields in the form `+000000120`. This\
- alignment option is only valid for numeric types. It becomes the default\
- for numbers when `0` immediately precedes the field width.|
- |'^' | Forces the field to be centered within the available space.|
- """
- var sign: UInt8
- """The sign option is only valid for number types, and can be one of the
- following:
-
- | Option | Meaning|
- |:------:|:-------|
- |'+' | indicates that a sign should be used for both positive as well as\
- negative numbers.|
- |'-' | indicates that a sign should be used only for negative numbers (this\
- is the default behavior).|
- |space | indicates that a leading space should be used on positive numbers,\
- and a minus sign on negative numbers.|
- """
- var coerce_z: Bool
- """The 'z' option coerces negative zero floating-point values to positive
- zero after rounding to the format precision. This option is only valid for
- floating-point presentation types.
- """
- var alternate_form: Bool
- """The alternate form is defined differently for different types. This
- option is only valid for types that implement the trait `# TODO: define
- trait`. For integers, when binary, octal, or hexadecimal output is used,
- this option adds the respective prefix '0b', '0o', '0x', or '0X' to the
- output value. For float and complex the alternate form causes the result of
- the conversion to always contain a decimal-point character, even if no
- digits follow it.
- """
- var width: UInt8
- """A decimal integer defining the minimum total field width, including any
- prefixes, separators, and other formatting characters. If not specified,
- then the field width will be determined by the content. When no explicit
- alignment is given, preceding the width field by a zero ('0') character
- enables sign-aware zero-padding for numeric types. This is equivalent to a
- fill character of '0' with an alignment type of '='.
- """
- var grouping_option: UInt8
- """The ',' option signals the use of a comma for a thousands separator. For
- a locale aware separator, use the 'n' integer presentation type instead. The
- '_' option signals the use of an underscore for a thousands separator for
- floating-point presentation types and for integer presentation type 'd'. For
- integer presentation types 'b', 'o', 'x', and 'X', underscores will be
- inserted every 4 digits. For other presentation types, specifying this
- option is an error.
- """
- var precision: UInt8
- """The precision is a decimal integer indicating how many digits should be
- displayed after the decimal point for presentation types 'f' and 'F', or
- before and after the decimal point for presentation types 'g' or 'G'. For
- string presentation types the field indicates the maximum field size - in
- other words, how many characters will be used from the field content. The
- precision is not allowed for integer presentation types.
- """
- var type: UInt8
- """Determines how the data should be presented.
-
- The available integer presentation types are:
-
- | Option | Meaning|
- |:------:|:-------|
- |'b' |Binary format. Outputs the number in base 2.|
- |'c' |Character. Converts the integer to the corresponding unicode\
- character before printing.|
- |'d' |Decimal Integer. Outputs the number in base 10.|
- |'o' |Octal format. Outputs the number in base 8.|
- |'x' |Hex format. Outputs the number in base 16, using lower-case letters\
- for the digits above 9.|
- |'X' |Hex format. Outputs the number in base 16, using upper-case letters\
- for the digits above 9. In case '#' is specified, the prefix '0x' will be\
- upper-cased to '0X' as well.|
- |'n' |Number. This is the same as 'd', except that it uses the current\
- locale setting to insert the appropriate number separator characters.|
- |None | The same as 'd'.|
-
- In addition to the above presentation types, integers can be formatted with
- the floating-point presentation types listed below (except 'n' and None).
- When doing so, float() is used to convert the integer to a floating-point
- number before formatting.
-
- The available presentation types for float and Decimal values are:
-
- | Option | Meaning|
- |:------:|:-------|
- |'e' |Scientific notation. For a given precision p, formats the number in\
- scientific notation with the letter `e` separating the coefficient from the\
- exponent. The coefficient has one digit before and p digits after the\
- decimal point, for a total of p + 1 significant digits. With no precision\
- given, uses a precision of 6 digits after the decimal point for float, and\
- shows all coefficient digits for Decimal. If no digits follow the decimal\
- point, the decimal point is also removed unless the # option is used.|
- |'E' |Scientific notation. Same as 'e' except it uses an upper case `E` as\
- the separator character.|
- |'f' |Fixed-point notation. For a given precision p, formats the number as\
- a decimal number with exactly p digits following the decimal point. With no\
- precision given, uses a precision of 6 digits after the decimal point for\
- float, and uses a precision large enough to show all coefficient digits for\
- Decimal. If no digits follow the decimal point, the decimal point is also\
- removed unless the '#' option is used.|
- |'F' |Fixed-point notation. Same as 'f', but converts nan to NAN and inf to\
- INF.|
- |'g' |General format. For a given precision p >= 1, this rounds the number\
- to p significant digits and then formats the result in either fixed-point\
- format or in scientific notation, depending on its magnitude. A precision\
- of 0 is treated as equivalent to a precision of 1.\
- The precise rules are as follows: suppose that the result formatted with\
- presentation type 'e' and precision p-1 would have exponent exp. Then, if\
- m <= exp < p, where m is -4 for floats and -6 for Decimals, the number is\
- formatted with presentation type 'f' and precision p-1-exp. Otherwise, the\
- number is formatted with presentation type 'e' and precision p-1. In both\
- cases insignificant trailing zeros are removed from the significand, and\
- the decimal point is also removed if there are no remaining digits\
- following it, unless the '#' option is used.\
- With no precision given, uses a precision of 6 significant digits for\
- float. For Decimal, the coefficient of the result is formed from the\
- coefficient digits of the value; scientific notation is used for values\
- smaller than 1e-6 in absolute value and values where the place value of the\
- least significant digit is larger than 1, and fixed-point notation is used\
- otherwise.\
- Positive and negative infinity, positive and negative zero, and nans, are\
- formatted as inf, -inf, 0, -0 and nan respectively, regardless of the\
- precision.|
- |'G' |General format. Same as 'g' except switches to 'E' if the number gets\
- too large. The representations of infinity and NaN are uppercased, too.|
- |'n' |Number. This is the same as 'g', except that it uses the current\
- locale setting to insert the appropriate number separator characters.|
- |'%' |Percentage. Multiplies the number by 100 and displays in fixed ('f')\
- format, followed by a percent sign.|
- |None |For float this is like the 'g' type, except that when fixed-point\
- notation is used to format the result, it always includes at least one\
- digit past the decimal point, and switches to the scientific notation when\
- exp >= p - 1. When the precision is not specified, the latter will be as\
- large as needed to represent the given value faithfully.\
- For Decimal, this is the same as either 'g' or 'G' depending on the value\
- of context.capitals for the current decimal context.\
- The overall effect is to match the output of str() as altered by the other\
- format modifiers.|
- """
-
- fn __init__(
- inout self,
- fill: UInt8 = ord(" "),
- align: UInt8 = 0,
- sign: UInt8 = ord("-"),
- coerce_z: Bool = False,
- alternate_form: Bool = False,
- width: UInt8 = 0,
- grouping_option: UInt8 = 0,
- precision: UInt8 = 0,
- type: UInt8 = 0,
- ):
- """Construct a FormatSpec instance.
-
- Args:
- fill: Defaults to space.
- align: Defaults to `0` which is adjusted to the default for the arg
- type.
- sign: Defaults to `-`.
- coerce_z: Defaults to False.
- alternate_form: Defaults to False.
- width: Defaults to `0` which is adjusted to the default for the arg
- type.
- grouping_option: Defaults to `0` which is adjusted to the default for
- the arg type.
- precision: Defaults to `0` which is adjusted to the default for the
- arg type.
- type: Defaults to `0` which is adjusted to the default for the arg
- type.
- """
- self.fill = fill
- self.align = align
- self.sign = sign
- self.coerce_z = coerce_z
- self.alternate_form = alternate_form
- self.width = width
- self.grouping_option = grouping_option
- self.precision = precision
- self.type = type
-
- @staticmethod
- fn parse(fmt_str: StringSlice) -> Optional[Self]:
- """Parses the format spec string.
-
- Args:
- fmt_str: The StringSlice with the format spec.
-
- Returns:
- An instance of FormatSpec.
- """
-
- alias `:` = UInt8(ord(":"))
- var f_len = fmt_str.byte_length()
- var f_ptr = fmt_str.unsafe_ptr()
- var colon_idx = -1
- var idx = 0
- while idx < f_len:
- if f_ptr[idx] == `:`:
- exclamation_index = idx
- break
- idx += 1
-
- if colon_idx == -1:
- return None
-
- # TODO: Future implementation of format specifiers
- return None
-
- fn stringify[
- T: _CurlyEntryFormattable
- ](self, inout res: String, item: T) raises:
- """Stringify a type according to its format specification.
-
- Args:
- res: The resulting String.
- item: The item to stringify.
- """
- var type_implements_float = True # TODO
- var type_implements_float_raising = True # TODO
- var type_implements_int = True # TODO
- var type_implements_int_raising = True # TODO
-
- # TODO: transform to int/float depending on format spec and stringify
- # with hex/bin/oct etc.
- res += str(item)
-
- fn format_string(self, inout res: String, item: String) raises:
- """Transform a String according to its format specification.
-
- Args:
- res: The resulting String.
- item: The item to format.
- """
-
- # TODO: align, fill, etc.
- res += item
diff --git a/stdlib/src/utils/stringref.mojo b/stdlib/src/utils/stringref.mojo
index 729999be24..75e864b405 100644
--- a/stdlib/src/utils/stringref.mojo
+++ b/stdlib/src/utils/stringref.mojo
@@ -13,15 +13,17 @@
"""Implements the StringRef class.
"""
-from bit import count_trailing_zeros
-from builtin.dtype import _uint_type_of_width
from collections.string import _atol, _isspace
from hashlib._hasher import _HashableWithHasher, _Hasher
-from memory import UnsafePointer, memcmp, pack_bits
+from sys import simdwidthof
+from sys.ffi import c_char
+
+from bit import count_trailing_zeros
+from builtin.dtype import _uint_type_of_width
+from memory import UnsafePointer, memcmp, pack_bits, Span
from memory.memory import _memcmp_impl_unconstrained
+
from utils import StringSlice
-from sys.ffi import c_char
-from sys import simdwidthof
# ===----------------------------------------------------------------------=== #
# Utilities
@@ -33,9 +35,9 @@ fn _align_down(value: Int, alignment: Int) -> Int:
return value._positive_div(alignment) * alignment
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# StringRef
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@value
@@ -355,7 +357,7 @@ struct StringRef(
"""
return hash(self.data, self.length)
- fn __hash__[H: _Hasher](self, inout hasher: H):
+ fn __hash__[H: _Hasher](self, mut hasher: H):
"""Updates hasher with the underlying bytes.
Parameters:
@@ -409,7 +411,7 @@ struct StringRef(
return String.write("StringRef(", repr(str(self)), ")")
@no_inline
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""
Formats this StringRef to the provided Writer.
@@ -689,9 +691,9 @@ struct StringRef(
)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Utilities
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
@always_inline
diff --git a/stdlib/src/utils/variant.mojo b/stdlib/src/utils/variant.mojo
index 07dc22da63..6936a3a003 100644
--- a/stdlib/src/utils/variant.mojo
+++ b/stdlib/src/utils/variant.mojo
@@ -18,7 +18,7 @@ You can use this type to implement variant/sum types. For example:
from utils import Variant
alias IntOrString = Variant[Int, String]
-fn to_string(inout x: IntOrString) -> String:
+fn to_string(mut x: IntOrString) -> String:
if x.isa[String]():
return x[String]
# x.isa[Int]()
@@ -81,7 +81,7 @@ struct Variant[*Ts: CollectionElement](
```mojo
from utils import Variant
alias IntOrString = Variant[Int, String]
- fn to_string(inout x: IntOrString) -> String:
+ fn to_string(mut x: IntOrString) -> String:
if x.isa[String]():
return x[String]
# x.isa[Int]()
@@ -124,7 +124,7 @@ struct Variant[*Ts: CollectionElement](
self._impl = __mlir_attr[`#kgen.unknown : `, Self._mlir_type]
@implicit
- fn __init__[T: CollectionElement](inout self, owned value: T):
+ fn __init__[T: CollectionElement](mut self, owned value: T):
"""Create a variant with one of the types.
Parameters:
@@ -239,7 +239,7 @@ struct Variant[*Ts: CollectionElement](
return UnsafePointer(discr_ptr).bitcast[UInt8]()[]
@always_inline
- fn take[T: CollectionElement](inout self) -> T:
+ fn take[T: CollectionElement](mut self) -> T:
"""Take the current value of the variant with the provided type.
The caller takes ownership of the underlying value.
@@ -260,7 +260,7 @@ struct Variant[*Ts: CollectionElement](
return self.unsafe_take[T]()
@always_inline
- fn unsafe_take[T: CollectionElement](inout self) -> T:
+ fn unsafe_take[T: CollectionElement](mut self) -> T:
"""Unsafely take the current value of the variant with the provided type.
The caller takes ownership of the underlying value.
@@ -284,7 +284,7 @@ struct Variant[*Ts: CollectionElement](
@always_inline
fn replace[
Tin: CollectionElement, Tout: CollectionElement
- ](inout self, owned value: Tin) -> Tout:
+ ](mut self, owned value: Tin) -> Tout:
"""Replace the current value of the variant with the provided type.
The caller takes ownership of the underlying value.
@@ -311,7 +311,7 @@ struct Variant[*Ts: CollectionElement](
@always_inline
fn unsafe_replace[
Tin: CollectionElement, Tout: CollectionElement
- ](inout self, owned value: Tin) -> Tout:
+ ](mut self, owned value: Tin) -> Tout:
"""Unsafely replace the current value of the variant with the provided type.
The caller takes ownership of the underlying value.
@@ -337,7 +337,7 @@ struct Variant[*Ts: CollectionElement](
self.set[Tin](value^)
return x^
- fn set[T: CollectionElement](inout self, owned value: T):
+ fn set[T: CollectionElement](mut self, owned value: T):
"""Set the variant value.
This will call the destructor on the old value, and update the variant's
diff --git a/stdlib/src/utils/write.mojo b/stdlib/src/utils/write.mojo
index 5cf8ba1d3e..6d68951b9b 100644
--- a/stdlib/src/utils/write.mojo
+++ b/stdlib/src/utils/write.mojo
@@ -13,13 +13,13 @@
"""Establishes the contract between `Writer` and `Writable` types."""
from collections import InlineArray
-from memory import memcpy, UnsafePointer
-from utils import Span, StaticString
-from sys.info import is_nvidia_gpu
-from builtin.io import _printf
+from sys.info import is_gpu
+from memory import UnsafePointer, memcpy, Span
-# ===----------------------------------------------------------------------===#
+from utils import StaticString
+
+# ===-----------------------------------------------------------------------===#
trait Writer:
@@ -35,18 +35,18 @@ trait Writer:
Example:
```mojo
- from utils import Span
+ from memory import Span
@value
struct NewString(Writer, Writable):
var s: String
# Writer requirement to write a Span of Bytes
- fn write_bytes(inout self, bytes: Span[Byte, _]):
+ fn write_bytes(mut self, bytes: Span[Byte, _]):
self.s._iadd[False](bytes)
# Writer requirement to take multiple args
- fn write[*Ts: Writable](inout self, *args: *Ts):
+ fn write[*Ts: Writable](mut self, *args: *Ts):
@parameter
fn write_arg[T: Writable](arg: T):
arg.write_to(self)
@@ -54,7 +54,7 @@ trait Writer:
args.each[write_arg]()
# Also make it Writable to allow `print` to write the inner String
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
writer.write(self.s)
@@ -65,7 +65,7 @@ trait Writer:
# Pass multiple args to the Writer. The Int and StringLiteral types
# call `writer.write_bytes` in their own `write_to` implementations.
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
writer.write("Point(", self.x, ", ", self.y, ")")
# Enable conversion to a String using `str(point)`
@@ -89,7 +89,7 @@ trait Writer:
"""
@always_inline
- fn write_bytes(inout self, bytes: Span[Byte, _]):
+ fn write_bytes(mut self, bytes: Span[Byte, _]):
"""
Write a `Span[Byte]` to this `Writer`.
@@ -99,7 +99,7 @@ trait Writer:
"""
...
- fn write[*Ts: Writable](inout self, *args: *Ts):
+ fn write[*Ts: Writable](mut self, *args: *Ts):
"""Write a sequence of Writable arguments to the provided Writer.
Parameters:
@@ -118,9 +118,9 @@ trait Writer:
# To only have to implement `write_bytes` to make a type a valid Writer
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Writable
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
trait Writable:
@@ -134,7 +134,7 @@ trait Writable:
var x: Float64
var y: Float64
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
var string = "Point"
# Write a single `Span[Byte]`:
writer.write_bytes(string.as_bytes())
@@ -143,7 +143,7 @@ trait Writable:
```
"""
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
"""
Formats the string representation of this type to the provided Writer.
@@ -156,15 +156,15 @@ trait Writable:
...
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# Utils
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
fn write_args[
W: Writer, *Ts: Writable
](
- inout writer: W,
+ mut writer: W,
args: VariadicPack[_, Writable, *Ts],
*,
sep: StaticString = "",
@@ -223,47 +223,48 @@ trait MovableWriter(Movable, Writer):
...
-struct _WriteBufferHeap[W: MovableWriter, //, capacity: Int](Writer):
+struct _WriteBufferHeap(Writer):
var data: UnsafePointer[UInt8]
var pos: Int
- var writer: W
- @implicit
- fn __init__(out self, owned writer: W):
+ fn __init__(out self, size: Int):
self.data = UnsafePointer[
- UInt8,
- address_space = AddressSpace.GENERIC,
- ].alloc(capacity)
+ UInt8, address_space = AddressSpace.GENERIC
+ ].alloc(size)
self.pos = 0
- self.writer = writer^
- fn flush(inout self):
- self.writer.write_bytes(
- Span[Byte, ImmutableAnyOrigin](ptr=self.data, length=self.pos)
- )
- self.pos = 0
+ fn __del__(owned self):
+ self.data.free()
@always_inline
- fn write_bytes(inout self, bytes: Span[UInt8, _]):
+ fn write_bytes(mut self, bytes: Span[UInt8, _]):
len_bytes = len(bytes)
# If empty then return
if len_bytes == 0:
return
- # If span is too large to fit in buffer, write directly and return
- if len_bytes > capacity:
- self.flush()
- self.writer.write_bytes(bytes)
- return
- # If buffer would overflow, flush writer and reset pos to 0.
- if self.pos + len_bytes > capacity:
- self.flush()
- ptr = bytes.unsafe_ptr()
- # Continue writing to buffer
+ var ptr = bytes.unsafe_ptr()
for i in range(len_bytes):
self.data[i + self.pos] = ptr[i]
self.pos += len_bytes
- fn write[*Ts: Writable](inout self, *args: *Ts):
+ fn write[*Ts: Writable](mut self, *args: *Ts):
+ @parameter
+ fn write_arg[T: Writable](arg: T):
+ arg.write_to(self)
+
+ args.each[write_arg]()
+
+
+struct _ArgBytes(Writer):
+ var size: Int
+
+ fn __init__(out self):
+ self.size = 0
+
+ fn write_bytes(mut self, bytes: Span[UInt8, _]):
+ self.size += len(bytes)
+
+ fn write[*Ts: Writable](mut self, *args: *Ts):
@parameter
fn write_arg[T: Writable](arg: T):
arg.write_to(self)
@@ -282,7 +283,7 @@ struct _WriteBufferStack[W: MovableWriter, //, capacity: Int](Writer):
self.pos = 0
self.writer = writer^
- fn flush(inout self):
+ fn flush(mut self):
self.writer.write_bytes(
Span[Byte, ImmutableAnyOrigin](
ptr=self.data.unsafe_ptr(), length=self.pos
@@ -290,7 +291,7 @@ struct _WriteBufferStack[W: MovableWriter, //, capacity: Int](Writer):
)
self.pos = 0
- fn write_bytes(inout self, bytes: Span[Byte, _]):
+ fn write_bytes(mut self, bytes: Span[Byte, _]):
len_bytes = len(bytes)
# If empty then return
if len_bytes == 0:
@@ -307,7 +308,7 @@ struct _WriteBufferStack[W: MovableWriter, //, capacity: Int](Writer):
memcpy(self.data.unsafe_ptr() + self.pos, bytes.unsafe_ptr(), len_bytes)
self.pos += len_bytes
- fn write[*Ts: Writable](inout self, *args: *Ts):
+ fn write[*Ts: Writable](mut self, *args: *Ts):
@parameter
fn write_arg[T: Writable](arg: T):
arg.write_to(self)
@@ -365,11 +366,18 @@ fn write_buffered[
"""
@parameter
- if is_nvidia_gpu():
+ if is_gpu():
# Stack space is very small on GPU due to many threads, so use heap
- var buffer = _WriteBufferHeap[buffer_size](writer^)
+ # Count the total length of bytes to allocate only once
+ var arg_bytes = _ArgBytes()
+ write_args(arg_bytes, args, sep=sep, end=end)
+
+ var buffer = _WriteBufferHeap(arg_bytes.size + 1)
write_args(buffer, args, sep=sep, end=end)
- buffer.flush()
+ buffer.data[buffer.pos] = 0
+ writer.write_bytes(
+ Span[Byte, ImmutableAnyOrigin](ptr=buffer.data, length=buffer.pos)
+ )
else:
var buffer = _WriteBufferStack[buffer_size](writer^)
write_args(buffer, args, sep=sep, end=end)
diff --git a/stdlib/test/bit/test_bit.mojo b/stdlib/test/bit/test_bit.mojo
index dee81507d1..1f1063eee0 100644
--- a/stdlib/test/bit/test_bit.mojo
+++ b/stdlib/test/bit/test_bit.mojo
@@ -25,7 +25,9 @@ from bit import (
pop_count,
rotate_bits_left,
rotate_bits_right,
+ log2_floor,
)
+from math import log2, floor
from testing import assert_equal
@@ -497,6 +499,30 @@ def test_rotate_bits_simd():
assert_equal(rotate_bits_right[6](Scalar[type](96)), 129)
+fn _log2_floor(n: Int) -> Int:
+ return int(floor(log2(float(n))))
+
+
+def test_log2_floor():
+ assert_equal(log2_floor(0), 0)
+ for i in range(1, 100):
+ assert_equal(
+ log2_floor(i),
+ _log2_floor(i),
+ msg="mismatching value for the input value of " + str(i),
+ )
+
+ fn _check_alias[n: Int](expected: Int) raises:
+ alias res = log2_floor(n)
+ assert_equal(res, expected)
+
+ _check_alias[0](0)
+ _check_alias[1](0)
+ _check_alias[2](1)
+ _check_alias[15](3)
+ _check_alias[32](5)
+
+
def main():
test_rotate_bits_int()
test_rotate_bits_simd()
@@ -519,3 +545,4 @@ def main():
test_pop_count()
test_pop_count_simd()
test_bit_not_simd()
+ test_log2_floor()
diff --git a/stdlib/test/builtin/test_debug_assert.mojo b/stdlib/test/builtin/test_debug_assert.mojo
index 9df1b1e1f3..6d8ceb57f3 100644
--- a/stdlib/test/builtin/test_debug_assert.mojo
+++ b/stdlib/test/builtin/test_debug_assert.mojo
@@ -52,5 +52,5 @@ def test_debug_assert_writable():
struct WritableOnly:
var message: String
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
writer.write(self.message)
diff --git a/stdlib/test/builtin/test_dtype.mojo b/stdlib/test/builtin/test_dtype.mojo
index 49d509d21c..d941ab794a 100644
--- a/stdlib/test/builtin/test_dtype.mojo
+++ b/stdlib/test/builtin/test_dtype.mojo
@@ -13,9 +13,9 @@
# RUN: %mojo %s
from collections import Set
+from sys import sizeof
from testing import assert_equal, assert_false, assert_true
-from sys import sizeof
fn test_equality() raises:
diff --git a/stdlib/test/builtin/test_file.mojo b/stdlib/test/builtin/test_file.mojo
index 7c9d3055f4..d30091958e 100644
--- a/stdlib/test/builtin/test_file.mojo
+++ b/stdlib/test/builtin/test_file.mojo
@@ -16,8 +16,8 @@
from pathlib import Path, _dir_of_current_file
from sys import os_is_windows
from tempfile import gettempdir
-from memory import UnsafePointer
+from memory import UnsafePointer
from testing import assert_equal, assert_true
diff --git a/stdlib/test/builtin/test_format_float.mojo b/stdlib/test/builtin/test_format_float.mojo
index 1544f185ff..3bf820543d 100644
--- a/stdlib/test/builtin/test_format_float.mojo
+++ b/stdlib/test/builtin/test_format_float.mojo
@@ -12,10 +12,11 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
+from random import random_float64
+
from builtin._format_float import _write_float
-from testing import assert_equal
from python import Python, PythonObject
-from random import random_float64
+from testing import assert_equal
def test_float64():
diff --git a/stdlib/test/builtin/test_int.mojo b/stdlib/test/builtin/test_int.mojo
index 8d898798da..9919b2f636 100644
--- a/stdlib/test/builtin/test_int.mojo
+++ b/stdlib/test/builtin/test_int.mojo
@@ -14,10 +14,9 @@
from sys.info import bitwidthof
-from testing import assert_equal, assert_true, assert_false, assert_raises
-
-from python import PythonObject
from memory import UnsafePointer
+from python import PythonObject
+from testing import assert_equal, assert_false, assert_raises, assert_true
def test_properties():
diff --git a/stdlib/test/builtin/test_int_literal.mojo b/stdlib/test/builtin/test_int_literal.mojo
index 84d23a7955..9651e564b5 100644
--- a/stdlib/test/builtin/test_int_literal.mojo
+++ b/stdlib/test/builtin/test_int_literal.mojo
@@ -12,7 +12,7 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
-from testing import assert_equal, assert_true, assert_false
+from testing import assert_equal, assert_false, assert_true
def test_add():
diff --git a/stdlib/test/builtin/test_issue_1505.mojo b/stdlib/test/builtin/test_issue_1505.mojo
index a4f9c4e14f..25f8f32e6f 100644
--- a/stdlib/test/builtin/test_issue_1505.mojo
+++ b/stdlib/test/builtin/test_issue_1505.mojo
@@ -15,9 +15,10 @@
from random import random_ui64
-from utils import IndexList
from testing import assert_equal
+from utils import IndexList
+
fn gen_perm() -> IndexList[64]:
var result = IndexList[64]()
diff --git a/stdlib/test/builtin/test_list_literal.mojo b/stdlib/test/builtin/test_list_literal.mojo
index 38ae7764fe..309a831b24 100644
--- a/stdlib/test/builtin/test_list_literal.mojo
+++ b/stdlib/test/builtin/test_list_literal.mojo
@@ -12,7 +12,7 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
-from testing import assert_equal, assert_true, assert_false
+from testing import assert_equal, assert_false, assert_true
def test_list():
diff --git a/stdlib/test/builtin/test_location.mojo b/stdlib/test/builtin/test_location.mojo
index c70610663d..cc9a706249 100644
--- a/stdlib/test/builtin/test_location.mojo
+++ b/stdlib/test/builtin/test_location.mojo
@@ -126,20 +126,22 @@ fn test_parameter_context() raises:
@always_inline
-fn capture_call_loc(cond: Bool = False) -> _SourceLocation:
+fn capture_call_loc[depth: Int = 1](cond: Bool = False) -> _SourceLocation:
if (
not cond
): # NOTE: we test that __call_location works even in a nested scope.
- return __call_location()
+ return __call_location[depth]()
return _SourceLocation(-1, -1, "")
@always_inline("nodebug")
-fn capture_call_loc_nodebug(cond: Bool = False) -> _SourceLocation:
+fn capture_call_loc_nodebug[
+ depth: Int = 1
+](cond: Bool = False) -> _SourceLocation:
if (
not cond
): # NOTE: we test that __call_location works even in a nested scope.
- return __call_location()
+ return __call_location[depth]()
return _SourceLocation(-1, -1, "")
@@ -151,13 +153,22 @@ fn get_call_locs() -> (_SourceLocation, _SourceLocation):
@always_inline("nodebug")
-fn get_call_locs_inlined() -> (_SourceLocation, _SourceLocation):
+fn get_call_locs_inlined[
+ depth: Int = 1
+]() -> (_SourceLocation, _SourceLocation):
return (
- capture_call_loc(),
- capture_call_loc_nodebug(),
+ capture_call_loc[depth](),
+ capture_call_loc_nodebug[depth](),
)
+@always_inline
+fn get_call_locs_inlined_twice[
+ depth: Int = 1
+]() -> (_SourceLocation, _SourceLocation):
+ return get_call_locs_inlined[depth]()
+
+
fn get_four_call_locs() -> (
_SourceLocation,
_SourceLocation,
@@ -182,8 +193,8 @@ fn get_four_call_locs_inlined() -> (
fn test_builtin_call_loc() raises:
- var l = (148, 149, 156, 157)
- var c = (25, 33, 25, 33)
+ var l = (150, 151, 160, 161)
+ var c = (25, 33, 32, 40)
var loc_pair = get_call_locs()
check_source_loc(l[0], c[0], loc_pair[0])
check_source_loc(l[1], c[1], loc_pair[1])
@@ -192,6 +203,10 @@ fn test_builtin_call_loc() raises:
check_source_loc(l[2], c[2], loc_pair[0])
check_source_loc(l[3], c[3], loc_pair[1])
+ loc_pair = get_call_locs_inlined_twice[2]()
+ check_source_loc(169, 40, loc_pair[0])
+ check_source_loc(169, 40, loc_pair[1])
+
var loc_quad = get_four_call_locs()
check_source_loc(l[0], c[0], loc_quad[0])
check_source_loc(l[1], c[1], loc_quad[1])
@@ -211,7 +226,7 @@ fn source_loc_with_debug() -> _SourceLocation:
var col: __mlir_type.index
var file_name: __mlir_type.`!kgen.string`
line, col, file_name = __mlir_op.`kgen.source_loc`[
- _properties = __mlir_attr.`{inlineCount = 0 : i64}`,
+ inlineCount = Int(0).value,
_type = (
__mlir_type.index,
__mlir_type.index,
diff --git a/stdlib/test/builtin/test_object.mojo b/stdlib/test/builtin/test_object.mojo
index 65c118665a..899c75da17 100644
--- a/stdlib/test/builtin/test_object.mojo
+++ b/stdlib/test/builtin/test_object.mojo
@@ -183,7 +183,7 @@ def test_function(lhs, rhs) -> object:
return lhs + rhs
-# These are all marked borrowed because 'object' doesn't support function
+# These are all marked read-only because 'object' doesn't support function
# types with owned arguments.
def test_function_raises(a) -> object:
raise Error("Error from function type")
diff --git a/stdlib/test/builtin/test_print.mojo b/stdlib/test/builtin/test_print.mojo
index ca3b03afcc..4ace3a30c1 100644
--- a/stdlib/test/builtin/test_print.mojo
+++ b/stdlib/test/builtin/test_print.mojo
@@ -14,11 +14,11 @@
import sys
-
from tempfile import NamedTemporaryFile
-from testing import assert_equal
from builtin._location import __call_location, _SourceLocation
+from testing import assert_equal
+
from utils import IndexList, StringRef
@@ -63,7 +63,7 @@ struct PrintChecker:
fn stream(self) -> FileDescriptor:
return self.tmp._file_handle._get_raw_fd()
- fn check_line(inout self, expected: String, msg: String = "") raises:
+ fn check_line(mut self, expected: String, msg: String = "") raises:
print(end="", file=self.stream(), flush=True)
_ = self.tmp.seek(self.cursor)
var result = self.tmp.read()[:-1]
@@ -72,7 +72,7 @@ struct PrintChecker:
self.cursor += len(result) + 1
fn check_line_starts_with(
- inout self, prefix: String, msg: String = ""
+ mut self, prefix: String, msg: String = ""
) raises:
print(end="", file=self.stream(), flush=True)
_ = self.tmp.seek(self.cursor)
diff --git a/stdlib/test/builtin/test_range.mojo b/stdlib/test/builtin/test_range.mojo
index b3a1f62be6..051656d27d 100644
--- a/stdlib/test/builtin/test_range.mojo
+++ b/stdlib/test/builtin/test_range.mojo
@@ -193,7 +193,7 @@ def test_scalar_range():
assert_equal(r.end, 16)
assert_equal(r.step, 4)
- fn append_many(inout list: List, *values: list.T):
+ fn append_many(mut list: List, *values: list.T):
for value in values:
list.append(value[])
diff --git a/stdlib/test/builtin/test_reversed.mojo b/stdlib/test/builtin/test_reversed.mojo
index d6027d5429..790619c6c4 100644
--- a/stdlib/test/builtin/test_reversed.mojo
+++ b/stdlib/test/builtin/test_reversed.mojo
@@ -13,6 +13,7 @@
# RUN: %mojo %s
from collections import Deque, Dict
+
from testing import assert_equal
diff --git a/stdlib/test/builtin/test_simd.mojo b/stdlib/test/builtin/test_simd.mojo
index 8b8698c9e7..d7bd8928b4 100644
--- a/stdlib/test/builtin/test_simd.mojo
+++ b/stdlib/test/builtin/test_simd.mojo
@@ -12,11 +12,11 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
+from collections import InlineArray
from sys import has_neon
-from memory import UnsafePointer
-from collections import InlineArray
from builtin.simd import _modf
+from memory import UnsafePointer
from testing import (
assert_almost_equal,
assert_equal,
@@ -24,7 +24,8 @@ from testing import (
assert_not_equal,
assert_true,
)
-from utils import unroll, StaticTuple, IndexList
+
+from utils import IndexList, StaticTuple, unroll
from utils.numerics import isfinite, isinf, isnan, nan
diff --git a/stdlib/test/builtin/test_sort.mojo b/stdlib/test/builtin/test_sort.mojo
index 7ff2834d46..3c98be083f 100644
--- a/stdlib/test/builtin/test_sort.mojo
+++ b/stdlib/test/builtin/test_sort.mojo
@@ -45,7 +45,7 @@ fn random_numbers[
return result
-# fn assert_sorted[dtype: DType](inout list: List[Scalar[dtype]]) raises:
+# fn assert_sorted[dtype: DType](mut list: List[Scalar[dtype]]) raises:
# sort[dtype](list)
# for i in range(1, len(list)):
# assert_true(
@@ -53,7 +53,7 @@ fn random_numbers[
# )
-fn assert_sorted_string(inout list: List[String]) raises:
+fn assert_sorted_string(mut list: List[String]) raises:
for i in range(1, len(list)):
assert_true(
list[i] >= list[i - 1], str(list[i - 1]) + " > " + str(list[i])
@@ -62,7 +62,7 @@ fn assert_sorted_string(inout list: List[String]) raises:
fn assert_sorted[
type: ComparableCollectionElement
-](inout list: List[type]) raises:
+](mut list: List[type]) raises:
for i in range(1, len(list)):
assert_true(list[i] >= list[i - 1], "error at index: " + str(i))
diff --git a/stdlib/test/builtin/test_sort_issue_1018.mojo b/stdlib/test/builtin/test_sort_issue_1018.mojo
index 855b0a8036..af50f5b896 100644
--- a/stdlib/test/builtin/test_sort_issue_1018.mojo
+++ b/stdlib/test/builtin/test_sort_issue_1018.mojo
@@ -14,8 +14,8 @@
# RUN: %mojo %s | FileCheck %s
from random import rand
-from memory import UnsafePointer
-from utils import Span
+
+from memory import UnsafePointer, Span
fn sort_test[D: DType, name: StringLiteral](size: Int, max: Int) raises:
diff --git a/stdlib/test/builtin/test_string_literal.mojo b/stdlib/test/builtin/test_string_literal.mojo
index 71c5853ba2..f4d5322a71 100644
--- a/stdlib/test/builtin/test_string_literal.mojo
+++ b/stdlib/test/builtin/test_string_literal.mojo
@@ -13,8 +13,8 @@
# RUN: %mojo %s
from sys.ffi import c_char
-from memory import UnsafePointer
+from memory import UnsafePointer
from testing import (
assert_equal,
assert_false,
@@ -219,6 +219,20 @@ def test_intable():
_ = StringLiteral.__int__("hi")
+def test_join():
+ assert_equal("".join(), "")
+ assert_equal("".join("a", "b", "c"), "abc")
+ assert_equal(" ".join("a", "b", "c"), "a b c")
+ assert_equal(" ".join("a", "b", "c", ""), "a b c ")
+ assert_equal(" ".join("a", "b", "c", " "), "a b c ")
+
+ var sep = ","
+ var s = String("abc")
+ assert_equal(sep.join(s, s, s, s), "abc,abc,abc,abc")
+ assert_equal(sep.join(1, 2, 3), "1,2,3")
+ assert_equal(sep.join(1, "abc", 3), "1,abc,3")
+
+
def test_isdigit():
assert_true("123".isdigit())
assert_false("abc".isdigit())
@@ -481,6 +495,15 @@ def test_float_conversion():
_ = ("not a float").__float__()
+def test_string_literal_from_stringable():
+ assert_equal(StringLiteral.get["hello"](), "hello")
+ assert_equal(StringLiteral.get[String("hello")](), "hello")
+ assert_equal(StringLiteral.get[42](), "42")
+ assert_equal(
+ StringLiteral.get[SIMD[DType.int64, 4](1, 2, 3, 4)](), "[1, 2, 3, 4]"
+ )
+
+
def main():
test_add()
test_iadd()
@@ -490,6 +513,7 @@ def main():
test_bool()
test_contains()
test_find()
+ test_join()
test_rfind()
test_replace()
test_comparison_operators()
@@ -512,3 +536,4 @@ def main():
test_split()
test_splitlines()
test_float_conversion()
+ test_string_literal_from_stringable()
diff --git a/stdlib/test/builtin/test_uint.mojo b/stdlib/test/builtin/test_uint.mojo
index 9e63c45937..1af1d2f125 100644
--- a/stdlib/test/builtin/test_uint.mojo
+++ b/stdlib/test/builtin/test_uint.mojo
@@ -12,9 +12,10 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
-from testing import assert_equal, assert_false, assert_not_equal, assert_true
from sys import bitwidthof
+
from bit import count_trailing_zeros
+from testing import assert_equal, assert_false, assert_not_equal, assert_true
def test_simple_uint():
diff --git a/stdlib/test/collections/test_counter.mojo b/stdlib/test/collections/test_counter.mojo
index 0abc8e1287..27f5f3b9e6 100644
--- a/stdlib/test/collections/test_counter.mojo
+++ b/stdlib/test/collections/test_counter.mojo
@@ -12,8 +12,8 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
-from collections.counter import Counter
from collections import Optional
+from collections.counter import Counter
from testing import assert_equal, assert_false, assert_raises, assert_true
diff --git a/stdlib/test/collections/test_deque.mojo b/stdlib/test/collections/test_deque.mojo
index a9350c2180..fd2db54440 100644
--- a/stdlib/test/collections/test_deque.mojo
+++ b/stdlib/test/collections/test_deque.mojo
@@ -12,13 +12,13 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
-from testing import assert_equal, assert_false, assert_true, assert_raises
-
from collections import Deque
-# ===----------------------------------------------------------------------===#
+from testing import assert_equal, assert_false, assert_raises, assert_true
+
+# ===-----------------------------------------------------------------------===#
# Implementation tests
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
fn test_impl_init_default() raises:
@@ -666,9 +666,9 @@ fn test_impl_imul() raises:
assert_equal((q._data + 0)[], 3)
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
# API Interface tests
-# ===----------------------------------------------------------------------===#
+# ===-----------------------------------------------------------------------===#
fn test_init_variadic_list() raises:
diff --git a/stdlib/test/collections/test_inline_array.mojo b/stdlib/test/collections/test_inline_array.mojo
index b16cb4b5bb..18a933c6be 100644
--- a/stdlib/test/collections/test_inline_array.mojo
+++ b/stdlib/test/collections/test_inline_array.mojo
@@ -13,10 +13,11 @@
# RUN: %mojo %s
from collections import InlineArray
-from testing import assert_equal, assert_false, assert_true
-from memory.maybe_uninitialized import UnsafeMaybeUninitialized
+
from memory import UnsafePointer
+from memory.maybe_uninitialized import UnsafeMaybeUninitialized
from test_utils import ValueDestructorRecorder
+from testing import assert_equal, assert_false, assert_true
def test_array_unsafe_get():
diff --git a/stdlib/test/collections/test_inline_list.mojo b/stdlib/test/collections/test_inline_list.mojo
index b3d21ed3a0..52adea853c 100644
--- a/stdlib/test/collections/test_inline_list.mojo
+++ b/stdlib/test/collections/test_inline_list.mojo
@@ -13,8 +13,8 @@
# RUN: %mojo %s
from collections import InlineList, Set
-from memory import UnsafePointer
+from memory import UnsafePointer
from test_utils import MoveCounter, ValueDestructorRecorder
from testing import assert_equal, assert_false, assert_raises, assert_true
diff --git a/stdlib/test/collections/test_list.mojo b/stdlib/test/collections/test_list.mojo
index 873baf32e6..1def6849ea 100644
--- a/stdlib/test/collections/test_list.mojo
+++ b/stdlib/test/collections/test_list.mojo
@@ -13,13 +13,12 @@
# RUN: %mojo %s
from collections import List
-from memory import UnsafePointer
from sys.info import sizeof
+
+from memory import UnsafePointer, Span
from test_utils import CopyCounter, MoveCounter
from testing import assert_equal, assert_false, assert_raises, assert_true
-from utils import Span
-
def test_mojo_issue_698():
var list = List[Float64]()
diff --git a/stdlib/test/collections/test_set.mojo b/stdlib/test/collections/test_set.mojo
index 4dceebd59d..147e488304 100644
--- a/stdlib/test/collections/test_set.mojo
+++ b/stdlib/test/collections/test_set.mojo
@@ -14,8 +14,8 @@
from collections import Set
-from testing import assert_false, assert_raises, assert_true
from testing import assert_equal as AE
+from testing import assert_false, assert_raises, assert_true
fn assert_equal[T: EqualityComparable](lhs: T, rhs: T) raises:
diff --git a/stdlib/test/collections/test_string.mojo b/stdlib/test/collections/test_string.mojo
index 84c881c97b..8f0027893e 100644
--- a/stdlib/test/collections/test_string.mojo
+++ b/stdlib/test/collections/test_string.mojo
@@ -17,6 +17,7 @@ from collections.string import (
_calc_initial_buffer_size_int64,
_isspace,
)
+
from memory import UnsafePointer
from python import Python
from testing import (
@@ -1272,19 +1273,23 @@ def test_iter():
var idx = -1
vs = String("mojo🔥")
- for item in vs:
- idx += 1
- if idx == 0:
- assert_equal("m", item)
- elif idx == 1:
- assert_equal("o", item)
- elif idx == 2:
- assert_equal("j", item)
- elif idx == 3:
- assert_equal("o", item)
- elif idx == 4:
- assert_equal("🔥", item)
- assert_equal(4, idx)
+ var iterator = vs.__iter__()
+ assert_equal(5, len(iterator))
+ var item = iterator.__next__()
+ assert_equal("m", item)
+ assert_equal(4, len(iterator))
+ item = iterator.__next__()
+ assert_equal("o", item)
+ assert_equal(3, len(iterator))
+ item = iterator.__next__()
+ assert_equal("j", item)
+ assert_equal(2, len(iterator))
+ item = iterator.__next__()
+ assert_equal("o", item)
+ assert_equal(1, len(iterator))
+ item = iterator.__next__()
+ assert_equal("🔥", item)
+ assert_equal(0, len(iterator))
var items = List[String](
"mojo🔥",
diff --git a/stdlib/test/hashlib/test_ahash.mojo b/stdlib/test/hashlib/test_ahash.mojo
index 87604606ca..c9f01c3a14 100644
--- a/stdlib/test/hashlib/test_ahash.mojo
+++ b/stdlib/test/hashlib/test_ahash.mojo
@@ -12,15 +12,14 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
-from bit import pop_count
-from builtin._location import __call_location
from hashlib._ahash import AHasher
-from hashlib.hash import hash as old_hash
from hashlib._hasher import _hash_with_hasher as hash
+from hashlib.hash import hash as old_hash
+
+from bit import pop_count
+from builtin._location import __call_location
+from memory import memset_zero, stack_allocation, Span
from testing import assert_equal, assert_not_equal, assert_true
-from memory import memset_zero, stack_allocation
-from time import now
-from utils import Span
# Source: https://www.101languages.net/arabic/most-common-arabic-words/
alias words_ar = """
@@ -578,7 +577,7 @@ fn gen_word_pairs[words: String = words_en]() -> List[String]:
try:
var list = words.split(", ")
for w in list:
- var w1 = w[].strip()
+ var w1 = str(w[].strip())
for w in list:
var w2 = w[].strip()
result.append(w1 + " " + w2)
diff --git a/stdlib/test/hashlib/test_hash.mojo b/stdlib/test/hashlib/test_hash.mojo
index 5e7662fbd7..56f475f55d 100644
--- a/stdlib/test/hashlib/test_hash.mojo
+++ b/stdlib/test/hashlib/test_hash.mojo
@@ -19,6 +19,7 @@
# specific. But for now they test behavior and reproducibility.
from hashlib.hash import _hash_simd
+
from testing import assert_equal, assert_not_equal, assert_true
diff --git a/stdlib/test/hashlib/test_hasher.mojo b/stdlib/test/hashlib/test_hasher.mojo
index f41685b553..4c10ac50a5 100644
--- a/stdlib/test/hashlib/test_hasher.mojo
+++ b/stdlib/test/hashlib/test_hasher.mojo
@@ -13,12 +13,14 @@
# RUN: %mojo %s
-from hashlib._hasher import _hash_with_hasher, _HashableWithHasher, _Hasher
from hashlib._ahash import AHasher
-from memory import UnsafePointer
+from hashlib._hasher import _hash_with_hasher, _HashableWithHasher, _Hasher
from pathlib import Path
+
+from memory import UnsafePointer
from python import Python, PythonObject
from testing import assert_equal, assert_true
+
from utils import StringRef
@@ -28,14 +30,14 @@ struct DummyHasher(_Hasher):
fn __init__(out self):
self._dummy_value = 0
- fn _update_with_bytes(inout self, data: UnsafePointer[UInt8], length: Int):
+ fn _update_with_bytes(mut self, data: UnsafePointer[UInt8], length: Int):
for i in range(length):
self._dummy_value += data[i].cast[DType.uint64]()
- fn _update_with_simd(inout self, value: SIMD[_, _]):
+ fn _update_with_simd(mut self, value: SIMD[_, _]):
self._dummy_value += value.cast[DType.uint64]().reduce_add()
- fn update[T: _HashableWithHasher](inout self, value: T):
+ fn update[T: _HashableWithHasher](mut self, value: T):
value.__hash__(self)
fn finish(owned self) -> UInt64:
@@ -46,7 +48,7 @@ struct DummyHasher(_Hasher):
struct SomeHashableStruct(_HashableWithHasher):
var _value: Int64
- fn __hash__[H: _Hasher](self, inout hasher: H):
+ fn __hash__[H: _Hasher](self, mut hasher: H):
hasher._update_with_simd(self._value)
@@ -67,7 +69,7 @@ struct ComplexeHashableStruct(_HashableWithHasher):
var _value1: SomeHashableStruct
var _value2: SomeHashableStruct
- fn __hash__[H: _Hasher](self, inout hasher: H):
+ fn __hash__[H: _Hasher](self, mut hasher: H):
hasher.update(self._value1)
hasher.update(self._value2)
@@ -94,10 +96,10 @@ struct ComplexHashableStructWithList(_HashableWithHasher):
var _value2: SomeHashableStruct
var _value3: List[UInt8]
- fn __hash__[H: _Hasher](self, inout hasher: H):
+ fn __hash__[H: _Hasher](self, mut hasher: H):
hasher.update(self._value1)
hasher.update(self._value2)
- # This is okay because self is passed as borrowed so the pointer will
+ # This is okay because self is passed as read-only so the pointer will
# be valid until at least the end of the function
hasher._update_with_bytes(
data=self._value3.unsafe_ptr(),
@@ -113,10 +115,10 @@ struct ComplexHashableStructWithListAndWideSIMD(_HashableWithHasher):
var _value3: List[UInt8]
var _value4: SIMD[DType.uint32, 4]
- fn __hash__[H: _Hasher](self, inout hasher: H):
+ fn __hash__[H: _Hasher](self, mut hasher: H):
hasher.update(self._value1)
hasher.update(self._value2)
- # This is okay because self is passed as borrowed so the pointer will
+ # This is okay because self is passed as read-only so the pointer will
# be valid until at least the end of the function
hasher._update_with_bytes(
data=self._value3.unsafe_ptr(),
diff --git a/stdlib/test/lit.cfg.py b/stdlib/test/lit.cfg.py
index ad8ab36e9a..67d1f613b2 100644
--- a/stdlib/test/lit.cfg.py
+++ b/stdlib/test/lit.cfg.py
@@ -12,9 +12,7 @@
# ===----------------------------------------------------------------------=== #
import os
-import platform
import shutil
-
from pathlib import Path
import lit.formats
@@ -80,8 +78,9 @@ def has_not():
# with assertions enabled.
config.substitutions.insert(1, ("%bare-mojo", "mojo"))
- # NOTE: Right now this is the same as %mojo but we should start testing
+ # NOTE: Right now these are the same as %mojo but we should start testing
# with debug info as well
+ config.substitutions.insert(0, ("%mojo-no-debug-no-assert", "mojo"))
config.substitutions.insert(0, ("%mojo-no-debug", base_mojo_command))
# The `mojo` nightly compiler ships with its own `stdlib.mojopkg`. For the
diff --git a/stdlib/test/memory/test_arc.mojo b/stdlib/test/memory/test_arc.mojo
index 394b1d507f..82b5342aea 100644
--- a/stdlib/test/memory/test_arc.mojo
+++ b/stdlib/test/memory/test_arc.mojo
@@ -14,22 +14,22 @@
from collections import List
-from memory import Arc, UnsafePointer
-from testing import assert_equal, assert_false, assert_true
+from memory import ArcPointer, UnsafePointer
from test_utils import ObservableDel
+from testing import assert_equal, assert_false, assert_true
def test_basic():
- var p = Arc(4)
+ var p = ArcPointer(4)
var p2 = p
p2[] = 3
assert_equal(3, p[])
def test_is():
- var p = Arc(3)
+ var p = ArcPointer(3)
var p2 = p
- var p3 = Arc(3)
+ var p3 = ArcPointer(3)
assert_true(p is p2)
assert_false(p is not p2)
assert_false(p is p3)
@@ -38,12 +38,12 @@ def test_is():
def test_deleter_not_called_until_no_references():
var deleted = False
- var p = Arc(ObservableDel(UnsafePointer.address_of(deleted)))
+ var p = ArcPointer(ObservableDel(UnsafePointer.address_of(deleted)))
var p2 = p
_ = p^
assert_false(deleted)
- var vec = List[Arc[ObservableDel]]()
+ var vec = List[ArcPointer[ObservableDel]]()
vec.append(p2)
_ = p2^
assert_false(deleted)
@@ -53,13 +53,13 @@ def test_deleter_not_called_until_no_references():
def test_deleter_not_called_until_no_references_explicit_copy():
var deleted = False
- var p = Arc(ObservableDel(UnsafePointer.address_of(deleted)))
- var p2 = Arc(other=p)
+ var p = ArcPointer(ObservableDel(UnsafePointer.address_of(deleted)))
+ var p2 = ArcPointer(other=p)
_ = p^
assert_false(deleted)
- var vec = List[Arc[ObservableDel]]()
- vec.append(Arc(other=p2)^)
+ var vec = List[ArcPointer[ObservableDel]]()
+ vec.append(ArcPointer(other=p2)^)
_ = p2^
assert_false(deleted)
_ = vec^
@@ -67,8 +67,8 @@ def test_deleter_not_called_until_no_references_explicit_copy():
def test_count():
- var a = Arc(10)
- var b = Arc(other=a)
+ var a = ArcPointer(10)
+ var b = ArcPointer(other=a)
var c = a
assert_equal(3, a.count())
_ = b^
diff --git a/stdlib/test/memory/test_maybe_uninitialized.mojo b/stdlib/test/memory/test_maybe_uninitialized.mojo
index 6c02fec9b6..5dbebfd8d7 100644
--- a/stdlib/test/memory/test_maybe_uninitialized.mojo
+++ b/stdlib/test/memory/test_maybe_uninitialized.mojo
@@ -13,9 +13,9 @@
# RUN: %mojo %s
from os import abort
+
from memory import UnsafePointer
from memory.maybe_uninitialized import UnsafeMaybeUninitialized
-
from test_utils import CopyCounter, MoveCounter, ValueDestructorRecorder
from testing import assert_equal
diff --git a/stdlib/test/memory/test_memory.mojo b/stdlib/test/memory/test_memory.mojo
index 52cbe98ae4..b9f754c97d 100644
--- a/stdlib/test/memory/test_memory.mojo
+++ b/stdlib/test/memory/test_memory.mojo
@@ -12,7 +12,7 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo --debug-level full %s
-from sys import sizeof, simdwidthof
+from sys import simdwidthof, sizeof
from memory import (
AddressSpace,
diff --git a/stdlib/test/memory/test_owned_pointer.mojo b/stdlib/test/memory/test_owned_pointer.mojo
index a09b8fa59b..133dff1348 100644
--- a/stdlib/test/memory/test_owned_pointer.mojo
+++ b/stdlib/test/memory/test_owned_pointer.mojo
@@ -12,14 +12,14 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
-from testing import assert_equal, assert_false, assert_true, assert_not_equal
+from memory import OwnedPointer, UnsafePointer
from test_utils import (
- MoveOnly,
ExplicitCopyOnly,
ImplicitCopyOnly,
+ MoveOnly,
ObservableDel,
)
-from memory import OwnedPointer, UnsafePointer
+from testing import assert_equal, assert_false, assert_not_equal, assert_true
def test_basic_ref():
diff --git a/stdlib/test/utils/test_span.mojo b/stdlib/test/memory/test_span.mojo
similarity index 92%
rename from stdlib/test/utils/test_span.mojo
rename to stdlib/test/memory/test_span.mojo
index 79cd780401..92c49210c6 100644
--- a/stdlib/test/utils/test_span.mojo
+++ b/stdlib/test/memory/test_span.mojo
@@ -13,10 +13,9 @@
# RUN: %mojo %s
from collections import InlineArray, List
-from memory import UnsafePointer
-from testing import assert_equal, assert_true
-from utils import Span
+from memory import UnsafePointer, Span
+from testing import assert_equal, assert_true
def test_span_list_int():
@@ -137,19 +136,6 @@ def test_span_slice():
assert_equal(res[0], 2)
assert_equal(res[1], 3)
assert_equal(res[2], 4)
- # Test slicing with negative step
- res = s[1::-1]
- assert_equal(res[0], 2)
- assert_equal(res[1], 1)
- res.unsafe_ptr().free()
- res = s[2:1:-1]
- assert_equal(res[0], 3)
- assert_equal(len(res), 1)
- res.unsafe_ptr().free()
- res = s[5:1:-2]
- assert_equal(res[0], 5)
- assert_equal(res[1], 3)
- res.unsafe_ptr().free()
def test_copy_from():
@@ -203,6 +189,16 @@ def test_ref():
assert_true(s.as_ref() == Pointer.address_of(l.unsafe_ptr()[]))
+def test_reversed():
+ var forward = InlineArray[Int, 3](1, 2, 3)
+ var backward = InlineArray[Int, 3](3, 2, 1)
+ var s = Span[Int](forward)
+ var i = 0
+ for num in reversed(s):
+ assert_equal(num[], backward[i])
+ i += 1
+
+
def main():
test_span_list_int()
test_span_list_str()
@@ -214,3 +210,4 @@ def main():
test_bool()
test_fill()
test_ref()
+ test_reversed()
diff --git a/stdlib/test/memory/test_unsafepointer.mojo b/stdlib/test/memory/test_unsafepointer.mojo
index 657fc02b81..d6339f7e18 100644
--- a/stdlib/test/memory/test_unsafepointer.mojo
+++ b/stdlib/test/memory/test_unsafepointer.mojo
@@ -12,9 +12,9 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
-from memory import UnsafePointer, AddressSpace
+from memory import AddressSpace, UnsafePointer
from test_utils import ExplicitCopyOnly, MoveCounter
-from testing import assert_equal, assert_not_equal, assert_true, assert_false
+from testing import assert_equal, assert_false, assert_not_equal, assert_true
struct MoveOnlyType(Movable):
@@ -178,10 +178,10 @@ def test_comparisons():
def test_unsafepointer_address_space():
- var p1 = UnsafePointer[Int, AddressSpace(0)].alloc(1)
+ var p1 = UnsafePointer[Int, address_space = AddressSpace(0)].alloc(1)
p1.free()
- var p2 = UnsafePointer[Int, AddressSpace.GENERIC].alloc(1)
+ var p2 = UnsafePointer[Int, address_space = AddressSpace.GENERIC].alloc(1)
p2.free()
diff --git a/stdlib/test/os/path/test_basename.mojo b/stdlib/test/os/path/test_basename.mojo
new file mode 100644
index 0000000000..acda789eca
--- /dev/null
+++ b/stdlib/test/os/path/test_basename.mojo
@@ -0,0 +1,85 @@
+# ===----------------------------------------------------------------------=== #
+# Copyright (c) 2024, Modular Inc. All rights reserved.
+#
+# Licensed under the Apache License v2.0 with LLVM Exceptions:
+# https://llvm.org/LICENSE.txt
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ===----------------------------------------------------------------------=== #
+# RUN: %mojo %s
+
+from os.path import basename
+from pathlib import Path
+
+from builtin._location import __source_location
+from testing import assert_equal
+
+
+def main():
+ # Root directories
+ assert_equal("", basename("/"))
+
+ # Empty strings
+ assert_equal("", basename(""))
+
+ # Current directory (matching behavior of python, doesn't resolve `..` etc.)
+ assert_equal(".", basename("."))
+
+ # Parent directory
+ assert_equal("..", basename(".."))
+
+ # Absolute paths
+ assert_equal("file", basename("/file"))
+ assert_equal("file.txt", basename("/file.txt"))
+ assert_equal("file", basename("/dir/file"))
+ assert_equal("file", basename("/dir/subdir/file"))
+
+ # Relative paths
+ assert_equal("file", basename("dir/file"))
+ assert_equal("file", basename("dir/subdir/file"))
+ assert_equal("file", basename("file"))
+
+ # Trailing slashes
+ assert_equal("", basename("/path/to/"))
+ assert_equal("", basename("/path/to/dir/"))
+
+ # Multiple slashes
+ assert_equal("file", basename("/path/to//file"))
+ assert_equal("to", basename("/path//to"))
+
+ # Paths with spaces
+ assert_equal("file", basename("/path to/file"))
+ assert_equal("file", basename("/path to/dir/file"))
+
+ # Paths with special characters
+ assert_equal("file", basename("/path-to/file"))
+ assert_equal("file", basename("/path_to/dir/file"))
+
+ # Paths with dots
+ assert_equal("file", basename("/path/./to/file"))
+ assert_equal("file", basename("/path/../to/file"))
+
+ # Paths with double dots
+ assert_equal("file", basename("/path/../file"))
+ assert_equal("file", basename("/path/to/../file"))
+
+ # Root and relative mixed
+ assert_equal("file", basename("/dir/./file"))
+ assert_equal("file", basename("/dir/subdir/../file"))
+
+ # Edge cases
+ assert_equal("file", basename("/./file"))
+ assert_equal("file", basename("/../file"))
+
+ # Unix hidden files
+ assert_equal(".hiddenfile", basename("/path/to/.hiddenfile"))
+ assert_equal(".hiddenfile", basename("/path/to/dir/.hiddenfile"))
+
+ assert_equal("test_basename.mojo", basename(__source_location().file_name))
+ assert_equal(
+ "some_file.txt", basename(Path.home() / "dir" / "some_file.txt")
+ )
diff --git a/stdlib/test/os/path/test_expanduser.mojo b/stdlib/test/os/path/test_expanduser.mojo
index 78764e6bf1..7041eefdd6 100644
--- a/stdlib/test/os/path/test_expanduser.mojo
+++ b/stdlib/test/os/path/test_expanduser.mojo
@@ -14,11 +14,12 @@
import os
+from os.env import getenv, setenv
from os.path import expanduser, join
-from os.env import setenv, getenv
-from testing import assert_equal, assert_raises, assert_true
from sys.info import os_is_windows
+from testing import assert_equal, assert_raises, assert_true
+
fn get_user_path() -> String:
@parameter
diff --git a/stdlib/test/os/path/test_expandvars.mojo b/stdlib/test/os/path/test_expandvars.mojo
index d81746d88c..fead55656d 100644
--- a/stdlib/test/os/path/test_expandvars.mojo
+++ b/stdlib/test/os/path/test_expandvars.mojo
@@ -14,6 +14,7 @@
import os
from os.path import expandvars
+
from testing import assert_equal
@@ -21,7 +22,7 @@ from testing import assert_equal
struct EnvVar:
var name: String
- fn __init__(out self, name: String, value: String) -> None:
+ fn __init__(out self, name: String, value: String):
self.name = name
_ = os.setenv(name, value)
diff --git a/stdlib/test/os/path/test_getsize.mojo b/stdlib/test/os/path/test_getsize.mojo
index 6975d91335..1aa50e9bfb 100644
--- a/stdlib/test/os/path/test_getsize.mojo
+++ b/stdlib/test/os/path/test_getsize.mojo
@@ -14,6 +14,7 @@
from os.path import getsize
from tempfile import NamedTemporaryFile
+
from testing import assert_equal
diff --git a/stdlib/test/os/path/test_split.mojo b/stdlib/test/os/path/test_split.mojo
index eaa6c008ea..0ef994827b 100644
--- a/stdlib/test/os/path/test_split.mojo
+++ b/stdlib/test/os/path/test_split.mojo
@@ -13,7 +13,7 @@
# RUN: %mojo %s
import os
-from os.path import split, expanduser
+from os.path import expanduser, split
from pathlib import Path
from builtin._location import __source_location
diff --git a/stdlib/test/os/path/test_splitroot.mojo b/stdlib/test/os/path/test_splitroot.mojo
new file mode 100644
index 0000000000..fddf23677c
--- /dev/null
+++ b/stdlib/test/os/path/test_splitroot.mojo
@@ -0,0 +1,88 @@
+# ===----------------------------------------------------------------------=== #
+# Copyright (c) 2024, Modular Inc. All rights reserved.
+#
+# Licensed under the Apache License v2.0 with LLVM Exceptions:
+# https://llvm.org/LICENSE.txt
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ===----------------------------------------------------------------------=== #
+# RUN: %mojo %s
+
+import os
+from os.path import splitroot
+
+from testing import assert_equal
+
+
+def test_absolute_path():
+ drive, root, tail = splitroot("/usr/lib/file.txt")
+ assert_equal(drive, "")
+ assert_equal(root, "/")
+ assert_equal(tail, "usr/lib/file.txt")
+
+ drive, root, tail = splitroot("//usr/lib/file.txt")
+ assert_equal(drive, "")
+ assert_equal(root, "//")
+ assert_equal(tail, "usr/lib/file.txt")
+
+ drive, root, tail = splitroot("///usr/lib/file.txt")
+ assert_equal(drive, "")
+ assert_equal(root, "/")
+ assert_equal(tail, "//usr/lib/file.txt")
+
+
+def test_relative_path():
+ drive, root, tail = splitroot("usr/lib/file.txt")
+ assert_equal(drive, "")
+ assert_equal(root, "")
+ assert_equal(tail, "usr/lib/file.txt")
+
+ drive, root, tail = splitroot(".")
+ assert_equal(drive, "")
+ assert_equal(root, "")
+ assert_equal(tail, ".")
+
+ drive, root, tail = splitroot("..")
+ assert_equal(drive, "")
+ assert_equal(root, "")
+ assert_equal(tail, "..")
+
+ drive, root, tail = splitroot("entire/.//.tail/..//captured////")
+ assert_equal(drive, "")
+ assert_equal(root, "")
+ assert_equal(tail, "entire/.//.tail/..//captured////")
+
+
+def test_root_directory():
+ drive, root, tail = splitroot("/")
+ assert_equal(drive, "")
+ assert_equal(root, "/")
+ assert_equal(tail, "")
+
+ drive, root, tail = splitroot("//")
+ assert_equal(drive, "")
+ assert_equal(root, "//")
+ assert_equal(tail, "")
+
+ drive, root, tail = splitroot("///")
+ assert_equal(drive, "")
+ assert_equal(root, "/")
+ assert_equal(tail, "//")
+
+
+def test_empty_path():
+ drive, root, tail = splitroot("")
+ assert_equal(drive, "")
+ assert_equal(root, "")
+ assert_equal(tail, "")
+
+
+def main():
+ test_absolute_path()
+ test_relative_path()
+ test_root_directory()
+ test_empty_path()
diff --git a/stdlib/test/os/test_no_trap.mojo b/stdlib/test/os/test_no_trap.mojo
index 3ccfd1a230..8c36b634f1 100644
--- a/stdlib/test/os/test_no_trap.mojo
+++ b/stdlib/test/os/test_no_trap.mojo
@@ -14,8 +14,8 @@
# We pass an_argument here to avoid the compiler from optimizing the code
# away.
-from sys import argv
from os import abort
+from sys import argv
# CHECK-LABEL: OK
diff --git a/stdlib/test/os/test_remove.mojo b/stdlib/test/os/test_remove.mojo
index 820e1d21bb..ccd9382ad3 100644
--- a/stdlib/test/os/test_remove.mojo
+++ b/stdlib/test/os/test_remove.mojo
@@ -12,7 +12,7 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
-from os import remove, unlink, PathLike
+from os import PathLike, remove, unlink
from os.path import exists
from pathlib import Path
diff --git a/stdlib/test/pwd/test_pwd.mojo b/stdlib/test/pwd/test_pwd.mojo
index 0cab2ff11f..14f3946a87 100644
--- a/stdlib/test/pwd/test_pwd.mojo
+++ b/stdlib/test/pwd/test_pwd.mojo
@@ -12,9 +12,10 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
-import pwd
import os
-from testing import assert_equal, assert_true, assert_raises
+import pwd
+
+from testing import assert_equal, assert_raises, assert_true
def test_pwuid():
diff --git a/stdlib/test/python/module_for_test_python_object_dunder_contains.py b/stdlib/test/python/module_for_test_python_object_dunder_contains.py
new file mode 100644
index 0000000000..40ec598dee
--- /dev/null
+++ b/stdlib/test/python/module_for_test_python_object_dunder_contains.py
@@ -0,0 +1,40 @@
+# ===----------------------------------------------------------------------=== #
+# Copyright (c) 2024, Modular Inc. All rights reserved.
+#
+# Licensed under the Apache License v2.0 with LLVM Exceptions:
+# https://llvm.org/LICENSE.txt
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ===----------------------------------------------------------------------=== #
+
+
+class Class_no_iterable_no_contains:
+ x = 1
+
+
+class Class_no_iterable_but_contains:
+ x = 123
+
+ def __contains__(self, rhs):
+ return rhs == self.x
+
+
+class Class_iterable_no_contains:
+ def __init__(self):
+ self.data = [123, 456]
+
+ def __iter__(self):
+ self.i = 0
+ return self
+
+ def __next__(self):
+ if self.i >= len(self.data):
+ raise StopIteration
+ else:
+ tmp = self.data[self.i]
+ self.i += 1
+ return tmp
diff --git a/stdlib/test/python/my_module.py b/stdlib/test/python/my_module.py
index c78c39556e..8147b0a382 100644
--- a/stdlib/test/python/my_module.py
+++ b/stdlib/test/python/my_module.py
@@ -25,8 +25,7 @@ def __init__(self, bar):
class AbstractPerson(ABC):
@abstractmethod
- def method(self):
- ...
+ def method(self): ...
def my_function(name):
diff --git a/stdlib/test/python/test_ownership.mojo b/stdlib/test/python/test_ownership.mojo
index b2f1203332..ec7a71d89e 100644
--- a/stdlib/test/python/test_ownership.mojo
+++ b/stdlib/test/python/test_ownership.mojo
@@ -17,42 +17,42 @@ from python import Python, PythonObject
from testing import assert_equal
-fn test_import(inout python: Python) raises:
+fn test_import(mut python: Python) raises:
var my_module: PythonObject = Python.import_module("my_module")
var py_string = my_module.my_function("Hello")
var str = String(python.__str__(py_string))
assert_equal(str, "Formatting the string from Lit with Python: Hello")
-fn test_list(inout python: Python) raises:
+fn test_list(mut python: Python) raises:
var b: PythonObject = Python.import_module("builtins")
var my_list = PythonObject([1, 2.34, "False"])
var py_string = str(my_list)
assert_equal(py_string, "[1, 2.34, 'False']")
-fn test_tuple(inout python: Python) raises:
+fn test_tuple(mut python: Python) raises:
var b: PythonObject = Python.import_module("builtins")
var my_tuple = PythonObject((1, 2.34, "False"))
var py_string = str(my_tuple)
assert_equal(py_string, "(1, 2.34, 'False')")
-fn test_call_ownership(inout python: Python) raises:
+fn test_call_ownership(mut python: Python) raises:
var obj: PythonObject = [1, "5"]
var py_string = str(obj)
var string = python.__str__(py_string)
assert_equal(string, "[1, '5']")
-fn test_getitem_ownership(inout python: Python) raises:
+fn test_getitem_ownership(mut python: Python) raises:
var obj: PythonObject = [1, "5"]
var py_string = str(obj[1])
var string = python.__str__(py_string)
assert_equal(string, "5")
-fn test_getattr_ownership(inout python: Python) raises:
+fn test_getattr_ownership(mut python: Python) raises:
var my_module: PythonObject = Python.import_module("my_module")
var obj = my_module.Foo(4)
var py_string = str(obj.bar)
diff --git a/stdlib/test/python/test_python_cpython.mojo b/stdlib/test/python/test_python_cpython.mojo
new file mode 100644
index 0000000000..77d4bfdb59
--- /dev/null
+++ b/stdlib/test/python/test_python_cpython.mojo
@@ -0,0 +1,40 @@
+# ===----------------------------------------------------------------------=== #
+# Copyright (c) 2024, Modular Inc. All rights reserved.
+#
+# Licensed under the Apache License v2.0 with LLVM Exceptions:
+# https://llvm.org/LICENSE.txt
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ===----------------------------------------------------------------------=== #
+# XFAIL: asan && !system-darwin
+# RUN: %mojo %s
+
+from python import Python, PythonObject
+from testing import assert_equal, assert_false, assert_raises, assert_true
+
+
+def test_PyObject_HasAttrString(mut python: Python):
+ var Cpython_env = python.impl._cpython
+
+ var the_object = PythonObject(0)
+ var result = Cpython_env[].PyObject_HasAttrString(
+ the_object.py_object, "__contains__"
+ )
+ assert_equal(0, result)
+
+ the_object = PythonObject([1, 2, 3])
+ result = Cpython_env[].PyObject_HasAttrString(
+ the_object.py_object, "__contains__"
+ )
+ assert_equal(1, result)
+ _ = the_object
+
+
+def main():
+ # initializing Python instance calls init_python
+ var python = Python()
+ test_PyObject_HasAttrString(python)
diff --git a/stdlib/test/python/test_python_info.mojo b/stdlib/test/python/test_python_info.mojo
index 1728a10c24..b1b7eb29e7 100644
--- a/stdlib/test/python/test_python_info.mojo
+++ b/stdlib/test/python/test_python_info.mojo
@@ -19,7 +19,7 @@ from python._cpython import PythonVersion
from testing import assert_equal
-fn test_python_version(inout python: Python) raises:
+fn test_python_version(mut python: Python) raises:
var version = "3.10.8 (main, Nov 24 2022, 08:08:27) [Clang 14.0.6 ]"
var pythonVersion = PythonVersion(version)
assert_equal(pythonVersion.major, 3)
diff --git a/stdlib/test/python/test_python_interop.mojo b/stdlib/test/python/test_python_interop.mojo
index be71cfd2dc..3e1a465628 100644
--- a/stdlib/test/python/test_python_interop.mojo
+++ b/stdlib/test/python/test_python_interop.mojo
@@ -17,7 +17,7 @@ from python.python import Python, PythonObject, _get_global_python_itf
from testing import assert_equal
-fn test_execute_python_string(inout python: Python) -> String:
+fn test_execute_python_string(mut python: Python) -> String:
try:
_ = Python.evaluate("print('evaluated by PyRunString')")
return str(Python.evaluate("'a' + 'b'"))
@@ -25,7 +25,7 @@ fn test_execute_python_string(inout python: Python) -> String:
return str(e)
-fn test_local_import(inout python: Python) -> String:
+fn test_local_import(mut python: Python) -> String:
try:
var my_module: PythonObject = Python.import_module("my_module")
if my_module:
@@ -37,7 +37,7 @@ fn test_local_import(inout python: Python) -> String:
return str(e)
-fn test_dynamic_import(inout python: Python, times: Int = 1) -> String:
+fn test_dynamic_import(mut python: Python, times: Int = 1) -> String:
alias INLINE_MODULE = """
called_already = False
def hello(name):
@@ -56,7 +56,7 @@ def hello(name):
return str(e)
-fn test_call(inout python: Python) -> String:
+fn test_call(mut python: Python) -> String:
try:
var my_module: PythonObject = Python.import_module("my_module")
return str(
diff --git a/stdlib/test/python/test_python_object.mojo b/stdlib/test/python/test_python_object.mojo
index b6e5fc38c1..b1c6799157 100644
--- a/stdlib/test/python/test_python_object.mojo
+++ b/stdlib/test/python/test_python_object.mojo
@@ -14,13 +14,14 @@
# RUN: %mojo %s
from collections import Dict
+
from python import Python, PythonObject
from testing import assert_equal, assert_false, assert_raises, assert_true
from utils import StringRef
-def test_dunder_methods(inout python: Python):
+def test_dunder_methods(mut python: Python):
var a = PythonObject(34)
var b = PythonObject(10)
@@ -575,6 +576,31 @@ fn test_py_slice() raises:
_ = with_2d[0:1][4]
+def test_contains_dunder():
+ with assert_raises(contains="'int' object is not iterable"):
+ var z = PythonObject(0)
+ _ = 5 in z
+
+ var x = PythonObject([1.1, 2.2])
+ assert_true(1.1 in x)
+ assert_false(3.3 in x)
+
+ x = PythonObject(["Hello", "World"])
+ assert_true("World" in x)
+
+ x = PythonObject((1.5, 2))
+ assert_true(1.5 in x)
+ assert_false(3.5 in x)
+
+ var y = Dict[PythonObject, PythonObject]()
+ y["A"] = "A"
+ y["B"] = 5
+ x = PythonObject(y)
+ assert_true("A" in x)
+ assert_false("C" in x)
+ assert_true("B" in x)
+
+
def main():
# initializing Python instance calls init_python
var python = Python()
@@ -592,3 +618,4 @@ def main():
test_getitem_raises()
test_setitem_raises()
test_py_slice()
+ test_contains_dunder()
diff --git a/stdlib/test/python/test_python_object_dunder_contains.mojo b/stdlib/test/python/test_python_object_dunder_contains.mojo
new file mode 100644
index 0000000000..5d4c722278
--- /dev/null
+++ b/stdlib/test/python/test_python_object_dunder_contains.mojo
@@ -0,0 +1,70 @@
+# ===----------------------------------------------------------------------=== #
+# Copyright (c) 2024, Modular Inc. All rights reserved.
+#
+# Licensed under the Apache License v2.0 with LLVM Exceptions:
+# https://llvm.org/LICENSE.txt
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ===----------------------------------------------------------------------=== #
+# XFAIL: asan && !system-darwin
+# RUN: %mojo %s
+
+from python import Python, PythonObject
+from testing import assert_equal, assert_false, assert_raises, assert_true
+from collections import Dict
+
+
+def test_contains_dunder(mut python: Python):
+ with assert_raises(contains="'int' object is not iterable"):
+ var z = PythonObject(0)
+ _ = 5 in z
+
+ var x = PythonObject([1.1, 2.2])
+ assert_true(1.1 in x)
+ assert_false(3.3 in x)
+
+ x = PythonObject(["Hello", "World"])
+ assert_true("World" in x)
+
+ x = PythonObject((1.5, 2))
+ assert_true(1.5 in x)
+ assert_false(3.5 in x)
+
+ var y = Dict[PythonObject, PythonObject]()
+ y["A"] = "A"
+ y["B"] = 5
+ x = PythonObject(y)
+ assert_true("A" in x)
+ assert_false("C" in x)
+ assert_true("B" in x)
+
+ # tests with python modules:
+ module = python.import_module(
+ "module_for_test_python_object_dunder_contains"
+ )
+
+ x = module.Class_no_iterable_but_contains()
+ assert_true(123 in x)
+
+ x = module.Class_no_iterable_no_contains()
+ with assert_raises(
+ contains="'Class_no_iterable_no_contains' object is not iterable"
+ ):
+ _ = 123 in x
+
+ x = module.Class_iterable_no_contains()
+ assert_true(123 in x)
+ assert_true(456 in x)
+ assert_false(234 in x)
+ x.data.append(234)
+ assert_true(234 in x)
+
+
+def main():
+ # initializing Python instance calls init_python
+ var python = Python()
+ test_contains_dunder(python)
diff --git a/stdlib/test/python/test_python_to_mojo.mojo b/stdlib/test/python/test_python_to_mojo.mojo
index 0fbf502b7a..d621943f9c 100644
--- a/stdlib/test/python/test_python_to_mojo.mojo
+++ b/stdlib/test/python/test_python_to_mojo.mojo
@@ -17,7 +17,7 @@ from python import Python, PythonObject
from testing import assert_equal, assert_false, assert_true
-fn test_string_to_python_to_mojo(inout python: Python) raises:
+fn test_string_to_python_to_mojo(mut python: Python) raises:
var py_string = PythonObject("mojo")
var py_string_capitalized = py_string.capitalize()
diff --git a/stdlib/test/random/test_random.mojo b/stdlib/test/random/test_random.mojo
index f1f1f6ac73..0a90b5ae89 100644
--- a/stdlib/test/random/test_random.mojo
+++ b/stdlib/test/random/test_random.mojo
@@ -12,7 +12,14 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
-from random import randn_float64, random_float64, random_si64, random_ui64, seed
+from random import (
+ randn_float64,
+ random_float64,
+ random_si64,
+ random_ui64,
+ seed,
+ shuffle,
+)
from testing import assert_equal, assert_true
@@ -73,6 +80,94 @@ def test_seed():
assert_equal(some_unsigned_integer, random_ui64(0, 255))
+def test_shuffle():
+ # TODO: Clean up with list comprehension when possible.
+
+ # Property tests
+ alias L_i = List[Int]
+ alias L_s = List[String]
+ var a = L_i(1, 2, 3, 4)
+ var b = L_i(1, 2, 3, 4)
+ var c = L_s("Random", "shuffle", "in", "Mojo")
+ var d = L_s("Random", "shuffle", "in", "Mojo")
+
+ shuffle(b)
+ assert_equal(len(a), len(b))
+ assert_true(a != b)
+ for i in range(len(b)):
+ assert_true(b[i] in a)
+
+ shuffle(d)
+ assert_equal(len(c), len(d))
+ assert_true(c != d)
+ for i in range(len(d)):
+ assert_true(d[i] in c)
+
+ var e = L_i(21)
+ shuffle(e)
+ assert_true(e == L_i(21))
+ var f = L_s("Mojo")
+ shuffle(f)
+ assert_true(f == L_s("Mojo"))
+
+ alias L_l = List[List[Int]]
+ var g = L_l()
+ var h = L_l()
+ for i in range(10):
+ g.append(L_i(i, i + 1, i + 3))
+ h.append(L_i(i, i + 1, i + 3))
+ shuffle(g)
+ # TODO: Uncomment when possible
+ # assert_true(g != h)
+ assert_equal(len(g), len(h))
+ for i in range(10):
+ # Currently, the below does not compile.
+ # assert_true(g.__contains__(L_i(i, i + 1, i + 3)))
+ var target: List[Int] = L_i(i, i + 1, i + 3)
+ var found = False
+ for j in range(len(g)):
+ if g[j] == target:
+ found = True
+ break
+ assert_true(found)
+
+ alias L_l_s = List[List[String]]
+ var i = L_l_s()
+ var j = L_l_s()
+ for x in range(10):
+ i.append(L_s(str(x), str(x + 1), str(x + 3)))
+ j.append(L_s(str(x), str(x + 1), str(x + 3)))
+ shuffle(i)
+ # TODO: Uncomment when possible
+ # assert_true(g != h)
+ assert_equal(len(i), len(j))
+ for x in range(10):
+ var target: List[String] = L_s(str(x), str(x + 1), str(x + 3))
+ var found = False
+ for y in range(len(i)):
+ if j[y] == target:
+ found = True
+ break
+ assert_true(found)
+
+ # Given the number of permutations of size 1000 is 1000!,
+ # we rely on the assertion that a truly random shuffle should not
+ # result in the same order as the to pre-shuffle list with extremely
+ # high probability.
+ var l = L_i()
+ var m = L_i()
+ for i in range(1000):
+ l.append(i)
+ m.append(i)
+ shuffle(l)
+ assert_equal(len(l), len(m))
+ assert_true(l != m)
+ shuffle(m)
+ assert_equal(len(l), len(m))
+ assert_true(l != m)
+
+
def main():
test_random()
test_seed()
+ test_shuffle()
diff --git a/stdlib/test/sys/test_c_types.mojo b/stdlib/test/sys/test_c_types.mojo
index 61029f21c9..f2610aa453 100644
--- a/stdlib/test/sys/test_c_types.mojo
+++ b/stdlib/test/sys/test_c_types.mojo
@@ -12,8 +12,8 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
-from sys.info import os_is_linux, os_is_macos, os_is_windows, is_64bit, is_32bit
from sys.ffi import c_int, c_long, c_long_long
+from sys.info import is_32bit, is_64bit, os_is_linux, os_is_macos, os_is_windows
from testing import assert_equal, assert_true
diff --git a/stdlib/test/sys/test_intrinsics.mojo b/stdlib/test/sys/test_intrinsics.mojo
index 417b5bd23b..2bc51de5c6 100644
--- a/stdlib/test/sys/test_intrinsics.mojo
+++ b/stdlib/test/sys/test_intrinsics.mojo
@@ -20,7 +20,7 @@ from sys import (
strided_load,
strided_store,
)
-from sys.intrinsics import likely, unlikely, assume
+from sys.intrinsics import assume, likely, unlikely
from memory import UnsafePointer, memset_zero
from testing import assert_equal
diff --git a/stdlib/test/sys/test_paramenv.mojo b/stdlib/test/sys/test_paramenv.mojo
index abdbd3c266..b1e3cadeb6 100644
--- a/stdlib/test/sys/test_paramenv.mojo
+++ b/stdlib/test/sys/test_paramenv.mojo
@@ -12,7 +12,7 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo -D bar=99 -D baz=hello -D foo=11 -D my_true=True -D my_false=false %s
-from sys import env_get_int, env_get_bool, env_get_string, is_defined
+from sys import env_get_bool, env_get_int, env_get_string, is_defined
from testing import assert_equal, assert_false, assert_true
diff --git a/stdlib/test/tempfile/test_tempfile.mojo b/stdlib/test/tempfile/test_tempfile.mojo
index c186776e6e..d84ac25554 100644
--- a/stdlib/test/tempfile/test_tempfile.mojo
+++ b/stdlib/test/tempfile/test_tempfile.mojo
@@ -55,7 +55,7 @@ struct TempEnvWithCleanup:
"""Function called after the context manager exits if an error occurs."""
fn __init__(
- inout self,
+ mut self,
vars_to_set: Dict[String, String],
clean_up_function: fn () raises -> None,
):
@@ -63,20 +63,20 @@ struct TempEnvWithCleanup:
self._vars_back = Dict[String, String]()
self.clean_up_function = clean_up_function
- def __enter__(inout self):
+ def __enter__(mut self):
for key_value in self.vars_to_set.items():
var key = key_value[].key
var value = key_value[].value
self._vars_back[key] = os.getenv(key)
_ = os.setenv(key, value, overwrite=True)
- fn __exit__(inout self):
+ fn __exit__(mut self):
for key_value in self.vars_to_set.items():
var key = key_value[].key
var value = key_value[].value
_ = os.setenv(key, value, overwrite=True)
- def __exit__(inout self, error: Error) -> Bool:
+ def __exit__(mut self, error: Error) -> Bool:
self.__exit__()
self.clean_up_function()
return False
diff --git a/stdlib/test/testing/test_assertion.mojo b/stdlib/test/testing/test_assertion.mojo
index 6f07f4d3b9..35283b7088 100644
--- a/stdlib/test/testing/test_assertion.mojo
+++ b/stdlib/test/testing/test_assertion.mojo
@@ -12,20 +12,20 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo -debug-level full %s
+from builtin._location import _SourceLocation
+from python import PythonObject
from testing import (
assert_almost_equal,
assert_equal,
assert_false,
+ assert_is,
+ assert_is_not,
assert_not_equal,
assert_raises,
assert_true,
- assert_is,
- assert_is_not,
)
from utils.numerics import inf, nan
-from builtin._location import _SourceLocation
-from python import PythonObject
def test_assert_messages():
diff --git a/stdlib/test/time/test_time.mojo b/stdlib/test/time/test_time.mojo
index 6be7e4e60a..0148bfeeef 100644
--- a/stdlib/test/time/test_time.mojo
+++ b/stdlib/test/time/test_time.mojo
@@ -14,12 +14,11 @@
from sys import os_is_windows
from time import (
- now,
+ monotonic,
perf_counter,
perf_counter_ns,
sleep,
time_function,
- monotonic,
)
from testing import assert_true
@@ -28,7 +27,7 @@ from testing import assert_true
@always_inline
@parameter
fn time_me():
- sleep(1)
+ sleep(1.0)
@always_inline
@@ -50,7 +49,7 @@ fn time_templated_function[
fn time_capturing_function(iters: Int) -> Int:
@parameter
fn time_fn():
- sleep(1)
+ sleep(1.0)
return time_function[time_fn]()
@@ -60,7 +59,6 @@ fn test_time() raises:
assert_true(perf_counter() > 0)
assert_true(perf_counter_ns() > 0)
- assert_true(now() > 0)
assert_true(monotonic() > 0)
var t1 = time_function[time_me]()
diff --git a/stdlib/test/utils/test_format.mojo b/stdlib/test/utils/test_format.mojo
index e15d744a88..975d26464b 100644
--- a/stdlib/test/utils/test_format.mojo
+++ b/stdlib/test/utils/test_format.mojo
@@ -34,7 +34,7 @@ struct Point(Writable, Stringable):
var y: Int
@no_inline
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
writer.write("Point(", self.x, ", ", self.y, ")")
@no_inline
diff --git a/stdlib/test/utils/test_format_to_stdout.mojo b/stdlib/test/utils/test_format_to_stdout.mojo
index 256146aeff..fed40ec33c 100644
--- a/stdlib/test/utils/test_format_to_stdout.mojo
+++ b/stdlib/test/utils/test_format_to_stdout.mojo
@@ -12,9 +12,10 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo -debug-level full %s
-from utils import Writable, Writer
import sys
+from utils import Writable, Writer
+
fn main() raises:
test_write_to_stdout()
@@ -25,7 +26,7 @@ struct Point(Writable):
var x: Int
var y: Int
- fn write_to[W: Writer](self, inout writer: W):
+ fn write_to[W: Writer](self, mut writer: W):
writer.write("Point(", self.x, ", ", self.y, ")")
diff --git a/stdlib/test/utils/test_inlined_string.mojo b/stdlib/test/utils/test_inlined_string.mojo
index 11712e5925..b2bc0d1956 100644
--- a/stdlib/test/utils/test_inlined_string.mojo
+++ b/stdlib/test/utils/test_inlined_string.mojo
@@ -13,9 +13,10 @@
# REQUIRES: disabled
# RUN: %mojo --debug-level full %s
+from os import abort
+
from testing import assert_equal, assert_true
-from os import abort
from utils import InlineString
from utils.inline_string import _FixedString
diff --git a/stdlib/test/utils/test_select.mojo b/stdlib/test/utils/test_select.mojo
index cd82f84a2e..dc1911c98a 100644
--- a/stdlib/test/utils/test_select.mojo
+++ b/stdlib/test/utils/test_select.mojo
@@ -12,9 +12,10 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
-from utils._select import _select_register_value
from testing import assert_equal
+from utils._select import _select_register_value
+
def test_select_register_value():
assert_equal(_select_register_value(True, 42, 100), 42)
diff --git a/stdlib/test/utils/test_static_tuple.mojo b/stdlib/test/utils/test_static_tuple.mojo
new file mode 100644
index 0000000000..b2f46d55af
--- /dev/null
+++ b/stdlib/test/utils/test_static_tuple.mojo
@@ -0,0 +1,56 @@
+# ===----------------------------------------------------------------------=== #
+# Copyright (c) 2024, Modular Inc. All rights reserved.
+#
+# Licensed under the Apache License v2.0 with LLVM Exceptions:
+# https://llvm.org/LICENSE.txt
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ===----------------------------------------------------------------------=== #
+# RUN: %mojo %s
+
+from testing import assert_equal
+from utils import StaticTuple
+
+
+def test_getitem():
+ # Should be constructible from a single element
+ # as well as a variadic list of elements.
+ var tup1 = StaticTuple[Int, 1](1)
+ assert_equal(tup1[0], 1)
+
+ var tup2 = StaticTuple[Int, 2](1, 1)
+ assert_equal(tup2[0], 1)
+ assert_equal(tup2[1], 1)
+
+ var tup3 = StaticTuple[Int, 3](1, 2, 3)
+ assert_equal(tup3[0], 1)
+ assert_equal(tup3[1], 2)
+ assert_equal(tup3[2], 3)
+
+ assert_equal(tup1[Int(0)], 1)
+
+
+def test_setitem():
+ var t = StaticTuple[Int, 3](1, 2, 3)
+
+ t[0] = 100
+ assert_equal(t[0], 100)
+
+ t[1] = 200
+ assert_equal(t[1], 200)
+
+ t[2] = 300
+ assert_equal(t[2], 300)
+
+ alias idx: Int = 0
+ t.__setitem__[idx](400)
+ assert_equal(t[0], 400)
+
+
+def main():
+ test_getitem()
+ test_setitem()
diff --git a/stdlib/test/utils/test_string_slice.mojo b/stdlib/test/utils/test_string_slice.mojo
index 1a47a96a5b..2fa18c44f2 100644
--- a/stdlib/test/utils/test_string_slice.mojo
+++ b/stdlib/test/utils/test_string_slice.mojo
@@ -12,9 +12,10 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
-from testing import assert_equal, assert_true, assert_false
+from testing import assert_equal, assert_false, assert_true
-from utils import Span, StringSlice
+from memory import Span
+from utils import StringSlice
from utils._utf8_validation import _is_valid_utf8
from utils.string_slice import _count_utf8_continuation_bytes
@@ -520,7 +521,103 @@ def test_iter():
assert_equal(4, idx)
-fn main() raises:
+def test_rstrip():
+ # with default rstrip chars
+ var empty_string = "".as_string_slice()
+ assert_true(empty_string.rstrip() == "")
+
+ var space_string = " \t\n\r\v\f ".as_string_slice()
+ assert_true(space_string.rstrip() == "")
+
+ var str0 = " n ".as_string_slice()
+ assert_true(str0.rstrip() == " n")
+
+ var str1 = "string".as_string_slice()
+ assert_true(str1.rstrip() == "string")
+
+ var str2 = "something \t\n\t\v\f".as_string_slice()
+ assert_true(str2.rstrip() == "something")
+
+ # with custom chars for rstrip
+ var str3 = "mississippi".as_string_slice()
+ assert_true(str3.rstrip("sip") == "m")
+
+ var str4 = "mississippimississippi \n ".as_string_slice()
+ assert_true(str4.rstrip("sip ") == "mississippimississippi \n")
+ assert_true(str4.rstrip("sip \n") == "mississippim")
+
+
+def test_lstrip():
+ # with default lstrip chars
+ var empty_string = "".as_string_slice()
+ assert_true(empty_string.lstrip() == "")
+
+ var space_string = " \t\n\r\v\f ".as_string_slice()
+ assert_true(space_string.lstrip() == "")
+
+ var str0 = " n ".as_string_slice()
+ assert_true(str0.lstrip() == "n ")
+
+ var str1 = "string".as_string_slice()
+ assert_true(str1.lstrip() == "string")
+
+ var str2 = " \t\n\t\v\fsomething".as_string_slice()
+ assert_true(str2.lstrip() == "something")
+
+ # with custom chars for lstrip
+ var str3 = "mississippi".as_string_slice()
+ assert_true(str3.lstrip("mis") == "ppi")
+
+ var str4 = " \n mississippimississippi".as_string_slice()
+ assert_true(str4.lstrip("mis ") == "\n mississippimississippi")
+ assert_true(str4.lstrip("mis \n") == "ppimississippi")
+
+
+def test_strip():
+ # with default strip chars
+ var empty_string = "".as_string_slice()
+ assert_true(empty_string.strip() == "")
+ alias comp_empty_string_stripped = "".as_string_slice().strip()
+ assert_true(comp_empty_string_stripped == "")
+
+ var space_string = " \t\n\r\v\f ".as_string_slice()
+ assert_true(space_string.strip() == "")
+ alias comp_space_string_stripped = " \t\n\r\v\f ".as_string_slice().strip()
+ assert_true(comp_space_string_stripped == "")
+
+ var str0 = " n ".as_string_slice()
+ assert_true(str0.strip() == "n")
+ alias comp_str0_stripped = " n ".as_string_slice().strip()
+ assert_true(comp_str0_stripped == "n")
+
+ var str1 = "string".as_string_slice()
+ assert_true(str1.strip() == "string")
+ alias comp_str1_stripped = ("string").strip()
+ assert_true(comp_str1_stripped == "string")
+
+ var str2 = " \t\n\t\v\fsomething \t\n\t\v\f".as_string_slice()
+ alias comp_str2_stripped = (" \t\n\t\v\fsomething \t\n\t\v\f").strip()
+ assert_true(str2.strip() == "something")
+ assert_true(comp_str2_stripped == "something")
+
+ # with custom strip chars
+ var str3 = "mississippi".as_string_slice()
+ assert_true(str3.strip("mips") == "")
+ assert_true(str3.strip("mip") == "ssiss")
+ alias comp_str3_stripped = "mississippi".as_string_slice().strip("mips")
+ assert_true(comp_str3_stripped == "")
+
+ var str4 = " \n mississippimississippi \n ".as_string_slice()
+ assert_true(str4.strip(" ") == "\n mississippimississippi \n")
+ assert_true(str4.strip("\nmip ") == "ssissippimississ")
+
+ alias comp_str4_stripped = (
+ " \n mississippimississippi \n ".as_string_slice().strip(" ")
+ )
+ assert_true(comp_str4_stripped == "\n mississippimississippi \n")
+
+
+def main():
test_string_literal_byte_span()
test_string_byte_span()
test_heap_string_from_string_slice()
@@ -538,4 +635,7 @@ fn main() raises:
test_combination_10_good_10_bad_utf8_sequences()
test_count_utf8_continuation_bytes()
test_splitlines()
+ test_rstrip()
+ test_lstrip()
+ test_strip()
test_iter()
diff --git a/stdlib/test/utils/test_tuple.mojo b/stdlib/test/utils/test_tuple.mojo
index b38a4e0e75..0748552be0 100644
--- a/stdlib/test/utils/test_tuple.mojo
+++ b/stdlib/test/utils/test_tuple.mojo
@@ -12,28 +12,11 @@
# ===----------------------------------------------------------------------=== #
# RUN: %mojo %s
-from testing import assert_equal, assert_false, assert_true
-
from memory import UnsafePointer
-from utils import IndexList, StaticTuple
from test_utils import ValueDestructorRecorder
+from testing import assert_equal, assert_false, assert_true
-
-def test_static_tuple():
- var tup1 = StaticTuple[Int, 1](1)
- assert_equal(tup1[0], 1)
-
- var tup2 = StaticTuple[Int, 2](1, 1)
- assert_equal(tup2[0], 1)
- assert_equal(tup2[1], 1)
-
- var tup3 = StaticTuple[Int, 3](1, 2, 3)
- assert_equal(tup3[0], 1)
- assert_equal(tup3[1], 2)
- assert_equal(tup3[2], 3)
-
- assert_equal(tup3[0], 1)
- assert_equal(tup3[Int(0)], 1)
+from utils import IndexList, StaticTuple
def test_static_int_tuple():
@@ -72,6 +55,5 @@ def test_tuple_literal():
def main():
- test_static_tuple()
test_static_int_tuple()
test_tuple_literal()
diff --git a/stdlib/test/utils/test_variant.mojo b/stdlib/test/utils/test_variant.mojo
index 2428ac18a7..f07b3aa099 100644
--- a/stdlib/test/utils/test_variant.mojo
+++ b/stdlib/test/utils/test_variant.mojo
@@ -15,8 +15,8 @@
from sys.ffi import _Global
from memory import UnsafePointer
-from testing import assert_equal, assert_false, assert_true
from test_utils import ObservableDel
+from testing import assert_equal, assert_false, assert_true
from utils import Variant