Initial commit

This commit is contained in:
Aleksandr 2024-10-15 19:03:39 +03:00
commit 9282b8565d
24 changed files with 599 additions and 0 deletions

8
crates/std/Cargo.toml Normal file
View file

@ -0,0 +1,8 @@
[package]
name = "shiny-std"
version = "0.1.0"
edition = "2021"
[dependencies]
fxhash.workspace = true
hashbrown.workspace = true

View file

@ -0,0 +1,73 @@
//! # Interning arena.
use std::{hash::Hash, num::NonZeroU32};
use hashbrown::hash_map::RawEntryMut;
use crate::collections::HashMap;
use super::wonly;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
struct Mapping<P> {
hash: u64,
key: P,
}
#[derive(Clone)]
pub struct Arena<T, P> {
objects: wonly::Arena<T, P>,
// No raw_entry API on hashset.
bi: HashMap<Mapping<P>, ()>,
}
impl<T, P> Default for Arena<T, P> {
fn default() -> Self {
Self {
objects: wonly::Arena::new(),
bi: HashMap::default(),
}
}
}
impl<T, P> Arena<T, P> {
pub fn get(&self, ptr: P) -> Option<&T>
where
NonZeroU32: From<P>,
{
self.objects.get(ptr)
}
pub fn insert(&mut self, object: T) -> P
where
P: From<NonZeroU32> + Hash + Clone,
NonZeroU32: From<P>,
T: Hash + Eq,
{
let hash = fxhash::hash64(&object);
match self.bi.raw_entry_mut().from_hash(hash, |m| {
self.objects
.get(m.key.clone())
.map_or(false, |lhs| lhs == &object)
}) {
RawEntryMut::Occupied(occup) => occup.into_key().key.clone(),
RawEntryMut::Vacant(vacant) => {
let key = self.objects.insert(object);
vacant.insert(
Mapping {
hash,
key: key.clone(),
},
(),
);
key
}
}
}
pub fn new() -> Self {
Self::default()
}
}

View file

@ -0,0 +1,20 @@
/// Combination of pointers.
#[macro_export]
#[doc(hidden)]
macro_rules! _make_comb {
($(
$item:item
)*) => {$(
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
)]
$item
)*};
}

View file

@ -0,0 +1,8 @@
pub mod intern;
pub mod wonly;
pub mod ptr;
pub use crate::_make_comb as make_comb;
mod macros;

View file

@ -0,0 +1,59 @@
use std::num::NonZeroU32;
#[macro_export]
#[doc(hidden)]
macro_rules! _ptrs {
($(
$(#[$outer:meta])*
$vis:vis struct $name:ident;
)*) => {$(
$(#[$outer])*
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
)]
$vis struct $name(::core::num::NonZeroU32);
impl $name {
/// Create instance of the pointer.
pub const fn new(v: ::core::num::NonZeroU32) -> Self {
Self(v)
}
pub const fn get(&self) -> ::core::num::NonZeroU32 {
self.0
}
}
impl From<$name> for ::core::num::NonZeroU32 {
fn from(value: $name) -> Self {
value.get()
}
}
impl From<::core::num::NonZeroU32> for $name {
fn from(value: ::core::num::NonZeroU32) -> Self {
Self::new(value)
}
}
impl $crate::ptr::Ptr for $name {
fn get(&self) -> ::core::num::NonZeroU32 {
self.0
}
}
)*};
}
/// Pointer in arena.
pub trait Ptr {
fn get(&self) -> NonZeroU32;
}
pub use crate::_ptrs as define;

View file

@ -0,0 +1,52 @@
//! # Write-only arena, without deletion
use std::{marker::PhantomData, num::NonZeroU32};
#[derive(Clone)]
pub struct Arena<T, P> {
mem: Vec<T>,
_ptr_ty: PhantomData<P>,
}
impl<T, P> Arena<T, P> {
pub fn get(&self, ptr: P) -> Option<&T>
where
P: Into<NonZeroU32>,
{
let index = ptr.into().get() as usize - 1;
self.mem.get(index)
}
pub fn insert(&mut self, obj: T) -> P
where
NonZeroU32: Into<P>,
{
let idx = self.mem.len();
self.mem.push(obj);
let ptr = idx
.checked_add(1)
.and_then(|v| v.try_into().ok())
.and_then(NonZeroU32::new)
.expect("shit happens")
.into();
ptr
}
}
impl<T, P> Default for Arena<T, P> {
fn default() -> Self {
Self::new()
}
}
impl<T, P> Arena<T, P> {
pub const fn new() -> Self {
Self {
mem: Vec::new(),
_ptr_ty: PhantomData,
}
}
}

View file

@ -0,0 +1,6 @@
use std::hash::BuildHasherDefault;
use fxhash::FxHasher;
pub type HashMap<K, V> = hashbrown::HashMap<K, V, BuildHasherDefault<FxHasher>>;
pub type HashSet<V> = hashbrown::HashSet<V, BuildHasherDefault<FxHasher>>;

3
crates/std/src/lib.rs Normal file
View file

@ -0,0 +1,3 @@
pub mod collections;
pub mod arena;

7
crates/typing/Cargo.toml Normal file
View file

@ -0,0 +1,7 @@
[package]
name = "shiny-typing"
version = "0.1.0"
edition = "2021"
[dependencies]
shiny-std.workspace = true

33
crates/typing/src/bin.rs Normal file
View file

@ -0,0 +1,33 @@
//! # Binary types
use shiny_arena::make_comb;
use crate::ptr;
make_comb! {
/// Type with additionally equipped ID.
pub struct Field {
pub ty: ptr::Ty,
pub id: ptr::Id,
}
/// Product type. Pretty much just `lhs_ty * rhs_ty`.
/// The following properties must be upheld:
///
/// 1. lhs * rhs = rhs * lhs <- commutativity
/// 2. (a * b) * c = a * (b * c) <- associativity
pub struct Prod {
pub lhs: ptr::Ty,
pub rhs: ptr::Ty,
}
/// Sum type. Pretty much just `lhs_ty + rhs_ty`.
/// The following properties must be upheld:
///
/// 1. lhs + rhs = rhs + rhs <- commutativity
/// 2. (a + b) + c = a + (b + c) <- associativity
pub struct Sum {
pub lhs: ptr::Ty,
pub rhs: ptr::Ty,
}
}

View file

@ -0,0 +1 @@
//! # Type checking.

View file

@ -0,0 +1,3 @@
//! # Type inference.
pub struct Ctx {}

14
crates/typing/src/int.rs Normal file
View file

@ -0,0 +1,14 @@
//! # Integer types.
/// Sign of the integer.
#[derive(Debug, Clone, Copy)]
pub enum Signedness {
/// The number has sign.
Signed,
/// The number has no sign.
Unsigned,
}
/// Integer.
#[derive(Debug, Clone, Copy)]
pub struct Int(pub Signedness);

10
crates/typing/src/lib.rs Normal file
View file

@ -0,0 +1,10 @@
pub mod bin;
pub mod un;
pub mod int;
pub mod pat;
pub mod ptr;
pub mod check;
pub mod infer;

32
crates/typing/src/pat.rs Normal file
View file

@ -0,0 +1,32 @@
use shiny_arena::make_comb;
use crate::ptr;
make_comb! {
/// Product type pattern.
pub struct Prod {
pub lhs: ptr::Pat,
pub rhs: ptr::Pat,
}
/// Sum type pattern.
pub struct Sum {
pub lhs: ptr::Pat,
pub rhs: ptr::Pat,
}
/// Exact type. Matches only if matched type
/// equals to specified.
pub struct ExactTy(pub ptr::Ty);
/// Field type. matches `{ name : ty_pat }`
pub struct Field {
pub name: ptr::Id,
pub ty: ptr::Pat,
}
/// "Value" pattern. Works like [`ExactTy`], but
/// additionally checks whether value of that type is equal
/// to specified value.
pub struct Value(pub ptr::Value);
}

21
crates/typing/src/ptr.rs Normal file
View file

@ -0,0 +1,21 @@
//! # Pointers to needed information.
//!
//! If values are equal, then their pointers are equal.
//! This means that there's unambiguous mapping from id to value and
//! back.
use shiny_arena::ptrs;
ptrs! {
/// Pointer to a type.
pub struct Ty;
/// Pointer to ID.
pub struct Id;
/// Pointer to a pattern.
pub struct Pat;
/// Pointer to a *complete* value.
pub struct Value;
}

1
crates/typing/src/un.rs Normal file
View file

@ -0,0 +1 @@
//! # Unary types