mirror of
https://github.com/Dummi26/mers.git
synced 2025-04-28 18:16:05 +02:00
cleaned up script/value.rs by splitting it up into val_data and val_type.
This commit is contained in:
parent
a43a23da8c
commit
664de5c347
17
src/main.rs
17
src/main.rs
@ -1,26 +1,9 @@
|
||||
use std::time::Instant;
|
||||
|
||||
use crate::script::value::{VSingleType, VType};
|
||||
|
||||
pub(crate) mod parse;
|
||||
pub(crate) mod script;
|
||||
|
||||
fn main() {
|
||||
let val: VType = VSingleType::Tuple(vec![
|
||||
VSingleType::Int.into(),
|
||||
VSingleType::String.into(),
|
||||
VSingleType::String.into(),
|
||||
])
|
||||
.into();
|
||||
let case: VType = VSingleType::Tuple(vec![
|
||||
VType {
|
||||
types: vec![VSingleType::Tuple(vec![]).into(), VSingleType::Int.into()],
|
||||
},
|
||||
VSingleType::String.into(),
|
||||
VSingleType::String.into(),
|
||||
])
|
||||
.into();
|
||||
assert!(val.fits_in(&case).is_empty());
|
||||
let script = parse::parse::parse(&mut parse::file::File::new(
|
||||
std::fs::read_to_string(std::env::args().nth(1).unwrap()).unwrap(),
|
||||
))
|
||||
|
@ -3,7 +3,8 @@ use crate::script::{
|
||||
to_runnable, to_runnable::ToRunnableError, RScript, SBlock, SFunction, SStatement,
|
||||
SStatementEnum,
|
||||
},
|
||||
value::{VDataEnum, VSingleType, VType},
|
||||
val_data::VDataEnum,
|
||||
val_type::{VSingleType, VType},
|
||||
};
|
||||
|
||||
use super::file::File;
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Types starting with S are directly parsed from Strings and unchecked. Types starting with T are type-checked templates for R-types. Types starting with R are runnable. S are converted to T after parsing is done, and T are converted to R whenever they need to run.
|
||||
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
fmt::Display,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
@ -11,7 +10,8 @@ use self::to_runnable::ToRunnableError;
|
||||
|
||||
use super::{
|
||||
builtins::BuiltinFunction,
|
||||
value::{VData, VDataEnum, VSingleType, VType},
|
||||
val_data::{VData, VDataEnum},
|
||||
val_type::{VSingleType, VType},
|
||||
};
|
||||
|
||||
// Represents a block of code
|
||||
@ -95,7 +95,10 @@ pub mod to_runnable {
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use crate::script::value::{VDataEnum, VSingleType, VType};
|
||||
use crate::script::{
|
||||
val_data::VDataEnum,
|
||||
val_type::{VSingleType, VType},
|
||||
};
|
||||
|
||||
use super::{
|
||||
BuiltinFunction, RBlock, RFunction, RScript, RStatement, RStatementEnum, SBlock, SFunction,
|
||||
|
@ -6,7 +6,8 @@ use std::{
|
||||
|
||||
use super::{
|
||||
block::RStatement,
|
||||
value::{VData, VDataEnum, VDataThreadEnum, VSingleType, VType},
|
||||
val_data::{VData, VDataEnum, VDataThreadEnum},
|
||||
val_type::{VSingleType, VType},
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -1,3 +1,5 @@
|
||||
pub mod block;
|
||||
pub mod builtins;
|
||||
pub mod val_data;
|
||||
pub mod val_type;
|
||||
pub mod value;
|
||||
|
@ -1,314 +1 @@
|
||||
use std::{
|
||||
fmt::Debug,
|
||||
ops::BitOr,
|
||||
sync::{Arc, Mutex},
|
||||
thread::JoinHandle,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use super::block::RFunction;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VData {
|
||||
// parents: Vec<()>,
|
||||
pub data: VDataEnum,
|
||||
}
|
||||
impl VData {
|
||||
pub fn out(&self) -> VType {
|
||||
VType {
|
||||
types: vec![self.out_single()],
|
||||
}
|
||||
}
|
||||
pub fn out_single(&self) -> VSingleType {
|
||||
match &self.data {
|
||||
VDataEnum::Bool(..) => VSingleType::Bool,
|
||||
VDataEnum::Int(..) => VSingleType::Int,
|
||||
VDataEnum::Float(..) => VSingleType::Float,
|
||||
VDataEnum::String(..) => VSingleType::String,
|
||||
VDataEnum::Tuple(v) => VSingleType::Tuple(v.iter().map(|v| v.out()).collect()),
|
||||
VDataEnum::List(t, _) => VSingleType::List(t.clone()),
|
||||
VDataEnum::Function(f) => VSingleType::Function(f.input_output_map.clone()),
|
||||
VDataEnum::Thread(_, o) => VSingleType::Thread(o.clone()),
|
||||
VDataEnum::Reference(r) => r.lock().unwrap().out_single(),
|
||||
}
|
||||
}
|
||||
pub fn get(&self, i: usize) -> Option<Self> {
|
||||
self.data.get(i)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum VDataEnum {
|
||||
Bool(bool),
|
||||
Int(isize),
|
||||
Float(f64),
|
||||
String(String),
|
||||
Tuple(Vec<VData>),
|
||||
List(VType, Vec<VData>),
|
||||
Function(RFunction),
|
||||
Thread(VDataThread, VType),
|
||||
Reference(Arc<Mutex<VData>>),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct VDataThread(Arc<Mutex<VDataThreadEnum>>);
|
||||
impl VDataThread {
|
||||
pub fn try_get(&self) -> Option<VData> {
|
||||
match &*self.lock() {
|
||||
VDataThreadEnum::Running(_) => None,
|
||||
VDataThreadEnum::Finished(v) => Some(v.clone()),
|
||||
}
|
||||
}
|
||||
pub fn get(&self) -> VData {
|
||||
let dur = Duration::from_millis(100);
|
||||
loop {
|
||||
match &*self.lock() {
|
||||
VDataThreadEnum::Running(v) => {
|
||||
while !v.is_finished() {
|
||||
std::thread::sleep(dur);
|
||||
}
|
||||
}
|
||||
VDataThreadEnum::Finished(v) => return v.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn lock(&self) -> std::sync::MutexGuard<VDataThreadEnum> {
|
||||
let mut mg = self.0.lock().unwrap();
|
||||
match &*mg {
|
||||
VDataThreadEnum::Running(v) => {
|
||||
if v.is_finished() {
|
||||
let m = std::mem::replace(
|
||||
&mut *mg,
|
||||
VDataThreadEnum::Finished(VData {
|
||||
data: VDataEnum::Bool(false),
|
||||
}),
|
||||
);
|
||||
match m {
|
||||
VDataThreadEnum::Running(v) => {
|
||||
*mg = VDataThreadEnum::Finished(v.join().unwrap())
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
mg
|
||||
}
|
||||
}
|
||||
impl Debug for VDataThread {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match &*self.lock() {
|
||||
VDataThreadEnum::Running(_) => write!(f, "(thread running)"),
|
||||
VDataThreadEnum::Finished(v) => write!(f, "(thread finished: {v})"),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub enum VDataThreadEnum {
|
||||
Running(JoinHandle<VData>),
|
||||
Finished(VData),
|
||||
}
|
||||
impl VDataThreadEnum {
|
||||
pub fn to(self) -> VDataThread {
|
||||
VDataThread(Arc::new(Mutex::new(self)))
|
||||
}
|
||||
}
|
||||
|
||||
impl VDataEnum {
|
||||
pub fn to(self) -> VData {
|
||||
VData { data: self }
|
||||
}
|
||||
}
|
||||
|
||||
// get()
|
||||
impl VDataEnum {
|
||||
pub fn get(&self, i: usize) -> Option<VData> {
|
||||
match self {
|
||||
Self::Bool(..)
|
||||
| Self::Int(..)
|
||||
| Self::Float(..)
|
||||
| Self::Function(..)
|
||||
| Self::Thread(..) => None,
|
||||
Self::String(s) => match s.chars().nth(i) {
|
||||
// Slow!
|
||||
Some(ch) => Some(Self::String(format!("{ch}")).to()),
|
||||
None => None,
|
||||
},
|
||||
Self::Tuple(v) | Self::List(_, v) => v.get(i).cloned(),
|
||||
Self::Reference(r) => r.lock().unwrap().get(i),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl VSingleType {
|
||||
// None => Cannot get, Some(t) => getting can return t or nothing
|
||||
pub fn get(&self, i: usize) -> Option<VType> {
|
||||
match self {
|
||||
Self::Bool | Self::Int | Self::Float | Self::Function(..) | Self::Thread(..) => None,
|
||||
Self::String => Some(VSingleType::String.into()),
|
||||
Self::Tuple(t) => t.get(i).cloned(),
|
||||
Self::List(t) => Some(t.clone()),
|
||||
Self::Reference(r) => r.get(i),
|
||||
}
|
||||
}
|
||||
pub fn get_any(&self) -> Option<VType> {
|
||||
match self {
|
||||
Self::Bool | Self::Int | Self::Float | Self::Function(..) | Self::Thread(..) => None,
|
||||
Self::String => Some(VSingleType::String.into()),
|
||||
Self::Tuple(t) => Some(t.iter().fold(VType { types: vec![] }, |a, b| a | b)),
|
||||
Self::List(t) => Some(t.clone()),
|
||||
Self::Reference(r) => r.get_any(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl VType {
|
||||
pub fn get(&self, i: usize) -> Option<VType> {
|
||||
let mut out = VType { types: vec![] };
|
||||
for t in &self.types {
|
||||
out = out | t.get(i)?; // if we can't use *get* on one type, we can't use it at all.
|
||||
}
|
||||
Some(out)
|
||||
}
|
||||
pub fn get_any(&self) -> Option<VType> {
|
||||
let mut out = VType { types: vec![] };
|
||||
for t in &self.types {
|
||||
out = out | t.get_any()?; // if we can't use *get* on one type, we can't use it at all.
|
||||
}
|
||||
Some(out)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct VType {
|
||||
pub types: Vec<VSingleType>,
|
||||
}
|
||||
impl VType {
|
||||
/// Returns a vec with all types in self that aren't covered by rhs. If the returned vec is empty, self fits in rhs.
|
||||
pub fn fits_in(&self, rhs: &Self) -> Vec<VSingleType> {
|
||||
let mut no = vec![];
|
||||
for t in &self.types {
|
||||
// if t doesnt fit in any of rhs's types
|
||||
if !rhs.types.iter().any(|r| t.fits_in(r)) {
|
||||
no.push(t.clone())
|
||||
}
|
||||
}
|
||||
no
|
||||
}
|
||||
pub fn inner_types(&self) -> VType {
|
||||
let mut out = VType { types: vec![] };
|
||||
for t in &self.types {
|
||||
for it in t.inner_types() {
|
||||
out = out | it.to();
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
pub fn contains(&self, t: &VSingleType) -> bool {
|
||||
self.types.contains(t)
|
||||
}
|
||||
}
|
||||
impl BitOr for VType {
|
||||
type Output = Self;
|
||||
fn bitor(self, rhs: Self) -> Self::Output {
|
||||
let mut types = self.types;
|
||||
for t in rhs.types {
|
||||
if !types.contains(&t) {
|
||||
types.push(t)
|
||||
}
|
||||
}
|
||||
Self { types }
|
||||
}
|
||||
}
|
||||
impl BitOr<&VType> for VType {
|
||||
type Output = Self;
|
||||
fn bitor(self, rhs: &Self) -> Self::Output {
|
||||
let mut types = self.types;
|
||||
for t in &rhs.types {
|
||||
if !types.contains(t) {
|
||||
types.push(t.clone())
|
||||
}
|
||||
}
|
||||
Self { types }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum VSingleType {
|
||||
Bool,
|
||||
Int,
|
||||
Float,
|
||||
String,
|
||||
Tuple(Vec<VType>),
|
||||
List(VType),
|
||||
Function(Vec<(Vec<VSingleType>, VType)>),
|
||||
Thread(VType),
|
||||
Reference(Box<Self>),
|
||||
}
|
||||
impl VSingleType {
|
||||
pub fn to(self) -> VType {
|
||||
VType { types: vec![self] }
|
||||
}
|
||||
pub fn inner_types(&self) -> Vec<VSingleType> {
|
||||
match self {
|
||||
Self::Tuple(v) => {
|
||||
let mut types = vec![];
|
||||
for it in v {
|
||||
// the tuple values
|
||||
for it in &it.types {
|
||||
// the possible types for each value
|
||||
if !types.contains(it) {
|
||||
types.push(it.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
types
|
||||
}
|
||||
Self::List(v) => v.types.clone(),
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
pub fn fits_in(&self, rhs: &Self) -> bool {
|
||||
match (self, rhs) {
|
||||
(Self::Bool, Self::Bool)
|
||||
| (Self::Int, Self::Int)
|
||||
| (Self::Float, Self::Float)
|
||||
| (Self::String, Self::String) => true,
|
||||
(Self::Bool | Self::Int | Self::Float | Self::String, _) => false,
|
||||
(Self::Tuple(a), Self::Tuple(b)) => {
|
||||
if a.len() == b.len() {
|
||||
a.iter().zip(b.iter()).all(|(a, b)| a.fits_in(b).is_empty())
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
(Self::Tuple(_), _) => false,
|
||||
(Self::List(a), Self::List(b)) => a.fits_in(b).is_empty(),
|
||||
(Self::List(_), _) => false,
|
||||
(Self::Function(a), Self::Function(b)) => 'func_out: {
|
||||
for a in a {
|
||||
'search: {
|
||||
for b in b {
|
||||
if a.1.fits_in(&b.1).is_empty()
|
||||
&& a.0.iter().zip(b.0.iter()).all(|(a, b)| *a == *b)
|
||||
{
|
||||
break 'search;
|
||||
}
|
||||
}
|
||||
break 'func_out false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
(Self::Function(..), _) => false,
|
||||
(Self::Thread(a), Self::Thread(b)) => a.fits_in(b).is_empty(),
|
||||
(Self::Thread(..), _) => false,
|
||||
(Self::Reference(r), Self::Reference(b)) => r.fits_in(b),
|
||||
(Self::Reference(_), _) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<VType> for VSingleType {
|
||||
fn into(self) -> VType {
|
||||
VType { types: vec![self] }
|
||||
}
|
||||
}
|
||||
// moved to val_data and val_type
|
||||
|
Loading…
Reference in New Issue
Block a user