mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 21:39:07 +00:00
Add soa
crate
This commit is contained in:
parent
7df1142455
commit
ece46a28d0
7 changed files with 201 additions and 10 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -3178,6 +3178,7 @@ dependencies = [
|
|||
"roc_parse",
|
||||
"roc_region",
|
||||
"roc_serialize",
|
||||
"soa",
|
||||
"static_assertions",
|
||||
"ven_pretty",
|
||||
]
|
||||
|
@ -3577,6 +3578,13 @@ version = "1.11.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
|
||||
|
||||
[[package]]
|
||||
name = "soa"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"pretty_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.9"
|
||||
|
|
|
@ -22,6 +22,7 @@ members = [
|
|||
"crates/valgrind",
|
||||
"crates/tracing",
|
||||
"crates/utils/*",
|
||||
"crates/soa",
|
||||
"crates/docs",
|
||||
"crates/docs_cli",
|
||||
"crates/linker",
|
||||
|
@ -74,6 +75,8 @@ inkwell = { git = "https://github.com/roc-lang/inkwell", branch = "inkwell-llvm-
|
|||
"llvm16-0",
|
||||
] }
|
||||
|
||||
soa = { path = "crates/soa" }
|
||||
|
||||
arrayvec = "0.7.2" # update roc_std/Cargo.toml on change
|
||||
backtrace = "0.3.67"
|
||||
base64-url = "1.4.13"
|
||||
|
@ -137,7 +140,10 @@ maplit = "1.0.2"
|
|||
memmap2 = "0.5.10"
|
||||
mimalloc = { version = "0.1.34", default-features = false }
|
||||
nonempty = "0.8.1"
|
||||
object = { version = "0.32.2", default-features = false, features = ["read", "write"] }
|
||||
object = { version = "0.32.2", default-features = false, features = [
|
||||
"read",
|
||||
"write",
|
||||
] }
|
||||
packed_struct = "0.10.1"
|
||||
page_size = "0.5.0"
|
||||
palette = "0.6.1"
|
||||
|
|
|
@ -12,7 +12,7 @@ use roc_module::{
|
|||
use roc_types::{
|
||||
subs::{
|
||||
self, AliasVariables, Descriptor, GetSubsSlice, OptVariable, RecordFields, Subs, SubsIndex,
|
||||
SubsSlice, TupleElems, UnionLambdas, UnionTags, Variable, VariableSubsSlice,
|
||||
SubsSlice, TupleElems, UnionLambdas, UnionTags, Variable, VariableSlice,
|
||||
},
|
||||
types::{RecordField, Uls},
|
||||
};
|
||||
|
@ -162,7 +162,7 @@ impl<'a> CopyEnv for AcrossSubs<'a> {
|
|||
fn clone_field_names(&mut self, field_names: SubsSlice<Lowercase>) -> SubsSlice<Lowercase> {
|
||||
SubsSlice::extend_new(
|
||||
&mut self.target.field_names,
|
||||
self.source.get_subs_slice(field_names).iter().cloned(),
|
||||
self.source.get_slice(field_names).iter().cloned(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -173,10 +173,7 @@ impl<'a> CopyEnv for AcrossSubs<'a> {
|
|||
) -> SubsSlice<usize> {
|
||||
SubsSlice::extend_new(
|
||||
&mut self.target.tuple_elem_indices,
|
||||
self.source
|
||||
.get_subs_slice(tuple_elem_indices)
|
||||
.iter()
|
||||
.cloned(),
|
||||
self.source.get_slice(tuple_elem_indices).iter().cloned(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -184,7 +181,7 @@ impl<'a> CopyEnv for AcrossSubs<'a> {
|
|||
fn clone_tag_names(&mut self, tag_names: SubsSlice<TagName>) -> SubsSlice<TagName> {
|
||||
SubsSlice::extend_new(
|
||||
&mut self.target.tag_names,
|
||||
self.source.get_subs_slice(tag_names).iter().cloned(),
|
||||
self.source.get_slice(tag_names).iter().cloned(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -192,7 +189,7 @@ impl<'a> CopyEnv for AcrossSubs<'a> {
|
|||
fn clone_lambda_names(&mut self, lambda_names: SubsSlice<Symbol>) -> SubsSlice<Symbol> {
|
||||
SubsSlice::extend_new(
|
||||
&mut self.target.symbol_names,
|
||||
self.source.get_subs_slice(lambda_names).iter().cloned(),
|
||||
self.source.get_slice(lambda_names).iter().cloned(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -203,7 +200,7 @@ impl<'a> CopyEnv for AcrossSubs<'a> {
|
|||
) -> SubsSlice<RecordField<()>> {
|
||||
SubsSlice::extend_new(
|
||||
&mut self.target.record_fields,
|
||||
self.source.get_subs_slice(record_fields).iter().copied(),
|
||||
self.source.get_slice(record_fields).iter().copied(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
13
crates/soa/Cargo.toml
Normal file
13
crates/soa/Cargo.toml
Normal file
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "soa"
|
||||
description = "Struct-of-Array helpers"
|
||||
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
pretty_assertions.workspace = true
|
||||
|
||||
[dev-dependencies]
|
5
crates/soa/src/lib.rs
Normal file
5
crates/soa/src/lib.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
mod soa_index;
|
||||
mod soa_slice;
|
||||
|
||||
pub use soa_index::*;
|
||||
pub use soa_slice::*;
|
50
crates/soa/src/soa_index.rs
Normal file
50
crates/soa/src/soa_index.rs
Normal file
|
@ -0,0 +1,50 @@
|
|||
use core::fmt;
|
||||
|
||||
use crate::soa_slice::Slice;
|
||||
|
||||
/// An index into an array of values, based
|
||||
/// on an offset into the array rather than a pointer.
|
||||
///
|
||||
/// Unlike a Rust pointer, this is a u32 offset
|
||||
/// rather than usize.
|
||||
pub struct Index<T> {
|
||||
pub index: u32,
|
||||
pub(crate) _marker: core::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for Index<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Index<{}>({})", core::any::type_name::<T>(), self.index)
|
||||
}
|
||||
}
|
||||
|
||||
// derive of copy and clone does not play well with PhantomData
|
||||
|
||||
impl<T> Copy for Index<T> {}
|
||||
|
||||
impl<T> Clone for Index<T> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Index<T> {
|
||||
pub const fn new(start: u32) -> Self {
|
||||
Self {
|
||||
index: start,
|
||||
_marker: core::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_new(vector: &mut Vec<T>, value: T) -> Self {
|
||||
let index = Self::new(vector.len() as _);
|
||||
|
||||
vector.push(value);
|
||||
|
||||
index
|
||||
}
|
||||
|
||||
pub const fn as_slice(self) -> Slice<T> {
|
||||
Slice::new(self.index, 1)
|
||||
}
|
||||
}
|
112
crates/soa/src/soa_slice.rs
Normal file
112
crates/soa/src/soa_slice.rs
Normal file
|
@ -0,0 +1,112 @@
|
|||
use core::fmt;
|
||||
use core::iter::Map;
|
||||
|
||||
use crate::soa_index::Index;
|
||||
|
||||
/// A slice into an array of values, based
|
||||
/// on an offset into the array rather than a pointer.
|
||||
///
|
||||
/// Unlike a Rust slice, this is a u32 offset
|
||||
/// rather than a pointer, and the length is u16.
|
||||
pub struct Slice<T> {
|
||||
pub start: u32,
|
||||
pub length: u16,
|
||||
_marker: core::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for Slice<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Slice {{ start: {}, length: {} }}",
|
||||
self.start, self.length
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// derive of copy and clone does not play well with PhantomData
|
||||
|
||||
impl<T> Copy for Slice<T> {}
|
||||
|
||||
impl<T> Clone for Slice<T> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for Slice<T> {
|
||||
fn default() -> Self {
|
||||
Self::empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Slice<T> {
|
||||
pub fn empty() -> Self {
|
||||
Self {
|
||||
start: 0,
|
||||
length: 0,
|
||||
_marker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_slice<'a>(&self, slice: &'a [T]) -> &'a [T] {
|
||||
&slice[self.indices()]
|
||||
}
|
||||
|
||||
pub fn get_slice_mut<'a>(&self, slice: &'a mut [T]) -> &'a mut [T] {
|
||||
&mut slice[self.indices()]
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn indices(&self) -> core::ops::Range<usize> {
|
||||
self.start as usize..(self.start as usize + self.length as usize)
|
||||
}
|
||||
|
||||
pub const fn len(&self) -> usize {
|
||||
self.length as usize
|
||||
}
|
||||
|
||||
pub const fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
pub const fn new(start: u32, length: u16) -> Self {
|
||||
Self {
|
||||
start,
|
||||
length,
|
||||
_marker: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend_new(vec: &mut Vec<T>, it: impl IntoIterator<Item = T>) -> Self {
|
||||
let start = vec.len();
|
||||
|
||||
vec.extend(it);
|
||||
|
||||
let end = vec.len();
|
||||
|
||||
Self::new(start as u32, (end - start) as u16)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for Slice<T> {
|
||||
type Item = Index<T>;
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
type IntoIter = Map<core::ops::Range<u32>, fn(u32) -> Self::Item>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
(self.start..(self.start + self.length as u32)).map(u32_to_index)
|
||||
}
|
||||
}
|
||||
|
||||
fn u32_to_index<T>(i: u32) -> Index<T> {
|
||||
Index {
|
||||
index: i,
|
||||
_marker: core::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GetSlice<T> {
|
||||
fn get_slice(&self, slice: Slice<T>) -> &[T];
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue