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_parse",
|
||||||
"roc_region",
|
"roc_region",
|
||||||
"roc_serialize",
|
"roc_serialize",
|
||||||
|
"soa",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
"ven_pretty",
|
"ven_pretty",
|
||||||
]
|
]
|
||||||
|
@ -3577,6 +3578,13 @@ version = "1.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
|
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "soa"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"pretty_assertions",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.4.9"
|
version = "0.4.9"
|
||||||
|
|
|
@ -22,6 +22,7 @@ members = [
|
||||||
"crates/valgrind",
|
"crates/valgrind",
|
||||||
"crates/tracing",
|
"crates/tracing",
|
||||||
"crates/utils/*",
|
"crates/utils/*",
|
||||||
|
"crates/soa",
|
||||||
"crates/docs",
|
"crates/docs",
|
||||||
"crates/docs_cli",
|
"crates/docs_cli",
|
||||||
"crates/linker",
|
"crates/linker",
|
||||||
|
@ -74,6 +75,8 @@ inkwell = { git = "https://github.com/roc-lang/inkwell", branch = "inkwell-llvm-
|
||||||
"llvm16-0",
|
"llvm16-0",
|
||||||
] }
|
] }
|
||||||
|
|
||||||
|
soa = { path = "crates/soa" }
|
||||||
|
|
||||||
arrayvec = "0.7.2" # update roc_std/Cargo.toml on change
|
arrayvec = "0.7.2" # update roc_std/Cargo.toml on change
|
||||||
backtrace = "0.3.67"
|
backtrace = "0.3.67"
|
||||||
base64-url = "1.4.13"
|
base64-url = "1.4.13"
|
||||||
|
@ -137,7 +140,10 @@ maplit = "1.0.2"
|
||||||
memmap2 = "0.5.10"
|
memmap2 = "0.5.10"
|
||||||
mimalloc = { version = "0.1.34", default-features = false }
|
mimalloc = { version = "0.1.34", default-features = false }
|
||||||
nonempty = "0.8.1"
|
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"
|
packed_struct = "0.10.1"
|
||||||
page_size = "0.5.0"
|
page_size = "0.5.0"
|
||||||
palette = "0.6.1"
|
palette = "0.6.1"
|
||||||
|
|
|
@ -12,7 +12,7 @@ use roc_module::{
|
||||||
use roc_types::{
|
use roc_types::{
|
||||||
subs::{
|
subs::{
|
||||||
self, AliasVariables, Descriptor, GetSubsSlice, OptVariable, RecordFields, Subs, SubsIndex,
|
self, AliasVariables, Descriptor, GetSubsSlice, OptVariable, RecordFields, Subs, SubsIndex,
|
||||||
SubsSlice, TupleElems, UnionLambdas, UnionTags, Variable, VariableSubsSlice,
|
SubsSlice, TupleElems, UnionLambdas, UnionTags, Variable, VariableSlice,
|
||||||
},
|
},
|
||||||
types::{RecordField, Uls},
|
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> {
|
fn clone_field_names(&mut self, field_names: SubsSlice<Lowercase>) -> SubsSlice<Lowercase> {
|
||||||
SubsSlice::extend_new(
|
SubsSlice::extend_new(
|
||||||
&mut self.target.field_names,
|
&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<usize> {
|
||||||
SubsSlice::extend_new(
|
SubsSlice::extend_new(
|
||||||
&mut self.target.tuple_elem_indices,
|
&mut self.target.tuple_elem_indices,
|
||||||
self.source
|
self.source.get_slice(tuple_elem_indices).iter().cloned(),
|
||||||
.get_subs_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> {
|
fn clone_tag_names(&mut self, tag_names: SubsSlice<TagName>) -> SubsSlice<TagName> {
|
||||||
SubsSlice::extend_new(
|
SubsSlice::extend_new(
|
||||||
&mut self.target.tag_names,
|
&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> {
|
fn clone_lambda_names(&mut self, lambda_names: SubsSlice<Symbol>) -> SubsSlice<Symbol> {
|
||||||
SubsSlice::extend_new(
|
SubsSlice::extend_new(
|
||||||
&mut self.target.symbol_names,
|
&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<RecordField<()>> {
|
||||||
SubsSlice::extend_new(
|
SubsSlice::extend_new(
|
||||||
&mut self.target.record_fields,
|
&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