commit a8468a99ebb7891ba4de04881f4409b653d9190b Author: yukirij Date: Sun Nov 3 18:21:41 2024 -0800 Initialize repository. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..d889142 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "szun" +version = "0.1.0" +edition = "2021" + +[dependencies] +num = "0.4.3" + +pack = { git = "https://git.tsukiyo.org/Utility/pack" } diff --git a/src/bin/test.rs b/src/bin/test.rs new file mode 100644 index 0000000..7ad9a74 --- /dev/null +++ b/src/bin/test.rs @@ -0,0 +1,44 @@ +use szun::*; + +fn main() +{ + { + let data = Boolean::new().with(true); + println!("bool {}", data.get()); + } + + { + let data = Natural::new().with(15); + println!("nat {}", data.get::()); + } + + { + let data = Integer::new().with(-55); + println!("int {}", data.get::()); + } + + { + let (data, mut value) = Optional::::new().with_default(); + value.set(-1); + println!("opt {}", data.is_some()); + + if let Some(data) = data.get() { + println!("opt {}", data.get::()); + } + + data.unset(); + println!("opt {}", data.is_some()); + } + + { + let seq = Sequence::new().with_str("Hello, world!"); + println!("{} {} {}", seq.len(), seq.capacity(), seq.get_str()); + } + + { + let a = Integer::new().with(100); + let b = a.clone(); + + println!("100 <> {}, {}", a.get::(), b.get::()); + } +} diff --git a/src/implement/any.rs b/src/implement/any.rs new file mode 100644 index 0000000..31caf0f --- /dev/null +++ b/src/implement/any.rs @@ -0,0 +1,26 @@ +use crate::prelude::{*, internal::*}; + +pub struct Any { + pub(crate) refer:Ref, +} +impl Any { + pub fn null() -> Self + { + Self { refer:Ref::null() } + } + + pub fn typeid(&self) -> usize { self.refer.typeid() } +} +impl Szun for Any { + fn typeid() -> usize { 0 } +} +impl internal::SzunInternal for Any { + fn to_ref(&self) -> Ref { self.refer } + fn from_ref(refer:Ref) -> Self { Self { refer } } +} +impl Clone for Any { + fn clone(&self) -> Self { Self::from_ref(clone(self.to_ref(), None)) } +} +impl Drop for Any { + fn drop(&mut self) { drop(self.to_ref()); } +} diff --git a/src/implement/array.rs b/src/implement/array.rs new file mode 100644 index 0000000..2d65b52 --- /dev/null +++ b/src/implement/array.rs @@ -0,0 +1,67 @@ +use std::marker::PhantomData; +use crate::{prelude::{*, internal::*}, Runtime, Any, types}; + +pub struct Array { + refer:Ref, + phantom:PhantomData, +} +impl Array { + pub fn new() -> Self { + Self { + refer:Runtime::acquire(Self::typeid()), + phantom:PhantomData, + } + } + + pub fn with(self, data:&[R]) -> Self + { + self.set(data); + self + } + + pub fn set(&self, data:&[R]) + { + for i in 0..data.len() { + let _refer = data[i].to_ref(); + /*if self.compatible(&data[i]) { + + let inner_type = Runtime::type_in(self.refer.typeid()); + let inner_size = types::size(inner_type); + + let mut bytes = vec![0u8; types::size(inner_type)]; + + Runtime::load(data[i].to_ref(), bytes.as_ptr() as _, 0, inner_size); + + Runtime::store(self.refer, bytes.as_ptr() as _, 0, inner_size); + Runtime::write(self.refer, 0xFF, inner_size); + + if !types::primitive(data[i].to_ref().typeid()) { + bytes.fill(0); + Runtime::store(data[i].to_ref(), bytes.as_ptr() as _, 0, inner_size); + } + }*/ + } + } + + pub fn get(&self) -> std::option::Option + { + let inner_type = Runtime::type_in(self.refer.typeid()); + + let mut flag :u8 = 0; + Runtime::load(self.refer, &mut flag as _, types::size(inner_type), 1); + if flag != 0 { + let refer = self.refer; + Some(T::from_ref(refer.inner())) + } else { + None + } + } +} +impl Szun for Array { + fn typeid() -> usize { Runtime::type_from(T::typeid(), &[N, types::ARRAY]) } +} +impl internal::SzunInternal for Array { + fn to_ref(&self) -> Ref { self.refer } + fn from_ref(refer:Ref) -> Self { Self { refer, phantom:PhantomData } } +} +crate::impl_szun_generic_sized!(Array); diff --git a/src/implement/block.rs b/src/implement/block.rs new file mode 100644 index 0000000..0de0332 --- /dev/null +++ b/src/implement/block.rs @@ -0,0 +1,65 @@ +use crate::{prelude::{*, internal::*}, Runtime, Any, types}; + +pub struct Block { + refer:Ref, +} +impl Block { + pub fn new() -> Self { + Self { + refer:Runtime::acquire(Self::typeid()), + } + } + + pub fn with(mut self, data:&[u8]) -> Self + { + self.set(data); + self + } + + pub fn set(&mut self, data:&[u8]) + { + let size = Runtime::type_of(Runtime::type_in(self.refer.typeid())); + let mut write = data.to_vec(); + write.resize(size, 0); + Runtime::store(self.refer, write.as_ptr() as _, 0, types::size(self.refer.typeid())); + } + + pub fn set_byte(&mut self, index:usize, byte:u8) + { + if index < self.len() { + Runtime::store(self.refer, &byte as _, index, 1); + } + } + + pub fn get(&self) -> Vec + { + let size = Runtime::type_of(Runtime::type_in(self.refer.typeid())); + let mut data = vec![0u8; size]; + Runtime::load(self.refer, data.as_mut_ptr() as _, 0, types::size(self.refer.typeid())); + data + } + + pub fn get_byte(&mut self, index:usize) -> u8 + { + if index < self.len() { + let mut byte = 0u8; + Runtime::load(self.refer, &mut byte as _, index, 1); + byte + } else { + 0 + } + } + + pub fn len(&self) -> usize + { + Runtime::type_of(Runtime::type_in(self.refer.typeid())) + } +} +impl Szun for Block { + fn typeid() -> usize { Runtime::type_from(types::ANY, &[N, types::BLOCK]) } +} +impl SzunInternal for Block { + fn to_ref(&self) -> Ref { self.refer } + fn from_ref(refer:Ref) -> Self { Self { refer } } +} +crate::impl_szun_sized!(Block); diff --git a/src/implement/boolean.rs b/src/implement/boolean.rs new file mode 100644 index 0000000..4f55fb0 --- /dev/null +++ b/src/implement/boolean.rs @@ -0,0 +1,42 @@ +use crate::{prelude::{*, internal::*}, Runtime, Any, types}; + +pub struct Boolean { + refer:Ref, +} +impl Boolean { + pub fn new() -> Self { + Self { + refer:Runtime::acquire(Self::typeid()), + } + } + + pub fn with(self, data:bool) -> Self + { + self.set(data); + self + } + + pub fn set(&self, data:bool) + { + if let Some(memory) = unsafe {(self.refer.address_mut() as *mut bool).as_mut()} { + *memory = data; + } + } + + pub fn get(&self) -> bool + { + if let Some(memory) = unsafe {(self.refer.address() as *const bool).as_ref()} { + *memory + } else { + false + } + } +} +impl Szun for Boolean { + fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::BOOLEAN]) } +} +impl SzunInternal for Boolean { + fn to_ref(&self) -> Ref { self.refer } + fn from_ref(refer:Ref) -> Self { Self { refer } } +} +crate::impl_szun!(Boolean); diff --git a/src/implement/integer.rs b/src/implement/integer.rs new file mode 100644 index 0000000..d43a1b4 --- /dev/null +++ b/src/implement/integer.rs @@ -0,0 +1,43 @@ +use crate::{prelude::{*, internal::*}, Runtime, Any, types}; + +pub struct Integer { + refer:Ref, +} +impl Integer { + pub fn new() -> Self { + Self { + refer:Runtime::acquire(Self::typeid()), + } + } + + pub fn with(mut self, data:T) -> Self + { + self.set(data); + self + } + + pub fn set(&mut self, data:T) + { + let data = data.to_i64().unwrap_or_default(); + if let Some(memory) = unsafe {(self.refer.address_mut() as *mut i64).as_mut()} { + *memory = data; + } + } + + pub fn get(&self) -> T + { + T::from_i64(if let Some(memory) = unsafe {(self.refer.address() as *const i64).as_ref()} { + *memory + } else { + 0 + }).unwrap_or_default() + } +} +impl Szun for Integer { + fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::INTEGER]) } +} +impl SzunInternal for Integer { + fn to_ref(&self) -> Ref { self.refer } + fn from_ref(refer:Ref) -> Self { Self { refer } } +} +crate::impl_szun!(Integer); diff --git a/src/implement/mod.rs b/src/implement/mod.rs new file mode 100644 index 0000000..561a46a --- /dev/null +++ b/src/implement/mod.rs @@ -0,0 +1,9 @@ +pub mod any; pub use any::Any; +pub mod null; pub use null::Null; +pub mod boolean; pub use boolean::Boolean; +pub mod natural; pub use natural::Natural; +pub mod integer; pub use integer::Integer; +pub mod block; pub use block::Block; +pub mod sequence; pub use sequence::Sequence; +pub mod optional; pub use optional::Optional; +pub mod array; pub use array::Array; diff --git a/src/implement/natural.rs b/src/implement/natural.rs new file mode 100644 index 0000000..c8cb662 --- /dev/null +++ b/src/implement/natural.rs @@ -0,0 +1,43 @@ +use crate::{prelude::{*, internal::*}, Runtime, Any, types}; + +pub struct Natural { + refer:Ref, +} +impl Natural { + pub fn new() -> Self { + Self { + refer:Runtime::acquire(Self::typeid()), + } + } + + pub fn with(mut self, data:T) -> Self + { + self.set(data); + self + } + + pub fn set(&mut self, data:T) + { + let data = data.to_u64().unwrap_or_default(); + if let Some(memory) = unsafe {(self.refer.address_mut() as *mut u64).as_mut()} { + *memory = data; + } + } + + pub fn get(&self) -> T + { + T::from_u64(if let Some(memory) = unsafe {(self.refer.address() as *const u64).as_ref()} { + *memory + } else { + 0 + }).unwrap_or_default() + } +} +impl Szun for Natural { + fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::NATURAL]) } +} +impl SzunInternal for Natural { + fn to_ref(&self) -> Ref { self.refer } + fn from_ref(refer:Ref) -> Self { Self { refer } } +} +crate::impl_szun!(Natural); diff --git a/src/implement/null.rs b/src/implement/null.rs new file mode 100644 index 0000000..4d4e57c --- /dev/null +++ b/src/implement/null.rs @@ -0,0 +1,16 @@ +use crate::{prelude::{*, internal::*}, Runtime, Any, types}; + +pub struct Null { } +impl Null { + pub fn new() -> Self { + Self { } + } +} +impl Szun for Null { + fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::BOOLEAN]) } +} +impl SzunInternal for Null { + fn to_ref(&self) -> Ref { Ref::null() } + fn from_ref(_:Ref) -> Self { Self { } } +} +crate::impl_szun!(Null); diff --git a/src/implement/optional.rs b/src/implement/optional.rs new file mode 100644 index 0000000..2ba868e --- /dev/null +++ b/src/implement/optional.rs @@ -0,0 +1,120 @@ +use std::marker::PhantomData; +use internal::SzunInternal; + +use crate::{prelude::*, Runtime, Any, types}; + +pub struct Optional where T:Szun { + refer:Ref, + phantom:PhantomData, +} +impl Optional { + pub fn new() -> Self { + Self { + refer:Runtime::acquire(Self::typeid()), + phantom:PhantomData, + } + } + + pub fn with(self, data:&T) -> Self + { + self.set(data); + self + } + + pub fn with_default(self) -> (Self, T) + { + self.set_default(); + let refer = self.refer; + (self, T::from_ref(refer.inner())) + } + + pub fn set(&self, data:&T) + { + let inner_type = Runtime::type_in(self.refer.typeid()); + let inner_size = types::size(inner_type); + + let mut bytes = vec![0u8; types::size(inner_type)]; + + Runtime::load(data.to_ref(), bytes.as_ptr() as _, 0, inner_size); + + Runtime::store(self.refer, bytes.as_ptr() as _, 0, inner_size); + Runtime::write(self.refer, 0xFF, inner_size); + + if !types::primitive(data.to_ref().typeid()) { + bytes.fill(0); + Runtime::store(data.to_ref(), bytes.as_ptr() as _, 0, inner_size); + } + } + + pub fn set_default(&self) -> T + { + let inner_type = Runtime::type_in(self.refer.typeid()); + Runtime::write(self.refer, 0xFF, types::size(inner_type)); + + T::from_ref(self.refer.temporary()) + } + + pub fn unset(&self) + { + let inner_type = Runtime::type_in(self.refer.typeid()); + let inner_size = types::size(inner_type); + let bytes = vec![0u8; types::size(inner_type)]; + + Runtime::store(self.refer, bytes.as_ptr() as _, 0, inner_size); + Runtime::write(self.refer, 0x00, inner_size); + } + + pub fn get(&self) -> std::option::Option + { + let inner_type = Runtime::type_in(self.refer.typeid()); + + let mut flag :u8 = 0; + Runtime::load(self.refer, &mut flag as _, types::size(inner_type), 1); + if flag != 0 { + let refer = self.refer; + Some(T::from_ref(refer.inner())) + } else { + None + } + } + + pub fn is_some(&self) -> bool + { + let inner_type = Runtime::type_in(self.refer.typeid()); + + let mut flag :u8 = 0; + Runtime::load(self.refer, &mut flag as _, types::size(inner_type), 1); + flag != 0 + } + + pub fn is_none(&self) -> bool + { + !self.is_some() + } +} +impl Szun for Optional { + fn typeid() -> usize { Runtime::type_from(T::typeid(), &[types::OPTIONAL]) } +} +impl SzunInternal for Optional { + fn to_ref(&self) -> Ref { self.refer } + fn from_ref(refer:Ref) -> Self { Self { refer, phantom:PhantomData } } + + fn mem_clone(refer:Ref, memory:std::prelude::v1::Option) -> Ref { + // Allocate new memory if not provided + let memory = if let Some(memory) = memory { + memory + } else { + Runtime::acquire(refer.typeid()) + }; + + // Copy memory + clone(refer.inner(), Some(memory.inner())); + + memory + } + + fn mem_drop(refer:Ref) { + drop(refer.inner()) + } +} +crate::impl_szun_generic!(Optional); diff --git a/src/implement/sequence.rs b/src/implement/sequence.rs new file mode 100644 index 0000000..98c2eb3 --- /dev/null +++ b/src/implement/sequence.rs @@ -0,0 +1,109 @@ +use internal::SzunInternal; + +use crate::{prelude::*, Runtime, Any, types}; + +pub(crate) struct Data { + pub capacity:usize, + pub length:usize, + pub data:*const u8, +} + +pub struct Sequence { + refer:Ref, +} +impl Sequence { + pub fn new() -> Self { + Self { + refer:Runtime::acquire(Self::typeid()), + } + } + + pub fn with(mut self, data:&[u8]) -> Self + { + self.set(data); + self + } + + pub fn with_str(mut self, data:&str) -> Self + { + self.set(data.as_bytes()); + self + } + + pub fn set(&mut self, data:&[u8]) + { + if let Some(header) = unsafe {(self.refer.address_mut() as *mut Data).as_mut()} { + // Reallocate memory if capacity is insufficient + if header.capacity < data.len() { + // Free existing memory + if !header.data.is_null() { + if let Ok(layout) = std::alloc::Layout::from_size_align(header.capacity, 1) { + unsafe { std::alloc::dealloc(header.data as _, layout); } + } + } + // Allocate sufficient memory + header.capacity = data.len(); + if let Ok(layout) = std::alloc::Layout::from_size_align(header.capacity, 1) { + header.data = unsafe {std::alloc::alloc(layout)}; + } else { + header.data = std::ptr::null(); + header.capacity = 0; + } + } + + // Copy data to memory + if !header.data.is_null() { + header.length = data.len(); + unsafe { std::ptr::copy_nonoverlapping(data.as_ptr() as _, header.data as _, data.len()); } + } + } + } + + pub fn set_str(&mut self, data:&str) + { + self.set(data.as_bytes()) + } + + pub fn get(&self) -> Vec + { + if let Some(header) = unsafe {(self.refer.address_mut() as *mut Data).as_mut()} { + // Load data + let mut data = vec![0u8; header.length]; + unsafe { std::ptr::copy_nonoverlapping(header.data as _, data.as_mut_ptr() as _, header.length); } + data + } else { + Vec::new() + } + } + + pub fn get_str(&self) -> String + { + String::from_utf8(self.get()).unwrap_or_default() + } + + pub fn len(&self) -> usize + { + if let Some(header) = unsafe {(self.refer.address_mut() as *mut Data).as_mut()} { + header.length + } else { + 0 + } + } + + pub fn capacity(&self) -> usize + { + if let Some(header) = unsafe {(self.refer.address_mut() as *mut Data).as_mut()} { + header.capacity + } else { + 0 + } + } +} +impl Szun for Sequence { + fn typeid() -> usize { Runtime::type_from(types::ANY, &[types::SEQUENCE]) } +} +impl internal::SzunInternal for Sequence { + fn to_ref(&self) -> Ref { self.refer } + fn from_ref(refer:Ref) -> Self { Self { refer } } +} +crate::impl_szun!(Sequence); diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..5c4e32f --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,7 @@ +#![allow(dead_code)] + +mod util; +pub mod prelude; pub use prelude::*; +mod types; +mod runtime; use runtime::Runtime; +mod implement; pub use implement::*; diff --git a/src/prelude/clone.rs b/src/prelude/clone.rs new file mode 100644 index 0000000..59a7c59 --- /dev/null +++ b/src/prelude/clone.rs @@ -0,0 +1,15 @@ +use crate::Ref; + +pub fn clone(refer:Ref, memory:Option) -> Ref +// Deep copy an object and return the copy's reference. +// +{ + use crate::{*, prelude::internal::*}; + match Runtime::type_of(refer.typeid()) { + types::SEQUENCE => Sequence::mem_clone(refer, memory), + types::OPTIONAL => Optional::::mem_clone(refer, memory), + types::ARRAY => Array::::mem_clone(refer, memory), + + _ => Any::mem_clone(refer, memory), + } +} diff --git a/src/prelude/drop.rs b/src/prelude/drop.rs new file mode 100644 index 0000000..dbb890c --- /dev/null +++ b/src/prelude/drop.rs @@ -0,0 +1,34 @@ +use crate::{prelude::{*, internal::*}, types::*, implement::*}; + +pub fn drop(refer:Ref) +{ + if !refer.is_temporary() { + drop_memory(refer); + Runtime::release(refer); + } +} + +fn drop_memory(refer:Ref) +{ + let typeid = refer.typeid(); + match typeid { + OPTIONAL => { + let obj = crate::Optional::::from_ref(refer.temporary()); + if obj.is_some() { + drop_memory(refer.inner()); + } + } + + SEQUENCE => { + if let Some(header) = unsafe {(refer.address_mut() as *mut sequence::Data).as_mut()} { + if !header.data.is_null() { + if let Ok(layout) = std::alloc::Layout::from_size_align(header.capacity, 1) { + unsafe { std::alloc::dealloc(header.data as _, layout); } + } + } + } + } + + _ => { } + } +} diff --git a/src/prelude/encode.rs b/src/prelude/encode.rs new file mode 100644 index 0000000..a5bbeb6 --- /dev/null +++ b/src/prelude/encode.rs @@ -0,0 +1,70 @@ +use crate::{*, prelude::{*, internal::*}, types::*}; + +pub fn encode(refer:Ref) -> Vec +{ + let refer = refer.temporary(); + let mut result = Vec::new(); + + let typeid = Runtime::type_of(refer.typeid()); + match typeid { + BOOLEAN => { + // + // + let data = Boolean::from_ref(refer); + result.push(data.get() as u8); + } + + NATURAL => { + // + // + let data = Natural::from_ref(refer); + result.append(&mut data.get::().pack()); + } + + INTEGER => { + // + // + let _data = Integer::from_ref(refer); + //result.append(&mut data.get::().pack()); + } + + BLOCK => { + // + // + let data = Block::<0>::from_ref(refer); + result.append(&mut data.get()); + } + + SEQUENCE => { + // + // + let data = Sequence::from_ref(refer); + result.append(&mut (data.len() as u64).pack()); + result.append(&mut data.get()); + } + + OPTIONAL => { + // ? + // + let data = Optional::::from_ref(refer); + let is_some = data.is_some(); + result.push(is_some as u8); + if let Some(value) = data.get() { + result.append(&mut encode(value.to_ref())); + } + } + + _ => { } + } + + result +} + +pub fn decode(refer:Ref, _data:&[u8], _index:&mut usize) -> Result<(),()> +{ + let typeid = Runtime::type_of(refer.typeid()); + match typeid { + _ => { } + } + Err(()) +} diff --git a/src/prelude/implement.rs b/src/prelude/implement.rs new file mode 100644 index 0000000..4f0efe4 --- /dev/null +++ b/src/prelude/implement.rs @@ -0,0 +1,13 @@ +use crate::prelude::{*, internal::*}; + +pub(crate) fn to_any(data:T) -> Any +{ + Any::from_ref(data.to_ref()) +} + +pub(crate) fn from_any(any:Any) -> Result +{ + if any.typeid() == T::typeid() + || (Runtime::type_of(any.typeid()) == Runtime::type_of(T::typeid()) && Runtime::type_in(T::typeid()) == 0) + { Ok(T::from_ref(any.refer)) } else { Err(()) } +} diff --git a/src/prelude/internal/mod.rs b/src/prelude/internal/mod.rs new file mode 100644 index 0000000..8e1b651 --- /dev/null +++ b/src/prelude/internal/mod.rs @@ -0,0 +1,25 @@ +use crate::{Ref, Runtime, types}; + +#[allow(drop_bounds)] +pub(crate) trait SzunInternal { + fn to_ref(&self) -> Ref; + fn from_ref(refer:Ref) -> Self; + + fn mem_clone(refer:Ref, memory:Option) -> Ref { + let typeid = refer.typeid(); + + // Acquire memory if not provided + let memory = if let Some(memory) = memory { + memory + } else { + Runtime::acquire(typeid) + }; + + // Copy data to destination + Runtime::copy(refer.address(), memory.address_mut(), types::size(typeid)); + + memory + } + + fn mem_drop(_refer:Ref) { /* Do nothing */ } +} diff --git a/src/prelude/mod.rs b/src/prelude/mod.rs new file mode 100644 index 0000000..b4da354 --- /dev/null +++ b/src/prelude/mod.rs @@ -0,0 +1,38 @@ +use crate::{Runtime, Any}; +use pack::prelude::*; + +pub mod internal; + +mod refer; pub(crate) use refer::Ref; +mod encode; pub(crate) use encode::*; + +#[allow(drop_bounds, private_bounds)] +pub trait Szun : internal::SzunInternal + Clone + TryFrom + Into + Drop { + fn typeid() -> usize; + + fn compatible(&self, data:&T) -> bool + { + let data_type = data.to_ref().typeid(); + let self_type = self.to_ref().typeid(); + data_type == Runtime::type_in(self_type) + || Runtime::type_in(self_type) == 0 + } + + fn encode(&self) -> Vec { encode(self.to_ref()) } + fn decode(&mut self, bytes:&Vec, index:&mut usize) -> Result<(),()> { decode(self.to_ref(), bytes, index) } + + fn tag(&self) -> Vec + { + let mut result = Vec::new(); + let mut next = Some(Self::typeid()); + while let Some(next_id) = next { + result.append(&mut 0u32.pack()); + next = Runtime::type_in_opt(next_id); + } + result + } +} + +mod implement; pub(crate) use implement::*; +mod clone; pub(crate) use clone::*; +mod drop; pub(crate) use drop::*; diff --git a/src/prelude/refer.rs b/src/prelude/refer.rs new file mode 100644 index 0000000..5fa0b85 --- /dev/null +++ b/src/prelude/refer.rs @@ -0,0 +1,58 @@ +use crate::Runtime; + +#[derive(Clone, Copy)] +pub struct Ref { + typeid:usize, + address:*const u8, +} +impl Ref { + pub(crate) fn new(typeid:usize, address:*const u8) -> Self + { + Self { + typeid, + address, + } + } + + pub fn null() -> Self + { + Self { + typeid:0, + address:std::ptr::null(), + } + } + + pub fn inner(&self) -> Self + { + let mut refer = *self; + refer.typeid = Runtime::type_in(self.typeid); + self.temporary() + } + + pub fn temporary(&self) -> Self + { + let mut refer = *self; + refer.typeid |= 1 << (usize::BITS - 1); + refer + } + + pub fn is_temporary(&self) -> bool + { + (self.typeid & (1 << (usize::BITS - 1))) != 0 + } + + pub fn typeid(&self) -> usize + { + self.typeid & !(1 << (usize::BITS - 1)) + } + + pub fn address(&self) -> *const u8 + { + self.address + } + + pub fn address_mut(&self) -> *mut u8 + { + self.address as _ + } +} diff --git a/src/runtime/mod.rs b/src/runtime/mod.rs new file mode 100644 index 0000000..a8b9239 --- /dev/null +++ b/src/runtime/mod.rs @@ -0,0 +1,118 @@ +use crate::{prelude::*, types}; + +mod typetree; use typetree::TypeTree; + +struct RuntimeData { + terms:Vec, + types:TypeTree, +} +impl RuntimeData { + const fn init() -> Self + { + Self { + terms:Vec::new(), + types:TypeTree::new(), + } + } + + fn acquire(&mut self, typeid:usize) -> Ref + { + use std::alloc::{alloc_zeroed, Layout}; + + let size = types::size(typeid); + if size > 0 { + if let Ok(layout) = Layout::from_size_align(size, types::align(typeid)) { + let address :*const u8; + unsafe { + address = alloc_zeroed(layout) as _; + } + Ref::new(typeid, address) + } else { + Ref::null() + } + } else { + Ref::null() + } + } + + fn release(&mut self, refer:Ref) + { + use std::alloc::{dealloc, Layout}; + + let typeid = refer.typeid(); + let size = types::size(typeid); + if size > 0 { + if let Ok(layout) = Layout::from_size_align(size, types::align(typeid)) { + unsafe { + dealloc(refer.address_mut(), layout); + } + } + } + } + + fn store(&mut self, refer:Ref, data:*const u8, index:usize, len:usize) + { + unsafe { + std::ptr::copy_nonoverlapping(data, refer.address_mut().add(index), len); + } + } + + fn load(&mut self, refer:Ref, data:*mut u8, index:usize, len:usize) + { + unsafe { + std::ptr::copy_nonoverlapping(refer.address().add(index), data, len); + } + } + + fn copy(&mut self, src:*const u8, dst:*mut u8, len:usize) + { + unsafe { + std::ptr::copy_nonoverlapping(src, dst, len); + } + } + + fn write(&mut self, refer:Ref, data:u8, index:usize) + { + unsafe { *refer.address_mut().byte_add(index) = data; } + } + + fn zero(&mut self, refer:Ref) + { + let size = types::size(refer.typeid()); + for i in 0..size { + unsafe { *refer.address_mut().byte_add(i) = 0; } + } + } + + fn type_from(&mut self, parent:usize, types:&[usize]) -> usize + { + self.types.outer(parent, types) + } + + fn type_in(&mut self, typeid:usize) -> Option + { + self.types.inner(typeid) + } + + fn type_of(&mut self, typeid:usize) -> usize + { + self.types.value(typeid) + } +} +static mut RUNTIME :RuntimeData = RuntimeData::init(); + +pub struct Runtime { } +impl Runtime { + pub fn acquire(typeid:usize) -> Ref {unsafe{ RUNTIME.acquire(typeid) }} + pub fn release(refer:Ref) {unsafe{ RUNTIME.release(refer) }} + pub fn store(refer:Ref, data:*const u8, index:usize, len:usize) {unsafe{ RUNTIME.store(refer, data, index, len) }} + pub fn load(refer:Ref, data:*mut u8, index:usize, len:usize) {unsafe{ RUNTIME.load(refer, data, index, len) }} + pub fn copy(src:*const u8, dst:*mut u8, len:usize) {unsafe{ RUNTIME.copy(src, dst, len) }} + pub fn write(refer:Ref, data:u8, index:usize) {unsafe { RUNTIME.write(refer, data, index) }} + pub fn zero(refer:Ref) {unsafe { RUNTIME.zero(refer) }} + + pub fn type_of(typeid:usize) -> usize {unsafe{ RUNTIME.type_of(typeid) }} + pub fn type_in(typeid:usize) -> usize {unsafe{ RUNTIME.type_in(typeid).unwrap_or_default() }} + pub fn type_in_opt(typeid:usize) -> Option {unsafe{ RUNTIME.type_in(typeid) }} + pub fn type_from(typeid:usize, types:&[usize]) -> usize {unsafe{ RUNTIME.type_from(typeid, types) }} +} diff --git a/src/runtime/typetree.rs b/src/runtime/typetree.rs new file mode 100644 index 0000000..29f55e5 --- /dev/null +++ b/src/runtime/typetree.rs @@ -0,0 +1,104 @@ +struct Node { + typeid:usize, + parent:Option, + child:Option, + next:Option, +} + +pub struct TypeTree { + data:Vec, +} +impl TypeTree { + pub const fn new() -> Self + { + Self { + data:Vec::new(), + } + } + + pub fn value(&self, id:usize) -> usize + { + if id < self.data.len() { + self.data[id].typeid + } else { + 0 + } + } + + pub fn inner(&self, id:usize) -> Option + { + if id < self.data.len() { + self.data[id].parent + } else { + None + } + } + + pub fn outer(&mut self, typeid:usize, types:&[usize]) -> usize + { + let mut itr = typeid; + let mut type_index = 0; + + if self.data.len() == 0 { + self.data.push(Node { + typeid:0, + parent:None, + child:None, + next:None, + }); + } + + if typeid != 0 { + if let Some(child) = self.data[itr].child { + itr = child; + } else { + let node = Node { + typeid:types[type_index], + parent:Some(itr), + child:None, + next:None, + }; + itr = self.data.len(); + self.data.push(node); + } + } + + while type_index < types.len() { + if self.data[itr].typeid == types[type_index] { + if type_index + 1 < types.len() { + if let Some(child) = self.data[itr].child { + itr = child; + } else { + let node = Node { + typeid:types[type_index], + parent:Some(itr), + child:None, + next:None, + }; + itr = self.data.len(); + self.data.push(node); + } + type_index += 1; + } else { + break; + } + } else { + if let Some(next) = self.data[itr].next { + itr = next; + } else { + let node = Node { + typeid:types[type_index], + parent:self.data[itr].parent, + child:None, + next:None, + }; + self.data[itr].next = Some(self.data.len()); + itr = self.data.len(); + self.data.push(node); + } + } + } + + itr + } +} diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 0000000..b284046 --- /dev/null +++ b/src/types.rs @@ -0,0 +1,140 @@ +use crate::Runtime; + +/* +** Type Codes +*/ +pub const ANY :usize = 0x00; +pub const BOOLEAN :usize = 0x01; +pub const BYTE :usize = 0x02; +pub const CHAR :usize = 0x03; +pub const NATURAL :usize = 0x10; +pub const INTEGER :usize = 0x11; +pub const DECIMAL :usize = 0x12; +pub const SIGNIFICANT :usize = 0x13; +pub const BLOCK :usize = 0x20; +pub const SEQUENCE :usize = 0x21; +pub const VAR :usize = 0x30; +pub const OPTIONAL :usize = 0x31; +pub const ARRAY :usize = 0x32; +pub const LIST :usize = 0x33; +pub const GRAPH :usize = 0x34; +pub const TRIE :usize = 0x35; +pub const MAP :usize = 0x40; +pub const SPARSE :usize = 0x41; +pub const POOL :usize = 0x42; +pub const TABLE :usize = 0x43; +pub const ENUM :usize = 0x7D; +pub const RECORD :usize = 0x7E; +pub const SCHEMA :usize = 0x7F; + +pub fn size(typeid:usize) -> usize +// Byte size of static data in memory. +// +{ + use std::mem::size_of; + + match Runtime::type_of(typeid) { + ANY => 0, + BOOLEAN => size_of::(), + BYTE => size_of::(), + CHAR => size_of::(), + NATURAL => size_of::(), + INTEGER => size_of::(), + DECIMAL => size_of::(), + SIGNIFICANT => size_of::(), + BLOCK => Runtime::type_of(Runtime::type_in(typeid)), + SEQUENCE => size_of::(), + VAR => 16, + OPTIONAL => size(Runtime::type_in(typeid)) + 1, + ARRAY => { + let inner_size = Runtime::type_in(typeid); + let inner_type = Runtime::type_in(inner_size); + Runtime::type_of(inner_size) * size(Runtime::type_of(inner_type)) + }, + LIST => 16, + GRAPH => 0, + TRIE => 0, + MAP => 0, + SPARSE => 0, + POOL => 0, + TABLE => 0, + ENUM => 0, + RECORD => 0, + SCHEMA => 0, + _ => 0, + } +} + +pub fn align(typeid:usize) -> usize +// Byte alignment of type. +// +{ + use std::mem::align_of; + + match Runtime::type_of(typeid) { + ANY => 0, + BOOLEAN => align_of::(), + BYTE => align_of::(), + CHAR => align_of::(), + NATURAL => align_of::(), + INTEGER => align_of::(), + DECIMAL => align_of::(), + SIGNIFICANT => align_of::(), + BLOCK => align_of::(), + SEQUENCE => align_of::(), + VAR => 8, + OPTIONAL => align(Runtime::type_in(typeid)), + ARRAY => { + let inner_size = Runtime::type_in(typeid); + let inner_type = Runtime::type_in(inner_size); + align(Runtime::type_of(inner_type)) + }, + LIST => 8, + GRAPH => 0, + TRIE => 0, + MAP => 0, + SPARSE => 0, + POOL => 0, + TABLE => 0, + ENUM => 0, + RECORD => 0, + SCHEMA => 0, + _ => 0, + } +} + +pub fn primitive(typeid:usize) -> bool +// Whether type may be shallow copied. +// +{ + match Runtime::type_of(typeid) { + ANY | BOOLEAN + | BYTE | CHAR + | NATURAL | INTEGER | DECIMAL | SIGNIFICANT + | BLOCK + => true, + _ => false, + } +} + +pub fn tag_stack(typeid:usize) -> usize +// Number of dependent tags following root. +// +{ + match Runtime::type_of(typeid) { + ANY => 1, + BLOCK => 1, + OPTIONAL => 1, + ARRAY => 2, + LIST => 1, + GRAPH => 1, + TRIE => 1, + MAP => 1, + SPARSE => 1, + POOL => 1, + TABLE => 2, + RECORD => 1, + + _ => 0, + } +} diff --git a/src/util/macros.rs b/src/util/macros.rs new file mode 100644 index 0000000..f55e91a --- /dev/null +++ b/src/util/macros.rs @@ -0,0 +1,39 @@ +#[macro_export] +macro_rules! impl_szun { + ($type_name:ty) => { + impl Into for $type_name { fn into(self) -> Any { to_any(self) } } + impl TryFrom for $type_name { type Error = (); fn try_from(any: Any) -> Result { from_any(any) } } + impl Clone for $type_name { fn clone(&self) -> Self { Self::from_ref(clone(self.to_ref(), None)) } } + impl Drop for $type_name { fn drop(&mut self) { drop(self.to_ref()); } } + } +} + +#[macro_export] +macro_rules! impl_szun_generic { + ($type_name:ty) => { + impl Into for $type_name { fn into(self) -> Any { to_any(self) } } + impl TryFrom for $type_name { type Error = (); fn try_from(any: Any) -> Result { from_any(any) } } + impl Clone for $type_name { fn clone(&self) -> Self { Self::from_ref(clone(self.to_ref(), None)) } } + impl Drop for $type_name { fn drop(&mut self) { drop(self.to_ref()); } } + } +} + +#[macro_export] +macro_rules! impl_szun_sized { + ($type_name:ty) => { + impl Into for $type_name { fn into(self) -> Any { to_any(self) } } + impl TryFrom for $type_name { type Error = (); fn try_from(any: Any) -> Result { from_any(any) } } + impl Clone for $type_name { fn clone(&self) -> Self { Self::from_ref(clone(self.to_ref(), None)) } } + impl Drop for $type_name { fn drop(&mut self) { drop(self.to_ref()); } } + } +} + +#[macro_export] +macro_rules! impl_szun_generic_sized { + ($type_name:ty) => { + impl Into for $type_name { fn into(self) -> Any { to_any(self) } } + impl TryFrom for $type_name { type Error = (); fn try_from(any: Any) -> Result { from_any(any) } } + impl Clone for $type_name { fn clone(&self) -> Self { Self::from_ref(clone(self.to_ref(), None)) } } + impl Drop for $type_name { fn drop(&mut self) { drop(self.to_ref()); } } + } +} diff --git a/src/util/mod.rs b/src/util/mod.rs new file mode 100644 index 0000000..eda363d --- /dev/null +++ b/src/util/mod.rs @@ -0,0 +1 @@ +pub mod macros;