cleaned up script/value.rs by splitting it up into val_data and val_type.

This commit is contained in:
Dummi26 2023-03-17 14:23:54 +01:00
parent a43a23da8c
commit 664de5c347
6 changed files with 13 additions and 336 deletions

View File

@ -1,26 +1,9 @@
use std::time::Instant; use std::time::Instant;
use crate::script::value::{VSingleType, VType};
pub(crate) mod parse; pub(crate) mod parse;
pub(crate) mod script; pub(crate) mod script;
fn main() { 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( let script = parse::parse::parse(&mut parse::file::File::new(
std::fs::read_to_string(std::env::args().nth(1).unwrap()).unwrap(), std::fs::read_to_string(std::env::args().nth(1).unwrap()).unwrap(),
)) ))

View File

@ -3,7 +3,8 @@ use crate::script::{
to_runnable, to_runnable::ToRunnableError, RScript, SBlock, SFunction, SStatement, to_runnable, to_runnable::ToRunnableError, RScript, SBlock, SFunction, SStatement,
SStatementEnum, SStatementEnum,
}, },
value::{VDataEnum, VSingleType, VType}, val_data::VDataEnum,
val_type::{VSingleType, VType},
}; };
use super::file::File; use super::file::File;

View 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. // 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::{ use std::{
collections::HashSet,
fmt::Display, fmt::Display,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
@ -11,7 +10,8 @@ use self::to_runnable::ToRunnableError;
use super::{ use super::{
builtins::BuiltinFunction, builtins::BuiltinFunction,
value::{VData, VDataEnum, VSingleType, VType}, val_data::{VData, VDataEnum},
val_type::{VSingleType, VType},
}; };
// Represents a block of code // Represents a block of code
@ -95,7 +95,10 @@ pub mod to_runnable {
sync::Arc, sync::Arc,
}; };
use crate::script::value::{VDataEnum, VSingleType, VType}; use crate::script::{
val_data::VDataEnum,
val_type::{VSingleType, VType},
};
use super::{ use super::{
BuiltinFunction, RBlock, RFunction, RScript, RStatement, RStatementEnum, SBlock, SFunction, BuiltinFunction, RBlock, RFunction, RScript, RStatement, RStatementEnum, SBlock, SFunction,

View File

@ -6,7 +6,8 @@ use std::{
use super::{ use super::{
block::RStatement, block::RStatement,
value::{VData, VDataEnum, VDataThreadEnum, VSingleType, VType}, val_data::{VData, VDataEnum, VDataThreadEnum},
val_type::{VSingleType, VType},
}; };
#[derive(Clone, Debug)] #[derive(Clone, Debug)]

View File

@ -1,3 +1,5 @@
pub mod block; pub mod block;
pub mod builtins; pub mod builtins;
pub mod val_data;
pub mod val_type;
pub mod value; pub mod value;

View File

@ -1,314 +1 @@
use std::{ // moved to val_data and val_type
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] }
}
}