From 696a4eff5bf4f0947a10afec7458e95b0f94b7c4 Mon Sep 17 00:00:00 2001 From: Nordine Bittich Date: Fri, 22 Sep 2023 19:08:34 +0200 Subject: [PATCH] move script intrinsics to a separate crate --- Cargo.lock | 13 + Cargo.toml | 1 + src/adana_script/ast.rs | 11 +- src/adana_script/compute.rs | 147 +-- src/adana_script/mod.rs | 274 +---- src/adana_script/parser.rs | 10 +- src/adana_script/primitive.rs | 1152 ---------------------- src/adana_script/tests/builtin.rs | 4 +- src/adana_script/tests/examples.rs | 4 +- src/adana_script/tests/foreach.rs | 3 +- src/adana_script/tests/funct.rs | 3 +- src/adana_script/tests/misc.rs | 8 +- src/adana_script/tests/range.rs | 4 +- src/adana_script/tests/strings.rs | 3 +- src/adana_script/tests/struc.rs | 21 +- src/adana_script/tests/test_array.rs | 12 +- src/adana_script/tests/test_chaining.rs | 4 +- src/adana_script/tests/test_drop.rs | 4 +- src/adana_script/tests/test_parser.rs | 4 +- src/adana_script/tests/test_reference.rs | 4 +- src/adana_script/tests/test_scope_ctx.rs | 4 +- src/adana_script/tests/tests_file.rs | 3 +- src/adana_script/tests/unused.rs | 4 +- src/cache_command/process.rs | 3 +- src/editor.rs | 2 +- src/main.rs | 2 +- src/reserved_keywords.rs | 6 +- 27 files changed, 160 insertions(+), 1550 deletions(-) delete mode 100644 src/adana_script/primitive.rs diff --git a/Cargo.lock b/Cargo.lock index 2bfff43..336aec1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,6 +6,7 @@ version = 3 name = "adana" version = "0.13.35" dependencies = [ + "adana-script-core", "anyhow", "bincode", "ctrlc", @@ -24,6 +25,18 @@ dependencies = [ "strum", ] +[[package]] +name = "adana-script-core" +version = "0.13.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b57814e0056e7a9ec8debf356f04a72ef779c14190491697d6f6fcff180be1" +dependencies = [ + "anyhow", + "serde", + "serde_derive", + "strum", +] + [[package]] name = "aho-corasick" version = "1.0.2" diff --git a/Cargo.toml b/Cargo.toml index f9ce1a9..b754c10 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ serde_json = "1.0.107" slab_tree = "0.3.2" strum = { version = "0.25.0", features = ["derive"] } ctrlc = "3.4.1" +adana-script-core = "0.13.35" [dependencies.env_logger] default-features = false version = "0.10.0" diff --git a/src/adana_script/ast.rs b/src/adana_script/ast.rs index 7c422ee..2438df1 100644 --- a/src/adana_script/ast.rs +++ b/src/adana_script/ast.rs @@ -2,14 +2,11 @@ use std::borrow::Borrow; use slab_tree::{NodeId, Tree}; -use crate::{ - adana_script::primitive::ToNumber, - prelude::{BTreeMap, Context}, -}; +use crate::prelude::{BTreeMap, Context}; -use super::{ - primitive::{Neg, RefPrimitive}, - MathConstants, Operator, Primitive, TreeNodeValue, Value, +use adana_script_core::{ + primitive::{Neg, Primitive, RefPrimitive, ToNumber}, + MathConstants, Operator, TreeNodeValue, Value, }; fn variable_from_ctx( diff --git a/src/adana_script/compute.rs b/src/adana_script/compute.rs index 8ed233c..64de2ae 100644 --- a/src/adana_script/compute.rs +++ b/src/adana_script/compute.rs @@ -11,8 +11,8 @@ use std::{ use crate::{adana_script::parser::parse_instructions, prelude::BTreeMap}; -use super::{ - ast::to_ast, +use super::ast::to_ast; +use adana_script_core::{ primitive::{ Abs, Add, And, Array, Cos, Div, Logarithm, Mul, Neg, Not, Or, Pow, Primitive, RefPrimitive, Rem, Sin, Sqrt, Sub, Tan, ToBool, ToNumber, @@ -227,87 +227,106 @@ fn compute_recur( TreeNodeValue::BuiltInFunction(fn_type) => { let v = compute_recur(node.first_child(), ctx)?; match fn_type { - super::BuiltInFunctionType::Sqrt => Ok(v.sqrt()), - super::BuiltInFunctionType::Abs => Ok(v.abs()), - super::BuiltInFunctionType::Log => Ok(v.log()), - super::BuiltInFunctionType::Ln => Ok(v.ln()), - super::BuiltInFunctionType::Sin => Ok(v.sin()), - super::BuiltInFunctionType::Cos => Ok(v.cos()), - super::BuiltInFunctionType::Eval => { + adana_script_core::BuiltInFunctionType::Sqrt => { + Ok(v.sqrt()) + } + adana_script_core::BuiltInFunctionType::Abs => Ok(v.abs()), + adana_script_core::BuiltInFunctionType::Log => Ok(v.log()), + adana_script_core::BuiltInFunctionType::Ln => Ok(v.ln()), + adana_script_core::BuiltInFunctionType::Sin => Ok(v.sin()), + adana_script_core::BuiltInFunctionType::Cos => Ok(v.cos()), + adana_script_core::BuiltInFunctionType::Eval => { if let Primitive::String(script) = v { compute(&script, ctx) } else { Ok(Primitive::Error(format!("invalid script {v}"))) } } - super::BuiltInFunctionType::Tan => Ok(v.tan()), - super::BuiltInFunctionType::ToInt => Ok(v.to_int()), - super::BuiltInFunctionType::ToDouble => Ok(v.to_double()), - super::BuiltInFunctionType::ToBool => Ok(v.to_bool()), - super::BuiltInFunctionType::ToString => { + adana_script_core::BuiltInFunctionType::Tan => Ok(v.tan()), + adana_script_core::BuiltInFunctionType::ToInt => { + Ok(v.to_int()) + } + adana_script_core::BuiltInFunctionType::ToDouble => { + Ok(v.to_double()) + } + adana_script_core::BuiltInFunctionType::ToBool => { + Ok(v.to_bool()) + } + adana_script_core::BuiltInFunctionType::ToString => { Ok(Primitive::String(v.to_string())) } - super::BuiltInFunctionType::Length => Ok(v.len()), - super::BuiltInFunctionType::Println => { + adana_script_core::BuiltInFunctionType::Length => { + Ok(v.len()) + } + adana_script_core::BuiltInFunctionType::Println => { println!("{v}"); Ok(Primitive::Unit) } - super::BuiltInFunctionType::Print => { + adana_script_core::BuiltInFunctionType::Print => { print!("{v}"); Ok(Primitive::Unit) } - super::BuiltInFunctionType::Include => match v { - Primitive::String(file_path) => { - let curr_path = std::env::current_dir() - .context("no current dir! wasn't expected")?; - let temp_path = Path::new(&file_path); - if temp_path.is_absolute() || temp_path.exists() { - let parent = temp_path - .parent() - .context("parent doesn't exist")?; + adana_script_core::BuiltInFunctionType::Include => { + match v { + Primitive::String(file_path) => { + let curr_path = std::env::current_dir() + .context( + "no current dir! wasn't expected", + )?; + let temp_path = Path::new(&file_path); + if temp_path.is_absolute() || temp_path.exists() + { + let parent = temp_path + .parent() + .context("parent doesn't exist")?; - std::env::set_current_dir(PathBuf::from( - &parent, - ))?; - } + std::env::set_current_dir(PathBuf::from( + &parent, + ))?; + } - let res = temp_path - .file_name() - .context("file name not found") - .and_then(|p| { - read_to_string(p) - .map_err(anyhow::Error::new) - }) - .and_then(move |file| compute(&file, ctx)); - std::env::set_current_dir(curr_path)?; // todo this might be quiet fragile - res + let res = temp_path + .file_name() + .context("file name not found") + .and_then(|p| { + read_to_string(p) + .map_err(anyhow::Error::new) + }) + .and_then(move |file| compute(&file, ctx)); + std::env::set_current_dir(curr_path)?; // todo this might be quiet fragile + res + } + _ => Ok(Primitive::Error( + "wrong include call".to_string(), + )), } - _ => Ok(Primitive::Error( - "wrong include call".to_string(), - )), - }, - super::BuiltInFunctionType::ReadLines => match v { - Primitive::String(file_path) => { - if !PathBuf::from(file_path.as_str()).exists() { - Ok(Primitive::Error(format!( - "file {file_path} not found" - ))) - } else { - let file = File::open(file_path)?; - let reader = BufReader::new(file); - Ok(Primitive::Array( - reader - .lines() - .map(|s| s.map(Primitive::String)) - .collect::, _>>()?, - )) + } + adana_script_core::BuiltInFunctionType::ReadLines => { + match v { + Primitive::String(file_path) => { + if !PathBuf::from(file_path.as_str()).exists() { + Ok(Primitive::Error(format!( + "file {file_path} not found" + ))) + } else { + let file = File::open(file_path)?; + let reader = BufReader::new(file); + Ok(Primitive::Array( + reader + .lines() + .map(|s| s.map(Primitive::String)) + .collect::, _>>()?, + )) + } } + _ => Ok(Primitive::Error( + "wrong read lines call".to_string(), + )), } - _ => Ok(Primitive::Error( - "wrong read lines call".to_string(), - )), - }, - super::BuiltInFunctionType::TypeOf => Ok(v.type_of()), + } + adana_script_core::BuiltInFunctionType::TypeOf => { + Ok(v.type_of()) + } } } TreeNodeValue::IfExpr(v) => { diff --git a/src/adana_script/mod.rs b/src/adana_script/mod.rs index 3c3c54e..db1f0ec 100644 --- a/src/adana_script/mod.rs +++ b/src/adana_script/mod.rs @@ -1,291 +1,19 @@ mod ast; mod compute; mod parser; -mod primitive; mod string_parser; use std::collections::BTreeMap; +use adana_script_core::TreeNodeValue; pub use compute::compute; use nu_ansi_term::Color; -pub use primitive::Primitive; -pub use primitive::RefPrimitive; -use serde::{Deserialize, Serialize}; use slab_tree::Tree; -use strum::EnumCount; use crate::adana_script::ast::to_ast; use crate::adana_script::parser::parse_instructions; -use self::constants::TO_STRING; -use self::constants::{ - ABS, COS, EVAL, INCLUDE, LENGTH, LN, LOG, PRINT, PRINT_LN, READ_LINES, SIN, - SQRT, TAN, TO_BOOL, TO_DOUBLE, TO_INT, TYPE_OF, -}; - -#[macro_use] -pub mod constants { - macro_rules! pi { - () => { - 'π' - }; - } - macro_rules! euler_number { - () => { - 'γ' - }; - } - macro_rules! tau { - () => { - 'τ' - }; - } - pub const TRUE: &str = "true"; - pub const FALSE: &str = "false"; - pub const IF: &str = "if"; - pub const ELSE: &str = "else"; - pub const WHILE: &str = "while"; - pub const TAU: &str = concat!(tau!()); - pub const PI: &str = concat!(pi!()); - pub const EULER_NUMBER: &str = concat!(euler_number!()); - pub const SQRT: &str = "sqrt"; - pub const TO_INT: &str = "to_int"; - pub const TO_BOOL: &str = "to_bool"; - pub const TO_DOUBLE: &str = "to_double"; - pub const TO_STRING: &str = "to_string"; - pub const ABS: &str = "abs"; - pub const LENGTH: &str = "length"; - pub const LOG: &str = "log"; - pub const LN: &str = "ln"; - pub const READ_LINES: &str = "read_lines"; - pub const SIN: &str = "sin"; - pub const COS: &str = "cos"; - pub const TAN: &str = "tan"; - pub const BREAK: &str = "break"; - pub const RETURN: &str = "return"; - pub const PRINT_LN: &str = "println"; - pub const PRINT: &str = "print"; - pub const INCLUDE: &str = "include"; - pub const DROP: &str = "drop"; - pub const NULL: &str = "null"; - pub const MULTILINE: &str = "multiline"; - pub const STRUCT: &str = "struct"; - pub const EVAL: &str = "eval"; - pub const TYPE_OF: &str = "type_of"; - pub const FOR: &str = "for"; - pub const IN: &str = "in"; -} - -#[derive(Debug, EnumCount)] -pub(super) enum MathConstants { - Pi, - EulerNumber, - Tau, -} - -impl MathConstants { - pub(super) const fn get_symbol(&self) -> char { - match self { - MathConstants::Pi => pi!(), - MathConstants::EulerNumber => euler_number!(), - MathConstants::Tau => tau!(), - } - } - pub(super) const fn get_symbols() -> &'static str { - concat!(pi!(), euler_number!(), tau!()) - } - - pub(super) const fn _get_variants( - ) -> &'static [&'static MathConstants; MathConstants::COUNT] { - &[&MathConstants::Pi, &MathConstants::EulerNumber, &MathConstants::Tau] - } -} - -#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] -pub enum Value { - Break, - EarlyReturn(Box>), - Drop(Box), - Expression(Vec), - ImplicitMultiply(Box), - Operation(Operator), - BuiltInFunction { - fn_type: BuiltInFunctionType, - expr: Box, - }, - Function { - parameters: Box, - exprs: Vec, - }, - FunctionCall { - parameters: Box, - function: Box, - }, - Null, - Decimal(f64), - Integer(i128), - Bool(bool), - Range { - start: Box, - incl_both_end: bool, - end: Box, - }, - NoOp, - String(String), - FString(String, Vec<(String, Value)>), - BlockParen(Vec), - Variable(String), - VariableRef(String), - VariableUnused, - Const(char), - VariableNegate(String), - VariableExpr { - name: Box, - expr: Box, - }, - IfExpr { - cond: Box, - exprs: Vec, - else_expr: Option>, - }, - WhileExpr { - cond: Box, - exprs: Vec, - }, - ForeachExpr { - var: String, - index_var: Option, - iterator: Box, - exprs: Vec, - }, - Array(Vec), - ArrayAccess { - arr: Box, - index: Box, - }, - Struct(BTreeMap), - StructAccess { - struc: Box, - key: String, - }, -} -#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)] -pub enum BuiltInFunctionType { - Sqrt, - Abs, - Log, - Ln, - Sin, - Cos, - ToInt, - ToDouble, - ToBool, - ToString, - Tan, - Println, - ReadLines, - Print, - Eval, - TypeOf, - Length, - Include, -} - -#[derive(Debug, Eq, PartialEq, Copy, Clone, Serialize, Deserialize)] -pub enum Operator { - Add, - Subtr, - Mult, - Div, - Mod, - Pow, - Pow2, - Pow3, - Not, - Less, - Greater, - LessOrEqual, - GreaterOrEqual, - Equal, - NotEqual, - And, - Or, -} - -#[derive(Debug)] -pub enum TreeNodeValue { - Break, - EarlyReturn(Option), - Drop(Vec), - VariableUnused, - VariableAssign(Option), - VariableArrayAssign { name: String, index: Value }, - Ops(Operator), - Primitive(Primitive), - VariableRef(String), - BuiltInFunction(BuiltInFunctionType), - IfExpr(Value), - FString(String, Vec<(String, Value)>), - WhileExpr(Value), - Array(Vec), - Struct(BTreeMap), - StructAccess { struc: Value, key: Primitive }, - ArrayAccess { index: Value, array: Value }, - Function(Value), - FunctionCall(Value), - Foreach(Value), - Null, -} - -impl BuiltInFunctionType { - pub(super) fn as_str(&self) -> &'static str { - match self { - BuiltInFunctionType::Sqrt => SQRT, - BuiltInFunctionType::Abs => ABS, - BuiltInFunctionType::Log => LOG, - BuiltInFunctionType::Ln => LN, - BuiltInFunctionType::Length => LENGTH, - BuiltInFunctionType::Sin => SIN, - BuiltInFunctionType::Cos => COS, - BuiltInFunctionType::Tan => TAN, - BuiltInFunctionType::TypeOf => TYPE_OF, - BuiltInFunctionType::Println => PRINT_LN, - BuiltInFunctionType::Print => PRINT, - BuiltInFunctionType::Eval => EVAL, - BuiltInFunctionType::Include => INCLUDE, - BuiltInFunctionType::ReadLines => READ_LINES, - BuiltInFunctionType::ToInt => TO_INT, - BuiltInFunctionType::ToDouble => TO_DOUBLE, - BuiltInFunctionType::ToBool => TO_BOOL, - BuiltInFunctionType::ToString => TO_STRING, - } - } -} -impl Operator { - pub(super) const fn as_str(&self) -> &'static str { - match self { - Operator::Add => "+", - Operator::Subtr => "-", - Operator::Div => "/", - Operator::Mult => "*", - Operator::Pow => "^", - Operator::Pow2 => "²", - Operator::Pow3 => "³", - Operator::Not => "!", - Operator::Mod => "%", - Operator::Less => "<", - Operator::Greater => ">", - Operator::LessOrEqual => "<=", - Operator::GreaterOrEqual => ">=", - Operator::Equal => "==", - Operator::NotEqual => "!=", - Operator::And => "&&", - Operator::Or => "||", - } - } -} - pub fn print_ast(script: &str) -> anyhow::Result<()> { let (rest, instructions) = parse_instructions(script).map_err(|e| { anyhow::Error::msg(format!( diff --git a/src/adana_script/parser.rs b/src/adana_script/parser.rs index ce2f691..d341885 100644 --- a/src/adana_script/parser.rs +++ b/src/adana_script/parser.rs @@ -10,13 +10,11 @@ use crate::{ reserved_keywords::check_reserved_keyword, }; -use super::{ - constants::{ - BREAK, DROP, ELSE, FOR, IF, IN, MULTILINE, NULL, RETURN, STRUCT, WHILE, - }, - string_parser::parse_escaped_string, - BuiltInFunctionType, MathConstants, Operator, Value, +use super::string_parser::parse_escaped_string; +use adana_script_core::constants::{ + BREAK, DROP, ELSE, FOR, IF, IN, MULTILINE, NULL, RETURN, STRUCT, WHILE, }; +use adana_script_core::{BuiltInFunctionType, MathConstants, Operator, Value}; pub(super) fn comments(s: &str) -> Res> { terminated( diff --git a/src/adana_script/primitive.rs b/src/adana_script/primitive.rs deleted file mode 100644 index e0bf917..0000000 --- a/src/adana_script/primitive.rs +++ /dev/null @@ -1,1152 +0,0 @@ -use std::{ - cmp::Ordering, - collections::BTreeMap, - fmt::Display, - sync::{Arc, RwLock}, -}; - -use anyhow::Result; - -use crate::prelude::{Deserialize, Serialize}; - -use super::{constants::NULL, Value}; - -const MAX_U32_AS_I128: i128 = u32::MAX as i128; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum Primitive { - Int(i128), - Bool(bool), - Ref(RefPrimitive), - Null, - Double(f64), - String(String), - Array(Vec), - Struct(BTreeMap), - Error(String), - Function { parameters: Vec, exprs: Vec }, - Unit, - NoReturn, - EarlyReturn(Box), -} - -pub type RefPrimitive = Arc>; - -// region: traits -impl Primitive { - pub fn ref_prim(self) -> RefPrimitive { - Arc::new(RwLock::new(self)) - } -} - -pub trait TypeOf { - fn type_of(&self) -> Self; -} -pub trait ToBool { - fn to_bool(&self) -> Self; -} -pub trait ToNumber { - fn to_int(&self) -> Self; - fn to_double(&self) -> Self; -} -pub trait Pow { - fn pow(&self, n: &Self) -> Self; -} - -pub trait And { - fn and(&self, n: &Self) -> Self; -} -pub trait Or { - fn or(&self, n: &Self) -> Self; -} -pub trait Sqrt { - fn sqrt(&self) -> Self; -} -pub trait Abs { - fn abs(&self) -> Self; -} -pub trait Logarithm { - fn log(&self) -> Self; - fn ln(&self) -> Self; -} - -pub trait Sin { - fn sin(&self) -> Self; -} -pub trait Array { - fn index_at(&self, rhs: &Self) -> Self; - fn len(&self) -> Primitive; - fn swap_mem(&mut self, rhs: &mut Self, index: &Primitive) -> Self; - fn remove(&mut self, key: &Self) -> anyhow::Result<()>; -} - -pub trait Cos { - fn cos(&self) -> Self; -} -pub trait Tan { - fn tan(&self) -> Self; -} - -pub trait Add { - fn add(&self, rhs: &Self) -> Self; -} - -pub trait Neg { - fn neg(&self) -> Self; -} - -pub trait Not { - fn not(&self) -> Self; -} - -pub trait Sub { - fn sub(&self, rhs: &Self) -> Self; -} - -pub trait Mul { - fn mul(&self, rhs: &Self) -> Self; -} - -pub trait Div { - fn div(&self, rhs: &Self) -> Self; -} - -pub trait Rem { - fn rem(&self, rhs: &Self) -> Self; -} -// endregion traits - -// region: impl primitive -#[allow(dead_code)] -impl Primitive { - pub fn is_greater_than(&self, other: &Primitive) -> Primitive { - match self.partial_cmp(other) { - Some(Ordering::Greater) => Primitive::Bool(true), - Some(Ordering::Less) => Primitive::Bool(false), - Some(Ordering::Equal) => Primitive::Bool(false), - None => Primitive::Error( - format!("call to is_greater_than() for two different types {self} => {other}") - ), - } - } - pub fn is_greater_or_equal(&self, other: &Primitive) -> Primitive { - match self.partial_cmp(other) { - Some(Ordering::Greater) | Some(Ordering::Equal) => { - Primitive::Bool(true) - } - Some(Ordering::Less) => Primitive::Bool(false), - None => Primitive::Error( - format!("call to is_greater_or_equal() for two different types {self} => {other}") - ), - } - } - pub fn is_less_than(&self, other: &Primitive) -> Primitive { - match self.partial_cmp(other) { - Some(Ordering::Less) => Primitive::Bool(true), - Some(Ordering::Greater) => Primitive::Bool(false), - Some(Ordering::Equal) => Primitive::Bool(false), - None => Primitive::Error( - format!("call to is_less_than() for two different types {self} => {other}") - ), - } - } - pub fn is_less_or_equal(&self, other: &Primitive) -> Primitive { - match self.partial_cmp(other) { - Some(Ordering::Less) | Some(Ordering::Equal) => { - Primitive::Bool(true) - } - Some(Ordering::Greater) => Primitive::Bool(false), - None => Primitive::Error( - format!("call to is_less_or_equal() for two different types {self} => {other}") - ), - } - } - pub fn is_equal(&self, other: &Primitive) -> Primitive { - match self.partial_cmp(other) { - Some(Ordering::Equal) => Primitive::Bool(true), - Some(Ordering::Less) | Some(Ordering::Greater) => { - Primitive::Bool(false) - } - None => match (self, other) { - (Primitive::Null, _) | (_, Primitive::Null) => { - Primitive::Bool(false) - } - (Primitive::Struct(_), Primitive::Struct(_)) => { - Primitive::Bool(false) - } - _ => Primitive::Error( - format!("call to is_equal() for two different types {self} => {other}"), - ), - }, - } - } - pub fn as_ref_ok(&self) -> Result<&Primitive> { - match self { - Primitive::Error(msg) => Err(anyhow::Error::msg(msg.to_string())), - - _ => Ok(self), - } - } -} - -impl Display for Primitive { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Primitive::Ref(s) => { - let lock = s.read().expect("FMT ERROR: could not acquire lock"); - write!(f, "{lock}") - } - Primitive::Int(i) => write!(f, "{i}"), - Primitive::Double(d) => write!(f, "{d}"), - Primitive::Bool(b) => write!(f, "{b}"), - Primitive::Error(e) => write!(f, "Err: {e}"), - Primitive::String(s) => { - write!(f, "{s}") - } - Primitive::Unit => write!(f, "()"), - Primitive::Array(arr) => { - let joined_arr = arr - .iter() - .map(|p| match p { - Primitive::String(s) => format!(r#""{s}""#), - _ => p.to_string(), - }) - .collect::>(); - write!(f, "[{}]", joined_arr[..].join(", ")) - } - Primitive::Struct(struc) => { - let joined_arr = struc - .iter() - .map(|(k, p)| { - format!( - "\t{k}: {}", - if let Primitive::String(s) = p { - format!(r#""{s}""#) - } else { - p.to_string() - } - ) - }) - .collect::>(); - write!(f, "struct {{\n{}\n}}", joined_arr[..].join(", \n")) - } - Primitive::Function { parameters, exprs: _ } => { - let mut parameters_formatted = String::new(); - let len = parameters.len(); - for (idx, p) in parameters.iter().enumerate() { - match p { - Value::VariableUnused => parameters_formatted.push('_'), - _ => { - parameters_formatted.push('p'); - parameters_formatted.push( - char::from_digit(idx as u32, 10).unwrap_or('0'), - ); - } - } - if idx < len { - parameters_formatted.push(','); - } - } - write!(f, "({parameters_formatted}) => {{..}}") - } - Primitive::NoReturn => write!(f, "!"), - Primitive::Null => write!(f, "{NULL}"), - Primitive::EarlyReturn(p) => write!(f, "{p}"), - } - } -} - -impl Sin for Primitive { - fn sin(&self) -> Self { - match self { - Primitive::Ref(s) => { - let lock = - s.read().expect("SIN ERORR: could not acquire lock!"); - lock.sin() - } - Primitive::Int(i) => Primitive::Double((*i as f64).sin()), - Primitive::Double(d) => Primitive::Double(d.sin()), - - Primitive::Error(e) => panic!("call to sin() on an error. {e}"), - _ => Primitive::Error(format!("illegal call to sin() => {self}")), - } - } -} - -impl Cos for Primitive { - fn cos(&self) -> Self { - match self { - Primitive::Ref(s) => { - let lock = - s.read().expect("COS ERORR: could not acquire lock!"); - lock.cos() - } - Primitive::Int(i) => Primitive::Double((*i as f64).cos()), - Primitive::Double(d) => Primitive::Double(d.cos()), - Primitive::Error(e) => panic!("call to cos() on an error. {e}"), - _ => Primitive::Error(format!("illegal call to cos() => {self}")), - } - } -} - -impl Tan for Primitive { - fn tan(&self) -> Self { - match self { - Primitive::Ref(s) => { - let lock = - s.read().expect("TAN ERORR: could not acquire lock!"); - lock.tan() - } - Primitive::Int(i) => Primitive::Double((*i as f64).tan()), - Primitive::Double(d) => Primitive::Double(d.tan()), - Primitive::Error(e) => panic!("call to tan() on an error. {e}"), - _ => Primitive::Error(format!("illegal call to tan() => {self}")), - } - } -} - -impl Logarithm for Primitive { - fn log(&self) -> Self { - match self { - Primitive::Ref(s) => { - let lock = - s.read().expect("LOG ERORR: could not acquire lock!"); - lock.log() - } - Primitive::Int(i) => Primitive::Double((*i as f64).log10()), - Primitive::Double(d) => Primitive::Double(d.log10()), - Primitive::Error(e) => panic!("call to log() on an error. {e}"), - _ => Primitive::Error(format!("illegal call to log() => {self}")), - } - } - fn ln(&self) -> Self { - match self { - Primitive::Ref(s) => { - let lock = s.read().expect("LN ERORR: could not acquire lock!"); - lock.ln() - } - Primitive::Int(i) => Primitive::Double((*i as f64).ln()), - Primitive::Double(d) => Primitive::Double(d.ln()), - Primitive::Error(e) => panic!("call to ln() on an error. {e}"), - _ => Primitive::Error(format!("illegal call to ln() => {self}")), - } - } -} - -impl Sqrt for Primitive { - fn sqrt(&self) -> Self { - match self { - Primitive::Ref(s) => { - let lock = - s.read().expect("SQRT ERORR: could not acquire lock!"); - lock.sqrt() - } - Primitive::Int(i) => Primitive::Double((*i as f64).sqrt()), - Primitive::Double(d) => Primitive::Double(d.sqrt()), - Primitive::Error(e) => panic!("call to sqrt() on an error. {e}"), - _ => Primitive::Error(format!("illegal call to sqrt() => {self}")), - } - } -} -impl Abs for Primitive { - fn abs(&self) -> Self { - match self { - Primitive::Ref(s) => { - let lock = - s.read().expect("ABS ERORR: could not acquire lock!"); - lock.abs() - } - Primitive::Int(i) => Primitive::Int(i.abs()), - Primitive::Double(d) => Primitive::Double(d.abs()), - Primitive::Error(e) => panic!("call to abs() on an error. {e}"), - _ => Primitive::Error(format!("illegal call to abs() => {self}")), - } - } -} - -impl Pow for Primitive { - fn pow(&self, rhs: &Self) -> Self { - match (self, rhs) { - (Primitive::Ref(l), Primitive::Ref(r)) => { - let l = l.read().expect("POW L ERORR: could not acquire lock!"); - - let r = r.read().expect("POW R ERORR: could not acquire lock!"); - l.pow(&r) - } - (Primitive::Ref(l), r) => { - let l = l.read().expect("POW L ERORR: could not acquire lock!"); - - l.pow(r) - } - (l, Primitive::Ref(r)) => { - let r = r.read().expect("POW R ERORR: could not acquire lock!"); - - l.pow(&r) - } - #[allow(clippy::manual_range_contains)] - (Primitive::Int(l), Primitive::Int(r)) - if r >= &0 && r <= &MAX_U32_AS_I128 => - { - Primitive::Int(l.pow(*r as u32)) - } - (Primitive::Int(l), Primitive::Int(r)) => { - Primitive::Double((*l as f64).powf(*r as f64)) - } - (Primitive::Int(l), Primitive::Double(r)) => { - Primitive::Double((*l as f64).powf(*r)) - } - (Primitive::Double(l), Primitive::Int(r)) => { - Primitive::Double(l.powf(*r as f64)) - } - (Primitive::Double(l), Primitive::Double(r)) => { - Primitive::Double(l.powf(*r)) - } - (l, r) => Primitive::Error(format!( - "illegal call to pow() => left: {l} right: {r}" - )), - } - } -} - -impl Add for Primitive { - fn add(&self, rhs: &Self) -> Self { - match (self.clone(), rhs.clone()) { - (Primitive::Ref(l), Primitive::Ref(r)) => { - let l = l.read().expect("ADD L ERORR: could not acquire lock!"); - - let r = r.read().expect("ADD R ERORR: could not acquire lock!"); - l.add(&r) - } - (Primitive::Ref(l), r) => { - let l = l.read().expect("ADD L ERORR: could not acquire lock!"); - - l.add(&r) - } - (l, Primitive::Ref(r)) => { - let r = r.read().expect("ADD R ERORR: could not acquire lock!"); - - l.add(&r) - } - (Primitive::Int(l), Primitive::Int(r)) => Primitive::Int(l + r), - (Primitive::Int(l), Primitive::Double(r)) => { - Primitive::Double(l as f64 + r) - } - (Primitive::Int(l), Primitive::String(s)) => { - Primitive::String(format!("{l}{s}")) - } - - (Primitive::Double(l), Primitive::Int(r)) => { - Primitive::Double(l + r as f64) - } - (Primitive::Double(l), Primitive::Double(r)) => { - Primitive::Double(l + r) - } - (Primitive::Array(mut l), Primitive::Array(mut r)) => { - l.append(&mut r); - Primitive::Array(l) - } - - (Primitive::Array(mut l), r) => { - let r: Primitive = r; - l.push(r); - Primitive::Array(l) - } - (l, Primitive::Array(mut r)) => { - r.insert(0, l); - Primitive::Array(r) - } - (l, Primitive::String(s)) => Primitive::String(format!("{l}{s}")), - - (Primitive::String(s), r) => Primitive::String(format!("{s}{r}")), - (l, r) => Primitive::Error(format!( - "illegal call to add() => left: {l} right: {r}" - )), - } - } -} - -impl Sub for Primitive { - fn sub(&self, rhs: &Self) -> Self { - match (self.clone(), rhs.clone()) { - (Primitive::Ref(l), Primitive::Ref(r)) => { - let l = l.read().expect("SUB L ERORR: could not acquire lock!"); - - let r = r.read().expect("SUB R ERORR: could not acquire lock!"); - l.sub(&r) - } - (Primitive::Ref(l), r) => { - let l = l.read().expect("SUB L ERORR: could not acquire lock!"); - - l.sub(&r) - } - (l, Primitive::Ref(r)) => { - let r = r.read().expect("SUB R ERORR: could not acquire lock!"); - - l.sub(&r) - } - (Primitive::Int(l), Primitive::Int(r)) => Primitive::Int(l - r), - (Primitive::Int(l), Primitive::Double(r)) => { - Primitive::Double(l as f64 - r) - } - (Primitive::Double(l), Primitive::Int(r)) => { - Primitive::Double(l - r as f64) - } - (Primitive::Double(l), Primitive::Double(r)) => { - Primitive::Double(l - r) - } - (l, r) => Primitive::Error(format!( - "illegal call to sub() => left: {l} right: {r}" - )), - } - } -} - -impl Rem for Primitive { - fn rem(&self, rhs: &Self) -> Self { - match (self.clone(), rhs.clone()) { - (Primitive::Ref(l), Primitive::Ref(r)) => { - let l = l.read().expect("REM L ERORR: could not acquire lock!"); - - let r = r.read().expect("REM R ERORR: could not acquire lock!"); - l.rem(&r) - } - (Primitive::Ref(l), r) => { - let l = l.read().expect("REM L ERORR: could not acquire lock!"); - - l.rem(&r) - } - (l, Primitive::Ref(r)) => { - let r = r.read().expect("REM R ERORR: could not acquire lock!"); - - l.rem(&r) - } - (Primitive::Int(l), Primitive::Int(r)) if r != 0 => { - Primitive::Int(l % r) - } - (Primitive::Int(l), Primitive::Double(r)) => { - Primitive::Double(l as f64 % r) - } - (Primitive::Int(_), _) => Primitive::Double(f64::NAN), - - (Primitive::Double(l), Primitive::Int(r)) => { - Primitive::Double(l % r as f64) - } - (Primitive::Double(l), Primitive::Double(r)) => { - Primitive::Double(l % r) - } - - (l, r) => Primitive::Error(format!( - "illegal call to rem() => left: {l} right: {r}" - )), - } - } -} -impl Mul for Primitive { - fn mul(&self, rhs: &Self) -> Self { - fn multiply_array(arr: Vec, n: i128) -> Vec { - let arr_size = arr.len(); - arr.into_iter().cycle().take(n as usize * arr_size).collect() - } - match (self.clone(), rhs.clone()) { - (Primitive::Ref(l), Primitive::Ref(r)) => { - let l = l.read().expect("MUL L ERORR: could not acquire lock!"); - - let r = r.read().expect("MUL R ERORR: could not acquire lock!"); - l.mul(&r) - } - (Primitive::Ref(l), r) => { - let l = l.read().expect("MUL L ERORR: could not acquire lock!"); - - l.mul(&r) - } - (l, Primitive::Ref(r)) => { - let r = r.read().expect("MUL R ERORR: could not acquire lock!"); - - l.mul(&r) - } - (Primitive::Int(l), Primitive::Int(r)) => { - Primitive::Int(l.wrapping_mul(r)) - } - (Primitive::Int(l), Primitive::Double(r)) => { - Primitive::Double(l as f64 * r) - } - (Primitive::Int(l), Primitive::Array(r)) => { - Primitive::Array(multiply_array(r, l)) - } - (Primitive::Double(l), Primitive::Int(r)) => { - Primitive::Double(l * r as f64) - } - (Primitive::Double(l), Primitive::Double(r)) => { - Primitive::Double(l * r) - } - (Primitive::String(l), Primitive::Int(r)) => { - Primitive::String(l.repeat(r as usize)) - } - (Primitive::Array(l), Primitive::Int(n)) => { - Primitive::Array(multiply_array(l, n)) - } - - (l, r) => Primitive::Error(format!( - "illegal call to mul() => left: {l} right: {r}" - )), - } - } -} -impl Div for Primitive { - fn div(&self, rhs: &Self) -> Self { - match (self.clone(), rhs.clone()) { - (Primitive::Ref(l), Primitive::Ref(r)) => { - let l = l.read().expect("DIV L ERORR: could not acquire lock!"); - - let r = r.read().expect("DIV R ERORR: could not acquire lock!"); - l.div(&r) - } - (Primitive::Ref(l), r) => { - let l = l.read().expect("DIV L ERORR: could not acquire lock!"); - - l.div(&r) - } - (l, Primitive::Ref(r)) => { - let r = r.read().expect("DIV R ERORR: could not acquire lock!"); - - l.div(&r) - } - (Primitive::Int(l), Primitive::Int(r)) if r != 0 => { - Primitive::Int(l / r) - } - (Primitive::Int(l), Primitive::Double(r)) => { - Primitive::Double(l as f64 / r) - } - (Primitive::Int(l), Primitive::Int(_)) if l >= 1 => { - Primitive::Double(f64::INFINITY) - } - (Primitive::Int(_), _) => Primitive::Double(f64::NAN), - (Primitive::Double(l), Primitive::Int(r)) => { - Primitive::Double(l / r as f64) - } - (Primitive::Double(l), Primitive::Double(r)) => { - Primitive::Double(l / r) - } - (l, r) => Primitive::Error(format!( - "illegal call to div() => left: {l} right: {r}" - )), - } - } -} - -impl Neg for Primitive { - fn neg(&self) -> Self { - match self { - Primitive::Ref(s) => { - let lock = - s.read().expect("NEG ERORR: could not acquire lock!"); - lock.neg() - } - Primitive::Int(n) => Primitive::Int(-n), - Primitive::Double(n) => Primitive::Double(-n), - _ => Primitive::Error(format!("invalid call to neg() {self}")), - } - } -} - -impl Not for Primitive { - fn not(&self) -> Self { - match self { - Primitive::Ref(s) => { - let lock = - s.read().expect("NOT ERORR: could not acquire lock!"); - lock.not() - } - Primitive::Bool(b) => Primitive::Bool(!b), - _ => Primitive::Error(format!("invalid call to not() {self}")), - } - } -} - -impl ToBool for Primitive { - fn to_bool(&self) -> Self { - match self { - Primitive::Ref(s) => { - let lock = - s.read().expect("TO_BOOL ERORR: could not acquire lock!"); - lock.to_bool() - } - v @ Primitive::Bool(_) => v.clone(), - Primitive::Double(n) => Primitive::Bool(n > &0.0), - Primitive::Int(n) => Primitive::Bool(n > &0), - Primitive::Null => Primitive::Bool(false), - Primitive::Array(a) => Primitive::Bool(!a.is_empty()), - Primitive::String(s) => match s.parse::() { - Ok(b) => Primitive::Bool(b), - Err(e) => Primitive::Error(format!( - "invalid cast to bool: {self}, {e}" - )), - }, - _ => Primitive::Error(format!("invalide cast too bool: {self}")), - } - } -} - -impl ToNumber for Primitive { - fn to_int(&self) -> Self { - match self { - Primitive::Ref(s) => { - let lock = - s.read().expect("TO_INT ERORR: could not acquire lock!"); - lock.to_int() - } - v @ Primitive::Int(_) => v.clone(), - Primitive::Bool(false) => Primitive::Int(0), - Primitive::Bool(true) => Primitive::Int(1), - Primitive::Double(d) => Primitive::Int(*d as i128), - Primitive::String(s) => match s.parse::() { - Ok(number) => Primitive::Int(number), - Err(e) => Primitive::Error(format!( - "invalid cast to int: {self}, {e}" - )), - }, - _ => Primitive::Error(format!("invalid cast to int: {self}")), - } - } - - fn to_double(&self) -> Self { - match self { - Primitive::Ref(s) => { - let lock = - s.read().expect("TO_DOUBLE ERORR: could not acquire lock!"); - lock.to_double() - } - Primitive::Int(d) => Primitive::Double(*d as f64), - v @ Primitive::Double(_) => v.clone(), - Primitive::String(s) => match s.parse::() { - Ok(number) => Primitive::Double(number), - Err(e) => Primitive::Error(format!( - "invalid cast to double: {self}, {e}" - )), - }, - _ => Primitive::Error(format!("invalid cast to double: {self}")), - } - } -} -impl Or for Primitive { - fn or(&self, rhs: &Self) -> Self { - if let (&Primitive::Ref(l), &Primitive::Ref(r)) = (&self, &rhs) { - let l = l.read().expect("OR L ERROR: could not acquire lock!"); - let r = r.read().expect("OR R ERROR: could not acquire lock!"); - return l.or(&r); - } else if let &Primitive::Ref(l) = &self { - let l = l.read().expect("OR SELF ERROR: could not acquire lock!"); - return l.or(rhs); - } else if let &Primitive::Ref(r) = &rhs { - let r = r.read().expect("OR RHS ERROR: could not acquire lock!"); - return self.or(&r); - } - if let &Primitive::Bool(true) = &self { - return Primitive::Bool(true); - } - if !matches!((self, &rhs), (Primitive::Bool(_), Primitive::Bool(_))) { - return Primitive::Error(format!( - "illegal call to 'or' => left: {self} right: {rhs}" - )); - } - rhs.clone() - } -} -impl And for Primitive { - fn and(&self, rhs: &Self) -> Self { - if let (&Primitive::Ref(l), &Primitive::Ref(r)) = (&self, &rhs) { - let l = l.read().expect("AND L ERROR: could not acquire lock!"); - let r = r.read().expect("AND R ERROR: could not acquire lock!"); - return l.and(&r); - } else if let &Primitive::Ref(l) = &self { - let l = l.read().expect("AND SELF ERROR: could not acquire lock!"); - return l.and(rhs); - } else if let &Primitive::Ref(r) = &rhs { - let r = r.read().expect("AND RHS ERROR: could not acquire lock!"); - return self.and(&r); - } - if let &Primitive::Bool(false) = &self { - return Primitive::Bool(false); - } - - if !matches!((self, &rhs), (Primitive::Bool(_), Primitive::Bool(_))) { - return Primitive::Error(format!( - "illegal call to 'and' => left: {self} right: {rhs}" - )); - } - - rhs.clone() - } -} - -impl PartialOrd for Primitive { - fn partial_cmp(&self, other: &Self) -> Option { - match (self, other) { - (Primitive::Ref(l), Primitive::Ref(r)) => { - if Arc::ptr_eq(l, r) { - return Some(Ordering::Equal); - } - let l = l - .read() - .expect("PARTIAL_CMP L ERORR: could not acquire lock!"); - - let r = r - .read() - .expect("PARTIAL_CMP R ERORR: could not acquire lock!"); - l.partial_cmp(&r) - } - (Primitive::Ref(l), r) => { - let l = l - .read() - .expect("PARTIAL_CMP L ERORR: could not acquire lock!"); - - l.partial_cmp(r) - } - (l, Primitive::Ref(r)) => { - let r = r - .read() - .expect("PARTIAL_CMP R ERORR: could not acquire lock!"); - - l.partial_cmp(&r) - } - (Primitive::Int(l), Primitive::Int(r)) => l.partial_cmp(r), - (Primitive::Int(l), Primitive::Double(r)) => { - (*l as f64).partial_cmp(r) - } - (Primitive::Double(l), Primitive::Int(r)) => { - l.partial_cmp(&(*r as f64)) - } - (Primitive::Double(l), Primitive::Double(r)) => l.partial_cmp(r), - (Primitive::Bool(a), Primitive::Bool(b)) => a.partial_cmp(b), - (l @ Primitive::Bool(_), r) => l.partial_cmp(&(r.to_bool())), - - (Primitive::String(l), Primitive::String(r)) => l.partial_cmp(r), - (Primitive::Unit, Primitive::Unit) => Some(Ordering::Equal), - (Primitive::Array(l), Primitive::Array(r)) => l.partial_cmp(r), - ( - Primitive::Function { parameters: pl, exprs: el }, - Primitive::Function { parameters: pr, exprs: er }, - ) => { - if pl.eq(pr) - && el.iter().zip(er.iter()).filter(|&(a, b)| a != b).count() - == 0 - { - Some(Ordering::Equal) - } else { - None - } - } - (Primitive::Error(l), Primitive::Error(r)) => l.partial_cmp(r), - (Primitive::Null, Primitive::Null) => Some(Ordering::Equal), - (Primitive::EarlyReturn(l), Primitive::EarlyReturn(r)) => { - l.partial_cmp(r) - } - (Primitive::EarlyReturn(l), a) => l.as_ref().partial_cmp(a), - (l, Primitive::EarlyReturn(r)) => l.partial_cmp(r), - (Primitive::Struct(l), Primitive::Struct(r)) => { - if l.eq(r) { - Some(Ordering::Equal) - } else { - None - } - } - (Primitive::Struct(_), _) => None, - (Primitive::Int(_), _) => None, - (Primitive::Double(_), _) => None, - (Primitive::String(_), _) => None, - (Primitive::NoReturn, _) => None, - (Primitive::Null, _) => None, - (Primitive::Array(_), _) => None, - (Primitive::Error(_), _) => None, - (Primitive::Unit, _) => None, - (Primitive::Function { parameters: _, exprs: _ }, _) => None, - } - } -} - -impl TypeOf for Primitive { - fn type_of(&self) -> Self { - match self { - Primitive::Ref(l) => { - let l = - l.read().expect("TYPE_OF ERROR: could not acquire lock!"); - l.type_of() - } - Primitive::Int(_) => Primitive::String("int".to_string()), - Primitive::Bool(_) => Primitive::String("bool".to_string()), - Primitive::Null => Primitive::String("null".to_string()), - Primitive::Double(_) => Primitive::String("double".to_string()), - Primitive::String(_) => Primitive::String("string".to_string()), - Primitive::Array(_) => Primitive::String("array".to_string()), - Primitive::Error(_) => Primitive::String("error".to_string()), - Primitive::Function { parameters: _, exprs: _ } => { - Primitive::String("function".to_string()) - } - Primitive::Struct(_) => Primitive::String("struct".to_string()), - Primitive::Unit => Primitive::String("unit".to_string()), - Primitive::NoReturn => Primitive::String("!".to_string()), - Primitive::EarlyReturn(v) => v.type_of(), - } - } -} - -impl Array for Primitive { - fn index_at(&self, rhs: &Primitive) -> Primitive { - match (self, rhs) { - (Primitive::Ref(l), Primitive::Ref(r)) => { - let l = l - .read() - .expect("INDEX_AT L ERORR: could not acquire lock!"); - - let r = r - .read() - .expect("INDEX_AT R ERORR: could not acquire lock!"); - l.index_at(&r) - } - (Primitive::Ref(l), r) => { - let l = l - .read() - .expect("INDEX_AT L ERORR: could not acquire lock!"); - - l.index_at(r) - } - (l, Primitive::Ref(r)) => { - let r = r - .read() - .expect("INDEX_AT R ERORR: could not acquire lock!"); - - l.index_at(&r) - } - (Primitive::Array(arr), Primitive::Int(idx)) => { - let idx = *idx as usize; - if idx < arr.len() { - arr[idx].clone() - } else { - Primitive::Error("index out of range".to_string()) - } - } - (Primitive::String(s), Primitive::Int(idx)) => { - let idx = *idx as usize; - if idx < s.len() { - let s: String = s.chars().skip(idx).take(1).collect(); - Primitive::String(s) - } else { - Primitive::Error("index out of range".to_string()) - } - } - (Primitive::Struct(struc), Primitive::String(key)) => { - if let Some(p) = struc.get(key) { - p.clone() - } else { - Primitive::Null - } - } - _ => Primitive::Error("illegal access to array!!!".to_string()), - } - } - - fn len(&self) -> Primitive { - match self { - Primitive::Ref(l) => { - let l = l.read().expect("LEN ERROR: could not acquire lock!"); - l.len() - } - Primitive::String(s) => Primitive::Int(s.len() as i128), - Primitive::Array(a) => Primitive::Int(a.len() as i128), - Primitive::Struct(s) => Primitive::Int(s.len() as i128), - _ => Primitive::Error(format!( - "call to len() on a non array value => {self}" - )), - } - } - - fn swap_mem( - &mut self, - rhs: &mut Primitive, - index: &Primitive, - ) -> Primitive { - match (self, index) { - // FIXME this might be more complex than that - // RHS could be equal to self - // using Arc::ptr_eq(&arc1, &arc2) might be safer - (Primitive::Ref(l), Primitive::Ref(r)) => { - let mut l = l - .write() - .expect("SWAP_MEM L ERORR: could not acquire lock!"); - - let r = r - .read() - .expect("SWAP_MEM R ERORR: could not acquire lock!"); - l.swap_mem(rhs, &r) - } - (Primitive::Ref(l), _) => { - let mut l = l - .write() - .expect("SWAP_MEM L ERORR: could not acquire lock!"); - - l.swap_mem(rhs, index) - } - (l, Primitive::Ref(index)) => { - let index = index - .read() - .expect("SWAP_MEM R ERORR: could not acquire lock!"); - - l.swap_mem(rhs, &index) - } - (Primitive::Array(arr), Primitive::Int(idx)) => { - let idx = *idx as usize; - if !matches!(rhs, Primitive::Error(_) | Primitive::Unit) - && idx < arr.len() - { - std::mem::swap(&mut arr[idx], rhs); - arr[idx].clone() - } else { - Primitive::Error("index out of range".to_string()) - } - } - (Primitive::Struct(s), Primitive::String(k)) => { - if s.contains_key(k) { - std::mem::swap(s.get_mut(k).unwrap(), rhs); - } else { - s.insert(k.clone(), rhs.clone()); - } - s[k].clone() - } - (Primitive::String(s), Primitive::Int(idx)) => { - let idx = *idx as usize; - if !matches!(rhs, Primitive::Error(_) | Primitive::Unit) - && idx < s.len() - { - s.remove(idx); - s.insert_str(idx, &rhs.to_string()); - rhs.clone() - } else { - Primitive::Error("index out of range".to_string()) - } - } - _ => Primitive::Error("invalid call to swap_mem()".to_string()), - } - } - - fn remove(&mut self, key: &Primitive) -> anyhow::Result<()> { - match (self, key) { - // FIXME this might be more complex than that - // RHS could be equal to self - // using Arc::ptr_eq(&arc1, &arc2) might be safer - (Primitive::Ref(l), Primitive::Ref(r)) => { - let mut l = - l.write().expect("REMOVE L ERORR: could not acquire lock!"); - - let r = - r.read().expect("REMOVE R ERORR: could not acquire lock!"); - l.remove(&r) - } - (Primitive::Ref(l), _) => { - let mut l = - l.write().expect("REMOVE L ERORR: could not acquire lock!"); - - l.remove(key) - } - (l, Primitive::Ref(index)) => { - let index = index - .read() - .expect("REMOVE R ERORR: could not acquire lock!"); - - l.remove(&index) - } - (Primitive::Array(arr), Primitive::Int(idx)) => { - let idx = *idx as usize; - if idx < arr.len() { - arr.remove(idx); - Ok(()) - } else { - Err(anyhow::Error::msg("index out of range")) - } - } - (Primitive::String(s), Primitive::Int(idx)) => { - let idx = *idx as usize; - if idx < s.len() { - s.remove(idx); - Ok(()) - } else { - Err(anyhow::Error::msg("index out of range")) - } - } - (Primitive::Struct(struc), Primitive::String(key)) => { - if let Some(_p) = struc.remove(key) { - Ok(()) - } else { - Err(anyhow::Error::msg("key doesn't exist")) - } - } - _ => Err(anyhow::Error::msg("illegal access to array!!!")), - } - } -} -impl PartialEq for Primitive { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (Self::Ref(l0), Self::Ref(r0)) => { - if Arc::ptr_eq(l0, r0) { - return true; - } - - let l0 = - l0.read().expect("EQ L ERORR: could not acquire lock!"); - - let r = r0.read().expect("EQ R ERORR: could not acquire lock!"); - l0.eq(&r) - } - (Primitive::Ref(l), _) => { - let l = l.read().expect("EQ L ERORR: could not acquire lock!"); - l.eq(other) - } - (_, Primitive::Ref(r)) => { - let r = r.read().expect("EQ R ERORR: could not acquire lock!"); - self.eq(&r) - } - (Self::Int(l0), Self::Int(r0)) => l0 == r0, - (Self::Bool(l0), Self::Bool(r0)) => l0 == r0, - (Self::Double(l0), Self::Double(r0)) => l0 == r0, - (Self::String(l0), Self::String(r0)) => l0 == r0, - (Self::Array(l0), Self::Array(r0)) => l0 == r0, - (Self::Struct(l0), Self::Struct(r0)) => l0 == r0, - (Self::Error(l0), Self::Error(r0)) => l0 == r0, - ( - Self::Function { parameters: l_parameters, exprs: l_exprs }, - Self::Function { parameters: r_parameters, exprs: r_exprs }, - ) => l_parameters == r_parameters && l_exprs == r_exprs, - (Self::EarlyReturn(l0), Self::EarlyReturn(r0)) => l0 == r0, - _ => { - core::mem::discriminant(self) == core::mem::discriminant(other) - } - } - } -} -// endregion - -#[cfg(test)] -mod test { - use crate::adana_script::primitive::Add; - - use super::Primitive; - - #[test] - fn test_add_valid() { - let l = Primitive::Int(1); - let r = Primitive::Int(2); - assert_eq!(l.add(&r), Primitive::Int(3)); - - let l = Primitive::Int(1); - let r = Primitive::Double(2.); - assert_eq!(l.add(&r), Primitive::Double(3.)); - - let l = Primitive::Double(1.); - let r = Primitive::Int(2); - assert_eq!(l.add(&r), Primitive::Double(3.)); - - let l = Primitive::Double(1.); - let r = Primitive::Double(2.); - assert_eq!(l.add(&r), Primitive::Double(3.)); - } -} diff --git a/src/adana_script/tests/builtin.rs b/src/adana_script/tests/builtin.rs index a0e9905..b14d81a 100644 --- a/src/adana_script/tests/builtin.rs +++ b/src/adana_script/tests/builtin.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; -use crate::adana_script::{compute, Primitive}; - +use crate::adana_script::compute; +use adana_script_core::primitive::Primitive; #[test] fn test_builtin_to_int() { let mut ctx = BTreeMap::new(); diff --git a/src/adana_script/tests/examples.rs b/src/adana_script/tests/examples.rs index f1e12cf..6899234 100644 --- a/src/adana_script/tests/examples.rs +++ b/src/adana_script/tests/examples.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; -use crate::adana_script::{compute, Primitive::*}; - +use crate::adana_script::compute; +use adana_script_core::primitive::Primitive::*; #[test] fn test_example1() { let mut ctx = BTreeMap::new(); diff --git a/src/adana_script/tests/foreach.rs b/src/adana_script/tests/foreach.rs index 3b39912..5200fc2 100644 --- a/src/adana_script/tests/foreach.rs +++ b/src/adana_script/tests/foreach.rs @@ -1,7 +1,8 @@ use std::collections::BTreeMap; -use crate::adana_script::{compute, Primitive}; +use crate::adana_script::compute; +use adana_script_core::primitive::Primitive; #[test] fn simple_foreach() { let expr = r#" diff --git a/src/adana_script/tests/funct.rs b/src/adana_script/tests/funct.rs index faea3e0..3146d63 100644 --- a/src/adana_script/tests/funct.rs +++ b/src/adana_script/tests/funct.rs @@ -1,7 +1,8 @@ use std::collections::BTreeMap; -use crate::adana_script::{compute, Operator, Primitive, Value}; +use crate::adana_script::compute; +use adana_script_core::{primitive::Primitive, Operator, Value}; #[test] fn test_anon_func_call() { let mut ctx = BTreeMap::new(); diff --git a/src/adana_script/tests/misc.rs b/src/adana_script/tests/misc.rs index fbde549..65a8f2f 100644 --- a/src/adana_script/tests/misc.rs +++ b/src/adana_script/tests/misc.rs @@ -1,11 +1,9 @@ use std::collections::BTreeMap; -use crate::adana_script::{ - parser::parse_instructions as parse_var_expr, Operator::*, Value, -}; - -use crate::adana_script::{compute, Primitive}; +use crate::adana_script::parser::parse_instructions as parse_var_expr; +use crate::adana_script::compute; +use adana_script_core::{primitive::Primitive, Operator::*, Value}; #[test] #[should_panic(expected = "invalid expression!")] fn test_expr_invalid() { diff --git a/src/adana_script/tests/range.rs b/src/adana_script/tests/range.rs index 746f1fc..c9323c9 100644 --- a/src/adana_script/tests/range.rs +++ b/src/adana_script/tests/range.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; -use crate::adana_script::{compute, Primitive}; - +use crate::adana_script::compute; +use adana_script_core::primitive::Primitive; #[test] fn simple_foreach_range() { let expr = r#" diff --git a/src/adana_script/tests/strings.rs b/src/adana_script/tests/strings.rs index 468e105..30c79b1 100644 --- a/src/adana_script/tests/strings.rs +++ b/src/adana_script/tests/strings.rs @@ -1,7 +1,8 @@ use std::collections::BTreeMap; -use crate::adana_script::{compute, Primitive}; +use crate::adana_script::compute; +use adana_script_core::primitive::Primitive; #[test] fn test_string_block2() { let expr = r#" diff --git a/src/adana_script/tests/struc.rs b/src/adana_script/tests/struc.rs index 6d01403..a689411 100644 --- a/src/adana_script/tests/struc.rs +++ b/src/adana_script/tests/struc.rs @@ -2,8 +2,9 @@ use std::collections::BTreeMap; use serial_test::serial; -use crate::adana_script::{compute, Primitive, Value}; +use crate::adana_script::compute; +use adana_script_core::{primitive::Primitive, Value}; #[test] #[serial] fn test_simple_struc() { @@ -40,15 +41,15 @@ fn test_simple_struc_with_more_stuff_in_it() { "z".to_string(), Primitive::Function { parameters: vec![], - exprs: vec![Value::BlockParen( - vec![Value::BuiltInFunction { - fn_type: - crate::adana_script::BuiltInFunctionType::Println, - expr: Box::new(Value::BlockParen(vec![Value::String( - "hello".to_string() - )])) - }] - )] + exprs: vec![Value::BlockParen(vec![ + Value::BuiltInFunction { + fn_type: + adana_script_core::BuiltInFunctionType::Println, + expr: Box::new(Value::BlockParen(vec![ + Value::String("hello".to_string()) + ])) + } + ])] } ) ])) diff --git a/src/adana_script/tests/test_array.rs b/src/adana_script/tests/test_array.rs index 93832ae..69a3164 100644 --- a/src/adana_script/tests/test_array.rs +++ b/src/adana_script/tests/test_array.rs @@ -2,15 +2,11 @@ use std::collections::BTreeMap; use serial_test::serial; -use crate::adana_script::{ - compute, - primitive::{ - Array as Arr, - Primitive::{Array, Bool, Double, Int, String as Str}, - }, - Primitive, +use crate::adana_script::compute; +use adana_script_core::primitive::{ + Array as Arr, + Primitive::{self, Array, Bool, Double, Int, String as Str}, }; - #[test] #[serial] fn test_simple_array() { diff --git a/src/adana_script/tests/test_chaining.rs b/src/adana_script/tests/test_chaining.rs index 32a3088..0540bce 100644 --- a/src/adana_script/tests/test_chaining.rs +++ b/src/adana_script/tests/test_chaining.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; -use crate::adana_script::{compute, Primitive}; - +use crate::adana_script::compute; +use adana_script_core::primitive::Primitive; #[test] fn complex_struct_array() { let expr = r#" diff --git a/src/adana_script/tests/test_drop.rs b/src/adana_script/tests/test_drop.rs index 8675be7..1f4d6d3 100644 --- a/src/adana_script/tests/test_drop.rs +++ b/src/adana_script/tests/test_drop.rs @@ -1,6 +1,8 @@ use std::collections::BTreeMap; -use crate::adana_script::{compute, BuiltInFunctionType, Primitive, Value}; +use adana_script_core::{primitive::Primitive, BuiltInFunctionType, Value}; + +use crate::adana_script::compute; #[test] fn test_drop_arr_access() { diff --git a/src/adana_script/tests/test_parser.rs b/src/adana_script/tests/test_parser.rs index c764945..9e9da8c 100644 --- a/src/adana_script/tests/test_parser.rs +++ b/src/adana_script/tests/test_parser.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; -use crate::adana_script::{ - parser::parse_instructions, +use crate::adana_script::parser::parse_instructions; +use adana_script_core::{ BuiltInFunctionType, Operator, Value::{ self, BlockParen, Expression, Function, Integer, Operation, Variable, diff --git a/src/adana_script/tests/test_reference.rs b/src/adana_script/tests/test_reference.rs index 345afbb..14ae168 100644 --- a/src/adana_script/tests/test_reference.rs +++ b/src/adana_script/tests/test_reference.rs @@ -1,6 +1,8 @@ use std::collections::BTreeMap; -use crate::adana_script::{compute, Primitive}; +use adana_script_core::primitive::Primitive; + +use crate::adana_script::compute; #[test] fn test_simple() { diff --git a/src/adana_script/tests/test_scope_ctx.rs b/src/adana_script/tests/test_scope_ctx.rs index 49cba53..e47e8c9 100644 --- a/src/adana_script/tests/test_scope_ctx.rs +++ b/src/adana_script/tests/test_scope_ctx.rs @@ -1,6 +1,8 @@ use std::collections::BTreeMap; -use crate::adana_script::{compute, Primitive}; +use adana_script_core::primitive::Primitive; + +use crate::adana_script::compute; #[test] fn test_if_scope_simple() { diff --git a/src/adana_script/tests/tests_file.rs b/src/adana_script/tests/tests_file.rs index a36dcbf..0cb3cde 100644 --- a/src/adana_script/tests/tests_file.rs +++ b/src/adana_script/tests/tests_file.rs @@ -1,8 +1,9 @@ use std::collections::BTreeMap; +use adana_script_core::primitive::Primitive; use serial_test::serial; -use crate::adana_script::{compute, Primitive}; +use crate::adana_script::compute; #[test] #[serial] diff --git a/src/adana_script/tests/unused.rs b/src/adana_script/tests/unused.rs index 2c8217b..f3172f7 100644 --- a/src/adana_script/tests/unused.rs +++ b/src/adana_script/tests/unused.rs @@ -1,6 +1,8 @@ use std::collections::BTreeMap; -use crate::adana_script::{compute, Primitive}; +use adana_script_core::primitive::Primitive; + +use crate::adana_script::compute; #[test] fn test_simple_unused_array() { diff --git a/src/cache_command/process.rs b/src/cache_command/process.rs index 1725037..48e25dd 100644 --- a/src/cache_command/process.rs +++ b/src/cache_command/process.rs @@ -1,11 +1,12 @@ use std::{collections::BTreeMap, path::PathBuf}; +use adana_script_core::primitive::RefPrimitive; use anyhow::Context; use nom::error::ErrorKind; use regex::Regex; use crate::{ - adana_script::{print_ast, RefPrimitive}, + adana_script::print_ast, db::{DbOp, SCRIPT_CACHE_KEY}, prelude::colors::*, reserved_keywords::{check_reserved_keyword, CACHE_COMMAND_DOC}, diff --git a/src/editor.rs b/src/editor.rs index 64914c0..65a823c 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -12,7 +12,7 @@ use rustyline_derive::*; use std::path::{Path, PathBuf, MAIN_SEPARATOR}; use std::process::Command; -use crate::adana_script::constants::PI; +use adana_script_core::constants::PI; fn get_default_history_path() -> Option> { let mut home_dir = dirs::home_dir()?; diff --git a/src/main.rs b/src/main.rs index f058818..37b5c2f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,7 @@ mod editor; mod prelude; mod reserved_keywords; -use adana_script::Primitive; +use adana_script_core::primitive::Primitive; use args::*; use db::DbOp; use log::debug; diff --git a/src/reserved_keywords.rs b/src/reserved_keywords.rs index 0d5aab0..9535f88 100644 --- a/src/reserved_keywords.rs +++ b/src/reserved_keywords.rs @@ -1,8 +1,6 @@ -use crate::{ - adana_script::{constants::*, Operator}, - cache_command::CacheCommand, -}; +use crate::cache_command::CacheCommand; +use adana_script_core::{constants::*, Operator}; pub const CACHE_COMMAND_DOC: &[(&[&str], &str)] = CacheCommand::doc(); pub const FORBIDDEN_VARIABLE_NAME: &[&str] = &[