Initial commit
This commit is contained in:
commit
9282b8565d
24 changed files with 599 additions and 0 deletions
8
crates/std/Cargo.toml
Normal file
8
crates/std/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "shiny-std"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
fxhash.workspace = true
|
||||
hashbrown.workspace = true
|
73
crates/std/src/arena/intern.rs
Normal file
73
crates/std/src/arena/intern.rs
Normal 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()
|
||||
}
|
||||
}
|
20
crates/std/src/arena/macros.rs
Normal file
20
crates/std/src/arena/macros.rs
Normal 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
|
||||
)*};
|
||||
}
|
8
crates/std/src/arena/mod.rs
Normal file
8
crates/std/src/arena/mod.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
pub mod intern;
|
||||
pub mod wonly;
|
||||
|
||||
pub mod ptr;
|
||||
|
||||
pub use crate::_make_comb as make_comb;
|
||||
|
||||
mod macros;
|
59
crates/std/src/arena/ptr.rs
Normal file
59
crates/std/src/arena/ptr.rs
Normal 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;
|
52
crates/std/src/arena/wonly.rs
Normal file
52
crates/std/src/arena/wonly.rs
Normal 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,
|
||||
}
|
||||
}
|
||||
}
|
6
crates/std/src/collections.rs
Normal file
6
crates/std/src/collections.rs
Normal 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
3
crates/std/src/lib.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub mod collections;
|
||||
|
||||
pub mod arena;
|
7
crates/typing/Cargo.toml
Normal file
7
crates/typing/Cargo.toml
Normal 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
33
crates/typing/src/bin.rs
Normal 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,
|
||||
}
|
||||
}
|
1
crates/typing/src/check/mod.rs
Normal file
1
crates/typing/src/check/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
//! # Type checking.
|
3
crates/typing/src/infer/mod.rs
Normal file
3
crates/typing/src/infer/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
//! # Type inference.
|
||||
|
||||
pub struct Ctx {}
|
14
crates/typing/src/int.rs
Normal file
14
crates/typing/src/int.rs
Normal 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
10
crates/typing/src/lib.rs
Normal 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
32
crates/typing/src/pat.rs
Normal 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
21
crates/typing/src/ptr.rs
Normal 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
1
crates/typing/src/un.rs
Normal file
|
@ -0,0 +1 @@
|
|||
//! # Unary types
|
Loading…
Add table
Add a link
Reference in a new issue