mirror of
https://github.com/Dummi26/mers.git
synced 2026-03-04 08:36:33 +01:00
full rewrite, kinda works
This commit is contained in:
47
mers_lib/src/data/bool.rs
Executable file
47
mers_lib/src/data/bool.rs
Executable file
@@ -0,0 +1,47 @@
|
||||
use std::{any::Any, fmt::Display};
|
||||
|
||||
use super::{MersData, MersType};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Bool(pub bool);
|
||||
|
||||
impl MersData for Bool {
|
||||
fn clone(&self) -> Box<dyn MersData> {
|
||||
Box::new(Clone::clone(self))
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BoolT;
|
||||
impl MersType for BoolT {
|
||||
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
|
||||
other.as_any().downcast_ref::<Self>().is_some()
|
||||
}
|
||||
fn is_included_in_single(&self, target: &dyn MersType) -> bool {
|
||||
self.is_same_type_as(target)
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Bool {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
13
mers_lib/src/data/defs.rs
Executable file
13
mers_lib/src/data/defs.rs
Executable file
@@ -0,0 +1,13 @@
|
||||
use super::Data;
|
||||
|
||||
pub fn assign(from: Data, target: &Data) {
|
||||
let mut target = target.get_mut();
|
||||
if let Some(r) = target
|
||||
.mut_any()
|
||||
.downcast_mut::<crate::data::reference::Reference>()
|
||||
{
|
||||
*r.0.get_mut() = from.get().clone();
|
||||
} else {
|
||||
todo!("assignment to non-reference")
|
||||
}
|
||||
}
|
||||
47
mers_lib/src/data/float.rs
Executable file
47
mers_lib/src/data/float.rs
Executable file
@@ -0,0 +1,47 @@
|
||||
use std::{any::Any, fmt::Display};
|
||||
|
||||
use super::{MersData, MersType, Type};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Float(pub f64);
|
||||
|
||||
impl MersData for Float {
|
||||
fn clone(&self) -> Box<dyn MersData> {
|
||||
Box::new(Clone::clone(self))
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FloatT;
|
||||
impl MersType for FloatT {
|
||||
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
|
||||
other.as_any().downcast_ref::<Self>().is_some()
|
||||
}
|
||||
fn is_included_in_single(&self, target: &dyn MersType) -> bool {
|
||||
self.is_same_type_as(target)
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Float {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
79
mers_lib/src/data/function.rs
Executable file
79
mers_lib/src/data/function.rs
Executable file
@@ -0,0 +1,79 @@
|
||||
use std::{
|
||||
any::Any,
|
||||
fmt::{Debug, Display},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use crate::program::{self, run::Info};
|
||||
|
||||
use super::{Data, MersData, MersType, Type};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Function {
|
||||
pub info: Info,
|
||||
pub out: Arc<dyn Fn(&Type) -> Option<Type>>,
|
||||
pub run: Arc<dyn Fn(Data, &mut crate::program::run::Info) -> Data>,
|
||||
}
|
||||
impl Function {
|
||||
pub fn with_info(&self, info: program::run::Info) -> Self {
|
||||
Self {
|
||||
info,
|
||||
out: Arc::clone(&self.out),
|
||||
run: Arc::clone(&self.run),
|
||||
}
|
||||
}
|
||||
pub fn run(&self, arg: Data) -> Data {
|
||||
(self.run)(arg, &mut self.info.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl MersData for Function {
|
||||
fn clone(&self) -> Box<dyn MersData> {
|
||||
Box::new(Clone::clone(self))
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FunctionT(Arc<dyn Fn(&Type) -> Option<Type>>);
|
||||
impl MersType for FunctionT {
|
||||
fn is_same_type_as(&self, _other: &dyn MersType) -> bool {
|
||||
false
|
||||
}
|
||||
fn is_included_in_single(&self, _target: &dyn MersType) -> bool {
|
||||
false
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Function {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Function")
|
||||
}
|
||||
}
|
||||
impl Debug for FunctionT {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "FunctionT")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Function {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "<function>")
|
||||
}
|
||||
}
|
||||
47
mers_lib/src/data/int.rs
Executable file
47
mers_lib/src/data/int.rs
Executable file
@@ -0,0 +1,47 @@
|
||||
use std::{any::Any, fmt::Display};
|
||||
|
||||
use super::{MersData, MersType, Type};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Int(pub isize);
|
||||
|
||||
impl MersData for Int {
|
||||
fn clone(&self) -> Box<dyn MersData> {
|
||||
Box::new(Clone::clone(self))
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IntT;
|
||||
impl MersType for IntT {
|
||||
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
|
||||
other.as_any().downcast_ref::<Self>().is_some()
|
||||
}
|
||||
fn is_included_in_single(&self, target: &dyn MersType) -> bool {
|
||||
self.is_same_type_as(target)
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Int {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
155
mers_lib/src/data/mod.rs
Executable file
155
mers_lib/src/data/mod.rs
Executable file
@@ -0,0 +1,155 @@
|
||||
use std::{
|
||||
any::Any,
|
||||
fmt::{Debug, Display},
|
||||
sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||
};
|
||||
|
||||
pub mod bool;
|
||||
pub mod float;
|
||||
pub mod function;
|
||||
pub mod int;
|
||||
pub mod reference;
|
||||
pub mod string;
|
||||
pub mod tuple;
|
||||
|
||||
pub mod defs;
|
||||
|
||||
pub trait MersData: Any + Debug + Display {
|
||||
fn matches(&self) -> Option<Data> {
|
||||
None
|
||||
}
|
||||
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Data>>> {
|
||||
None
|
||||
}
|
||||
/// By default, uses `iterable` to get an iterator and `nth` to retrieve the nth element.
|
||||
/// Should have a custom implementation for better performance on most types
|
||||
fn get(&self, i: usize) -> Option<Data> {
|
||||
self.iterable()?.nth(i)
|
||||
}
|
||||
fn clone(&self) -> Box<dyn MersData>;
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
fn mut_any(&mut self) -> &mut dyn Any;
|
||||
fn to_any(self) -> Box<dyn Any>;
|
||||
}
|
||||
|
||||
pub trait MersType: Any + Debug {
|
||||
/// If Some((_, false)) is returned, data of this type could match. If it matches, it matches with the type.
|
||||
/// If Some((_, true)) is returned, data of this type will always match with the type.
|
||||
fn matches(&self) -> Option<(Type, bool)> {
|
||||
None
|
||||
}
|
||||
/// If Some(T), calling `iterable` on the MersData this MersType belongs to
|
||||
/// Should return Some(I), where I is an Iterator which only returns items of type T.
|
||||
fn iterable(&self) -> Option<Type> {
|
||||
None
|
||||
}
|
||||
/// If Some(T), calling `get` on data of this type may return T, but it might also return None.
|
||||
/// By default, this returns the same thing as `iterable`, since this is also the default implementation for `MersData::get`.
|
||||
fn get(&self) -> Option<Type> {
|
||||
self.iterable()
|
||||
}
|
||||
/// If self and other are different types (`other.as_any().downcast_ref::<Self>().is_none()`),
|
||||
/// this *must* return false.
|
||||
fn is_same_type_as(&self, other: &dyn MersType) -> bool;
|
||||
/// This doesn't handle the case where target is Type (is_included_in handles it)
|
||||
fn is_included_in_single(&self, target: &dyn MersType) -> bool;
|
||||
fn is_included_in(&self, target: &dyn MersType) -> bool {
|
||||
if let Some(target) = target.as_any().downcast_ref::<Type>() {
|
||||
target
|
||||
.types
|
||||
.iter()
|
||||
.any(|t| self.is_included_in_single(t.as_ref()))
|
||||
} else {
|
||||
self.is_included_in_single(target)
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
fn mut_any(&mut self) -> &mut dyn Any;
|
||||
fn to_any(self) -> Box<dyn Any>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Data {
|
||||
pub data: Arc<RwLock<Box<dyn MersData>>>,
|
||||
}
|
||||
impl Data {
|
||||
pub fn new<T: MersData>(data: T) -> Self {
|
||||
Self::new_boxed(Box::new(data))
|
||||
}
|
||||
pub fn new_boxed(data: Box<dyn MersData>) -> Self {
|
||||
Self {
|
||||
data: Arc::new(RwLock::new(data)),
|
||||
}
|
||||
}
|
||||
pub fn empty_tuple() -> Self {
|
||||
Self::new(tuple::Tuple(vec![]))
|
||||
}
|
||||
pub fn one_tuple(v: Self) -> Self {
|
||||
Self::new(tuple::Tuple(vec![v]))
|
||||
}
|
||||
pub fn get(&self) -> RwLockReadGuard<Box<dyn MersData>> {
|
||||
self.data.read().unwrap()
|
||||
}
|
||||
pub fn get_mut(&self) -> RwLockWriteGuard<Box<dyn MersData>> {
|
||||
self.data.write().unwrap()
|
||||
}
|
||||
}
|
||||
impl Clone for Data {
|
||||
fn clone(&self) -> Self {
|
||||
// todo!("clone for data - requires CoW");
|
||||
Self {
|
||||
data: Arc::clone(&self.data),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Type {
|
||||
// TODO: Maybe make sure this is always sorted by (recursive?!?) TypeId,
|
||||
// that way is_same_type_as can work more efficiently (cuz good code but also branch prediction)
|
||||
types: Vec<Arc<dyn MersType>>,
|
||||
}
|
||||
impl Type {
|
||||
pub fn new<T: MersType>(t: T) -> Self {
|
||||
Self {
|
||||
types: vec![Arc::new(t)],
|
||||
}
|
||||
}
|
||||
pub fn newm(types: Vec<Arc<dyn MersType>>) -> Self {
|
||||
Self { types }
|
||||
}
|
||||
pub fn empty_tuple() -> Self {
|
||||
Self::new(tuple::TupleT(vec![]))
|
||||
}
|
||||
pub fn add<T: MersType>(&mut self, new: Box<T>) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
// PROBLEM:
|
||||
// [int, int]/[int, string]/[string, int]/[string, string]
|
||||
// is the same type as [int/string, int/string],
|
||||
// but [int, int]/[int, string]/[string int] isn't.
|
||||
// somehow, we need to merge these into the simplest form (same outer type, inner types differ)
|
||||
// before we can implement `Type`
|
||||
// idea: pick all the ones with the same first type: [int, int]/[int, string] and [string, int]/[string, string]
|
||||
// then repeat with the second type if possible (here not, but for longer tuples, probably?)
|
||||
// merge the last existing type in all the collections until we reach the first type again or the last types aren't equal anymore (how to check????)
|
||||
|
||||
impl MersType for Type {
|
||||
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
|
||||
todo!()
|
||||
}
|
||||
fn is_included_in_single(&self, target: &dyn MersType) -> bool {
|
||||
todo!()
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
51
mers_lib/src/data/reference.rs
Executable file
51
mers_lib/src/data/reference.rs
Executable file
@@ -0,0 +1,51 @@
|
||||
use std::{any::Any, fmt::Display, sync::Mutex};
|
||||
|
||||
use super::{Data, MersData, MersType, Type};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Reference(pub Data);
|
||||
|
||||
impl MersData for Reference {
|
||||
fn clone(&self) -> Box<dyn MersData> {
|
||||
Box::new(Clone::clone(self))
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ReferenceT(pub Type);
|
||||
impl MersType for ReferenceT {
|
||||
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
|
||||
if let Some(o) = other.as_any().downcast_ref::<Self>() {
|
||||
self.0.is_same_type_as(&o.0)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
fn is_included_in_single(&self, target: &dyn MersType) -> bool {
|
||||
self.is_same_type_as(target)
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Reference {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "&{}", self.0.get())
|
||||
}
|
||||
}
|
||||
47
mers_lib/src/data/string.rs
Executable file
47
mers_lib/src/data/string.rs
Executable file
@@ -0,0 +1,47 @@
|
||||
use std::{any::Any, fmt::Display};
|
||||
|
||||
use super::{MersData, MersType, Type};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct String(pub std::string::String);
|
||||
|
||||
impl MersData for String {
|
||||
fn clone(&self) -> Box<dyn MersData> {
|
||||
Box::new(Clone::clone(self))
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StringT;
|
||||
impl MersType for StringT {
|
||||
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
|
||||
other.as_any().downcast_ref::<Self>().is_some()
|
||||
}
|
||||
fn is_included_in_single(&self, target: &dyn MersType) -> bool {
|
||||
self.is_same_type_as(target)
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for String {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
92
mers_lib/src/data/tuple.rs
Executable file
92
mers_lib/src/data/tuple.rs
Executable file
@@ -0,0 +1,92 @@
|
||||
use std::{any::Any, fmt::Display};
|
||||
|
||||
use super::{Data, MersData, MersType, Type};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Tuple(pub Vec<Data>);
|
||||
|
||||
impl Tuple {
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
pub fn get(&self, i: usize) -> Option<&Data> {
|
||||
self.0.get(i)
|
||||
}
|
||||
}
|
||||
|
||||
impl MersData for Tuple {
|
||||
fn matches(&self) -> Option<Data> {
|
||||
if let Some(d) = self.0.first() {
|
||||
if self.0.len() == 1 {
|
||||
Some(d.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Data>>> {
|
||||
Some(Box::new(self.0.clone().into_iter()))
|
||||
}
|
||||
fn clone(&self) -> Box<dyn MersData> {
|
||||
Box::new(Clone::clone(self))
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TupleT(pub Vec<Type>);
|
||||
impl MersType for TupleT {
|
||||
fn matches(&self) -> Option<(Type, bool)> {
|
||||
if let Some(d) = self.0.first() {
|
||||
if self.0.len() == 1 {
|
||||
Some((d.clone(), true))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn iterable(&self) -> Option<Type> {
|
||||
Some(todo!("joine types"))
|
||||
}
|
||||
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
|
||||
other.as_any().downcast_ref::<Self>().is_some()
|
||||
}
|
||||
fn is_included_in_single(&self, target: &dyn MersType) -> bool {
|
||||
self.is_same_type_as(target)
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn mut_any(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
fn to_any(self) -> Box<dyn Any> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Tuple {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "(")?;
|
||||
for (i, c) in self.0.iter().enumerate() {
|
||||
if i > 0 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
write!(f, "{}", c.get())?;
|
||||
}
|
||||
write!(f, ")")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user