diff --git a/lykiadb-server/src/engine/interpreter.rs b/lykiadb-server/src/engine/interpreter.rs index 7869d8fe..65dc94a2 100644 --- a/lykiadb-server/src/engine/interpreter.rs +++ b/lykiadb-server/src/engine/interpreter.rs @@ -17,7 +17,7 @@ use crate::plan::planner::Planner; use crate::util::{alloc_shared, Shared}; use crate::value::callable::{Callable, CallableKind, Function, Stateful}; use crate::value::environment::{EnvId, Environment}; -use crate::value::{RV, types::eval_binary}; +use crate::value::{RV, eval::eval_binary}; use std::sync::Arc; use std::vec; diff --git a/lykiadb-server/src/value/types.rs b/lykiadb-server/src/value/eval.rs similarity index 89% rename from lykiadb-server/src/value/types.rs rename to lykiadb-server/src/value/eval.rs index 524bc4c1..50d62212 100644 --- a/lykiadb-server/src/value/types.rs +++ b/lykiadb-server/src/value/eval.rs @@ -1,143 +1,8 @@ use lykiadb_lang::ast::expr::Operation; -use rustc_hash::FxHashMap; -use serde::ser::{SerializeMap, SerializeSeq}; -use serde::{Deserialize, Serialize}; use std::ops; -use std::sync::{Arc, RwLock}; -use crate::util::alloc_shared; +use std::sync::Arc; use super::RV; -impl Serialize for RV { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - match self { - RV::Str(s) => serializer.serialize_str(s), - RV::Num(n) => serializer.serialize_f64(*n), - RV::Bool(b) => serializer.serialize_bool(*b), - RV::Undefined => serializer.serialize_none(), - RV::NaN => serializer.serialize_none(), - RV::Null => serializer.serialize_none(), - RV::Array(arr) => { - let mut seq = serializer.serialize_seq(None).unwrap(); - let arr = (arr as &RwLock>).read().unwrap(); - for item in arr.iter() { - seq.serialize_element(&item)?; - } - seq.end() - } - RV::Object(obj) => { - let mut map = serializer.serialize_map(None).unwrap(); - let arr = (obj as &RwLock>) - .read() - .unwrap(); - for (key, value) in arr.iter() { - map.serialize_entry(key, value)?; - } - map.end() - }, - _ => serializer.serialize_none(), - } - } -} - -impl<'de> Deserialize<'de> for RV { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let value = serde_json::Value::deserialize(deserializer)?; - match value { - serde_json::Value::String(s) => Ok(RV::Str(Arc::new(s))), - serde_json::Value::Number(n) => Ok(RV::Num(n.as_f64().unwrap())), - serde_json::Value::Bool(b) => Ok(RV::Bool(b)), - serde_json::Value::Array(arr) => { - let mut vec = Vec::new(); - for item in arr { - vec.push(serde_json::from_value(item).unwrap()); - } - Ok(RV::Array(alloc_shared(vec))) - } - serde_json::Value::Object(obj) => { - let mut map = FxHashMap::default(); - for (key, value) in obj { - map.insert(key, serde_json::from_value(value).unwrap()); - } - Ok(RV::Object(alloc_shared(map))) - } - serde_json::Value::Null => Ok(RV::Null), - } - } -} - -impl RV { - pub fn as_bool(&self) -> bool { - match &self { - RV::Num(value) => !value.is_nan() && value.abs() > 0.0, - RV::Str(value) => !value.is_empty(), - RV::Bool(value) => *value, - RV::Null | RV::Undefined | RV::NaN => false, - _ => true, - } - } - - pub fn as_number(&self) -> Option { - match self { - RV::Num(value) => Some(*value), - RV::Bool(true) => Some(1.0), - RV::Bool(false) => Some(0.0), - RV::Str(s) => { - if let Ok(num) = s.parse::() { - Some(num) - } else { - None - } - } - _ => None, - } - } - - pub fn eq_any_bool(&self, b: bool) -> bool { - self.as_bool() == b - } - - pub fn eq_str_num(&self, n: f64) -> bool { - if let RV::Str(s) = self { - if let Ok(num) = s.parse::() { - return num == n; - } - } - false - } - - pub fn partial_cmp_str_bool(&self, other: bool) -> Option { - if let Some(num) = self.as_number() { - return num.partial_cmp(&if other { 1.0 } else { 0.0 }); - } - self.as_bool().partial_cmp(&other) - } - - pub fn is_in(&self, other: &RV) -> RV { - match (self, other) { - (RV::Str(lhs), RV::Str(rhs)) => { - RV::Bool(rhs.contains(lhs.as_str())) - } - (lhs, RV::Array(rhs)) => { - RV::Bool(rhs.read().unwrap().contains(&lhs)) - } - (RV::Str(key), RV::Object(map)) => { - RV::Bool(map.read().unwrap().contains_key(key.as_str())) - }, - _ => RV::Bool(false), - } - } - - pub fn not(&self) -> RV { - RV::Bool(!self.as_bool()) - } -} - impl PartialEq for RV { fn eq(&self, other: &Self) -> bool { match (self, other) { @@ -334,7 +199,7 @@ mod test { use crate::{ util::alloc_shared, - value::types::{eval_binary, RV}, + value::eval::{eval_binary, RV}, }; #[test] diff --git a/lykiadb-server/src/value/mod.rs b/lykiadb-server/src/value/mod.rs index eb7d8a89..7db8aae5 100644 --- a/lykiadb-server/src/value/mod.rs +++ b/lykiadb-server/src/value/mod.rs @@ -1,13 +1,16 @@ -use std::sync::Arc; - -use callable::Callable; +use std::sync::{Arc, RwLock}; +use serde::ser::{SerializeMap, SerializeSeq}; +use serde::{Deserialize, Serialize}; use rustc_hash::FxHashMap; +use crate::util::alloc_shared; use crate::util::Shared; +use callable::Callable; pub mod environment; -pub mod types; +pub mod eval; pub mod callable; + #[derive(Debug, Clone)] pub enum RV { Str(Arc), @@ -19,4 +22,137 @@ pub enum RV { Undefined, NaN, Null, -} \ No newline at end of file +} + +impl RV { + pub fn as_bool(&self) -> bool { + match &self { + RV::Num(value) => !value.is_nan() && value.abs() > 0.0, + RV::Str(value) => !value.is_empty(), + RV::Bool(value) => *value, + RV::Null | RV::Undefined | RV::NaN => false, + _ => true, + } + } + + pub fn as_number(&self) -> Option { + match self { + RV::Num(value) => Some(*value), + RV::Bool(true) => Some(1.0), + RV::Bool(false) => Some(0.0), + RV::Str(s) => { + if let Ok(num) = s.parse::() { + Some(num) + } else { + None + } + } + _ => None, + } + } + + pub fn eq_any_bool(&self, b: bool) -> bool { + self.as_bool() == b + } + + pub fn eq_str_num(&self, n: f64) -> bool { + if let RV::Str(s) = self { + if let Ok(num) = s.parse::() { + return num == n; + } + } + false + } + + pub fn partial_cmp_str_bool(&self, other: bool) -> Option { + if let Some(num) = self.as_number() { + return num.partial_cmp(&if other { 1.0 } else { 0.0 }); + } + self.as_bool().partial_cmp(&other) + } + + pub fn is_in(&self, other: &RV) -> RV { + match (self, other) { + (RV::Str(lhs), RV::Str(rhs)) => { + RV::Bool(rhs.contains(lhs.as_str())) + } + (lhs, RV::Array(rhs)) => { + RV::Bool(rhs.read().unwrap().contains(&lhs)) + } + (RV::Str(key), RV::Object(map)) => { + RV::Bool(map.read().unwrap().contains_key(key.as_str())) + }, + _ => RV::Bool(false), + } + } + + pub fn not(&self) -> RV { + RV::Bool(!self.as_bool()) + } +} + + +impl Serialize for RV { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + match self { + RV::Str(s) => serializer.serialize_str(s), + RV::Num(n) => serializer.serialize_f64(*n), + RV::Bool(b) => serializer.serialize_bool(*b), + RV::Undefined => serializer.serialize_none(), + RV::NaN => serializer.serialize_none(), + RV::Null => serializer.serialize_none(), + RV::Array(arr) => { + let mut seq = serializer.serialize_seq(None).unwrap(); + let arr = (arr as &RwLock>).read().unwrap(); + for item in arr.iter() { + seq.serialize_element(&item)?; + } + seq.end() + } + RV::Object(obj) => { + let mut map = serializer.serialize_map(None).unwrap(); + let arr = (obj as &RwLock>) + .read() + .unwrap(); + for (key, value) in arr.iter() { + map.serialize_entry(key, value)?; + } + map.end() + }, + _ => serializer.serialize_none(), + } + } +} + +impl<'de> Deserialize<'de> for RV { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let value = serde_json::Value::deserialize(deserializer)?; + match value { + serde_json::Value::String(s) => Ok(RV::Str(Arc::new(s))), + serde_json::Value::Number(n) => Ok(RV::Num(n.as_f64().unwrap())), + serde_json::Value::Bool(b) => Ok(RV::Bool(b)), + serde_json::Value::Array(arr) => { + let mut vec = Vec::new(); + for item in arr { + vec.push(serde_json::from_value(item).unwrap()); + } + Ok(RV::Array(alloc_shared(vec))) + } + serde_json::Value::Object(obj) => { + let mut map = FxHashMap::default(); + for (key, value) in obj { + map.insert(key, serde_json::from_value(value).unwrap()); + } + Ok(RV::Object(alloc_shared(map))) + } + serde_json::Value::Null => Ok(RV::Null), + } + } +} +