From f1f363002c2735e1fcf149f51a3623e0247d1261 Mon Sep 17 00:00:00 2001 From: dgkf <18220321+dgkf@users.noreply.github.com> Date: Thu, 12 Oct 2023 11:46:23 -0400 Subject: [PATCH 1/4] another attempt at surfacing release binaries --- .github/workflows/release.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a88e48a0..15626028 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -126,21 +126,21 @@ jobs: uses: actions/checkout@v4 - uses: actions/download-artifact@v3 + path: dist - - name: Check Artifacts - shell: bash - run: | - ls . + - name: Display structure of downloaded files + working-directory: dist + run: ls -R - name: Upload binaries to release uses: softprops/action-gh-release@v1 if: env.preview == 'false' with: - files: r-* + files: dist/* - name: Upload binaries as artifact uses: actions/upload-artifact@v3 if: env.preview == 'true' with: name: release - path: r-* + path: dist/* From 437caf8220882d20b62f150b8458505f7c32d35b Mon Sep 17 00:00:00 2001 From: dgkf <18220321+dgkf@users.noreply.github.com> Date: Thu, 12 Oct 2023 11:47:38 -0400 Subject: [PATCH 2/4] another attempt at surfacing release binaries --- .github/workflows/release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 15626028..773d7f50 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -126,7 +126,8 @@ jobs: uses: actions/checkout@v4 - uses: actions/download-artifact@v3 - path: dist + with: + path: dist - name: Display structure of downloaded files working-directory: dist From 5aa2ccf3be06204a1e482ba88eefcbcff2115378 Mon Sep 17 00:00:00 2001 From: dgkf <18220321+dgkf@users.noreply.github.com> Date: Thu, 12 Oct 2023 11:56:18 -0400 Subject: [PATCH 3/4] another attempt at surfacing release binaries --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 773d7f50..cf82f38a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -110,7 +110,7 @@ jobs: run: | mkdir -p dist ls ./target/${{ matrix.target }}/release/r* - cp ./target/${{ matrix.target }}/release/r dist/ + cp ./target/${{ matrix.target }}/release/r dist/r-${{ matrix.build }} - uses: actions/upload-artifact@v3 with: @@ -137,7 +137,7 @@ jobs: uses: softprops/action-gh-release@v1 if: env.preview == 'false' with: - files: dist/* + files: dist/**/* - name: Upload binaries as artifact uses: actions/upload-artifact@v3 From 2c0fba94d417a34945cd1914c06c696a8346b6c6 Mon Sep 17 00:00:00 2001 From: dgkf <18220321+dgkf@users.noreply.github.com> Date: Tue, 21 May 2024 16:57:15 -0400 Subject: [PATCH 4/4] wip: adding scalars --- r_derive/src/lib.rs | 2 +- src/callable/operators.rs | 21 +- src/callable/primitive/c.rs | 31 +- src/callable/primitive/names.rs | 1 + src/grammar/grammar.pest | 4 +- src/lang.rs | 105 +++- src/object/core.rs | 1 + src/object/mod.rs | 9 +- src/object/scalar.rs | 761 +++++++++++++++++++++++++++ src/object/vector/coercion.rs | 2 +- src/object/vector/core.rs | 85 ++- src/object/vector/rep.rs | 52 +- src/object/vector/subset.rs | 35 +- src/object/vector/types.rs | 33 +- src/parser/core.rs | 8 +- src/parser/localization/languages.rs | 1 - 16 files changed, 1058 insertions(+), 93 deletions(-) create mode 100644 src/object/scalar.rs diff --git a/r_derive/src/lib.rs b/r_derive/src/lib.rs index 9443b747..06b404bd 100644 --- a/r_derive/src/lib.rs +++ b/r_derive/src/lib.rs @@ -190,7 +190,7 @@ pub fn derive_translate(_input: TokenStream) -> TokenStream { Rule::negate => en::Rule::negate, Rule::postfix => en::Rule::postfix, Rule::call => en::Rule::call, - Rule::index => en::Rule::index, + // Rule::index => en::Rule::index, Rule::vector_index => en::Rule::vector_index, Rule::block => en::Rule::block, Rule::block_exprs => en::Rule::block_exprs, diff --git a/src/callable/operators.rs b/src/callable/operators.rs index 500481a7..f9c53776 100644 --- a/src/callable/operators.rs +++ b/src/callable/operators.rs @@ -1,3 +1,5 @@ +use std::ops::BitAnd; + use r_derive::*; use super::core::*; @@ -5,7 +7,7 @@ use crate::context::Context; use crate::error::Error; use crate::lang::{CallStack, EvalResult}; use crate::object::types::*; -use crate::object::*; +use crate::{internal_err, object::*}; #[derive(Debug, Clone, PartialEq)] #[builtin(sym = "<-", kind = Infix)] @@ -103,9 +105,14 @@ impl Callable for InfixOr { fn call(&self, args: ExprList, stack: &mut CallStack) -> EvalResult { let (lhs, rhs) = stack.eval_binary(args.unnamed_binary_args())?; let res = match (lhs, rhs) { + (Obj::Scalar(l), Obj::Scalar(r)) => (l.try_into()? && r.try_into()?).into(), (Obj::Vector(l), Obj::Vector(r)) => { - let Ok(lhs) = l.try_into() else { todo!() }; - let Ok(rhs) = r.try_into() else { todo!() }; + let Ok(lhs) = l.try_into() else { + return internal_err!(); + }; + let Ok(rhs) = r.try_into() else { + return internal_err!(); + }; Obj::Vector(Vector::from(vec![OptionNA::Some(lhs || rhs)])) } _ => Obj::Null, @@ -123,8 +130,12 @@ impl Callable for InfixAnd { let (lhs, rhs) = stack.eval_binary(args.unnamed_binary_args())?; let res = match (lhs, rhs) { (Obj::Vector(l), Obj::Vector(r)) => { - let Ok(lhs) = l.try_into() else { todo!() }; - let Ok(rhs) = r.try_into() else { todo!() }; + let Ok(lhs) = l.try_into() else { + return internal_err!(); + }; + let Ok(rhs) = r.try_into() else { + return internal_err!(); + }; Obj::Vector(Vector::from(vec![OptionNA::Some(lhs && rhs)])) } _ => Obj::Null, diff --git a/src/callable/primitive/c.rs b/src/callable/primitive/c.rs index 155e3968..3ac2861b 100644 --- a/src/callable/primitive/c.rs +++ b/src/callable/primitive/c.rs @@ -13,6 +13,7 @@ impl Callable for PrimitiveC { fn call(&self, args: ExprList, stack: &mut CallStack) -> EvalResult { // this can be cleaned up quite a bit, but I just need it working with // more types for now to test vectorized operators using different types + use Scalar::*; let Obj::List(vals) = stack.eval_list_eager(args)? else { unreachable!() @@ -25,7 +26,7 @@ impl Callable for PrimitiveC { .iter() .map(|(_, v)| match v { Obj::Null => 0, - Obj::Vector(_) => 1, + Obj::Scalar(_) | Obj::Vector(_) => 1, Obj::List(_) => 2, _ => 0, }) @@ -47,10 +48,18 @@ impl Callable for PrimitiveC { .borrow() .iter() .map(|(_, r)| match r { - Obj::Vector(Vector::Logical(_)) => Vector::from(Vec::::new()), - Obj::Vector(Vector::Integer(_)) => Vector::from(Vec::::new()), - Obj::Vector(Vector::Double(_)) => Vector::from(Vec::::new()), - Obj::Vector(Vector::Character(_)) => Vector::from(Vec::::new()), + Obj::Scalar(Bool(_)) | Obj::Vector(Vector::Logical(_)) => { + Vector::from(Vec::::new()) + } + Obj::Scalar(I32(_)) | Obj::Vector(Vector::Integer(_)) => { + Vector::from(Vec::::new()) + } + Obj::Scalar(F64(_)) | Obj::Vector(Vector::Double(_)) => { + Vector::from(Vec::::new()) + } + Obj::Scalar(String(_)) | Obj::Vector(Vector::Character(_)) => { + Vector::from(Vec::::new()) + } _ => unreachable!(), }) .fold(Vector::from(Vec::::new()), |l, r| match (l, r) { @@ -77,6 +86,9 @@ impl Callable for PrimitiveC { .clone() .into_iter() .flat_map(|(_, i)| match i.as_character() { + Ok(Obj::Scalar(String(ScalarType(x)))) => { + vec![OptionNA::Some(x)].into_iter() + } Ok(Obj::Vector(Vector::Character(v))) => { v.inner().clone().borrow().clone().into_iter() } @@ -97,6 +109,9 @@ impl Callable for PrimitiveC { .clone() .into_iter() .flat_map(|(_, i)| match i.as_double() { + Ok(Obj::Scalar(F64(ScalarType(x)))) => { + vec![OptionNA::Some(x)].into_iter() + } Ok(Obj::Vector(Vector::Double(v))) => { v.inner().clone().borrow().clone().into_iter() } @@ -117,6 +132,9 @@ impl Callable for PrimitiveC { .clone() .into_iter() .flat_map(|(_, i)| match i.as_integer() { + Ok(Obj::Scalar(I32(ScalarType(x)))) => { + vec![OptionNA::Some(x)].into_iter() + } Ok(Obj::Vector(Vector::Integer(v))) => { v.inner().clone().borrow().clone().into_iter() } @@ -137,6 +155,9 @@ impl Callable for PrimitiveC { .clone() .into_iter() .flat_map(|(_, i)| match i.as_logical() { + Ok(Obj::Scalar(Bool(ScalarType(x)))) => { + vec![OptionNA::Some(x)].into_iter() + } Ok(Obj::Vector(Vector::Logical(v))) => { v.inner().clone().borrow().clone().into_iter() } diff --git a/src/callable/primitive/names.rs b/src/callable/primitive/names.rs index 17763d57..10ba0a27 100644 --- a/src/callable/primitive/names.rs +++ b/src/callable/primitive/names.rs @@ -19,6 +19,7 @@ impl Callable for PrimitiveNames { match x { Null => Ok(Null), Promise(..) => Ok(Null), + Scalar(..) => Ok(Null), Vector(..) => Ok(Null), // named vectors currently not supported... Expr(..) => Ok(Null), // handle arg lists? Function(..) => Ok(Null), // return formals? diff --git a/src/grammar/grammar.pest b/src/grammar/grammar.pest index edaf5aa9..ec48ef09 100644 --- a/src/grammar/grammar.pest +++ b/src/grammar/grammar.pest @@ -110,10 +110,10 @@ prefix = _{ subtract | negate | more } negate = { "!" } - postfix = _{ call | index | vector_index | more } + postfix = _{ call | vector_index | more } // | index } call = { "(" ~ pairs ~ ")" } - index = { "[[" ~ pairs ~ "]]" } vector_index = { "[" ~ pairs ~ "]" } + // index = { "[[" ~ pairs ~ "]]" } standalone = _{ more } diff --git a/src/lang.rs b/src/lang.rs index 6ffcefc2..a787bcb4 100644 --- a/src/lang.rs +++ b/src/lang.rs @@ -94,6 +94,7 @@ impl Obj { pub fn as_list(&self) -> EvalResult { match self { Obj::Null => Ok(Obj::List(List::from(vec![]))), + Obj::Scalar(_s) => internal_err!(), Obj::Vector(_v) => internal_err!(), Obj::List(l) => Ok(Obj::List(l.clone())), Obj::Expr(e) => match e { @@ -125,6 +126,7 @@ impl Obj { pub fn as_integer(self) -> EvalResult { match self { + Obj::Scalar(s) => s.as_integer(), Obj::Vector(v) => Ok(Obj::Vector(v.as_integer())), Obj::Null => Ok(Obj::Vector(Vector::from(Vec::::new()))), _ => Err(Signal::Error(Error::CannotBeCoercedToInteger)), @@ -133,6 +135,7 @@ impl Obj { pub fn as_double(self) -> EvalResult { match self { + Obj::Scalar(s) => s.as_double(), Obj::Vector(v) => Ok(Obj::Vector(v.as_double())), Obj::Null => Ok(Obj::Vector(Vector::from(Vec::::new()))), _ => Error::CannotBeCoercedToDouble.into(), @@ -141,6 +144,7 @@ impl Obj { pub fn as_logical(self) -> EvalResult { match self { + Obj::Scalar(s) => s.as_logical(), Obj::Vector(v) => Ok(Obj::Vector(v.as_logical())), Obj::Null => Ok(Obj::Vector(Vector::from(Vec::::new()))), _ => Error::CannotBeCoercedToLogical.into(), @@ -149,6 +153,7 @@ impl Obj { pub fn as_character(self) -> EvalResult { match self { + Obj::Scalar(s) => s.as_character(), Obj::Vector(v) => Ok(Obj::Vector(v.as_character())), Obj::Null => Ok(Obj::Vector(Vector::from(Vec::::new()))), _ => Error::CannotBeCoercedToCharacter.into(), @@ -158,6 +163,7 @@ impl Obj { pub fn as_vector(self) -> EvalResult { match self { Obj::Null => Ok(Obj::Vector(Vector::from(Vec::::new()))), + Obj::Scalar(s) => s.as_vector(), Obj::Vector(_) => Ok(self), _ => Error::CannotBeCoercedTo("vector").into(), } @@ -188,6 +194,10 @@ impl Obj { pub fn get(&self, index: usize) -> Option { match self { + Obj::Scalar(s) => Obj::Scalar(s.clone()) + .as_vector() + .map(|v| v.get(index)) + .unwrap_or(None), Obj::Vector(v) => v.get(index).map(Obj::Vector), Obj::Null => None, Obj::List(..) => None, @@ -316,7 +326,8 @@ impl TryInto for Obj { impl Display for Obj { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Obj::Vector(v) => write!(f, "{}", v), + Obj::Scalar(s) => write!(f, "{s}"), + Obj::Vector(v) => write!(f, "{v}"), Obj::Null => write!(f, "NULL"), Obj::Environment(x) => write!(f, "", x.values.as_ptr()), Obj::Function(formals, Expr::Primitive(primitive), _) => { @@ -387,10 +398,12 @@ fn display_list(x: &List, f: &mut fmt::Formatter<'_>, bc: Option) -> fmt impl std::ops::Add for Obj { type Output = EvalResult; - fn add(self, rhs: Self) -> Self::Output { match (self.as_double()?, rhs.as_double()?) { + (Obj::Scalar(l), Obj::Scalar(r)) => Ok(Obj::Scalar(l + r)), (Obj::Vector(l), Obj::Vector(r)) => Ok(Obj::Vector(l + r)), + (l @ Obj::Scalar(_), r @ Obj::Vector(_)) => l.as_vector()? + r, + (l @ Obj::Vector(_), r @ Obj::Scalar(_)) => l + r.as_vector()?, _ => internal_err!(), } } @@ -398,10 +411,12 @@ impl std::ops::Add for Obj { impl std::ops::Sub for Obj { type Output = EvalResult; - fn sub(self, rhs: Self) -> Self::Output { match (self.as_double()?, rhs.as_double()?) { + (Obj::Scalar(l), Obj::Scalar(r)) => Ok(Obj::Scalar(l - r)), (Obj::Vector(l), Obj::Vector(r)) => Ok(Obj::Vector(l - r)), + (l @ Obj::Scalar(_), r @ Obj::Vector(_)) => l.as_vector()? - r, + (l @ Obj::Vector(_), r @ Obj::Scalar(_)) => l - r.as_vector()?, _ => internal_err!(), } } @@ -409,9 +424,9 @@ impl std::ops::Sub for Obj { impl std::ops::Neg for Obj { type Output = EvalResult; - fn neg(self) -> Self::Output { match self.as_double()? { + Obj::Scalar(x) => Ok(Obj::Scalar(-x)), Obj::Vector(x) => Ok(Obj::Vector(-x)), _ => internal_err!(), } @@ -420,10 +435,12 @@ impl std::ops::Neg for Obj { impl std::ops::Mul for Obj { type Output = EvalResult; - fn mul(self, rhs: Self) -> Self::Output { match (self.as_double()?, rhs.as_double()?) { + (Obj::Scalar(l), Obj::Scalar(r)) => Ok(Obj::Scalar(l * r)), (Obj::Vector(l), Obj::Vector(r)) => Ok(Obj::Vector(l * r)), + (l @ Obj::Scalar(_), r @ Obj::Vector(_)) => l.as_vector()? * r, + (l @ Obj::Vector(_), r @ Obj::Scalar(_)) => l * r.as_vector()?, _ => internal_err!(), } } @@ -431,10 +448,12 @@ impl std::ops::Mul for Obj { impl std::ops::Div for Obj { type Output = EvalResult; - fn div(self, rhs: Self) -> Self::Output { match (self.as_double()?, rhs.as_double()?) { + (Obj::Scalar(l), Obj::Scalar(r)) => Ok(Obj::Scalar(l / r)), (Obj::Vector(l), Obj::Vector(r)) => Ok(Obj::Vector(l / r)), + (l @ Obj::Scalar(_), r @ Obj::Vector(_)) => l.as_vector()? / r, + (l @ Obj::Vector(_), r @ Obj::Scalar(_)) => l / r.as_vector()?, _ => internal_err!(), } } @@ -442,10 +461,12 @@ impl std::ops::Div for Obj { impl super::object::Pow for Obj { type Output = EvalResult; - fn power(self, rhs: Self) -> Self::Output { match (self.as_double()?, rhs.as_double()?) { + (Obj::Scalar(l), Obj::Scalar(r)) => Ok(Obj::Scalar(l.power(r))), (Obj::Vector(l), Obj::Vector(r)) => Ok(Obj::Vector(l.power(r))), + (l @ Obj::Scalar(_), r @ Obj::Vector(_)) => l.as_vector()?.power(r), + (l @ Obj::Vector(_), r @ Obj::Scalar(_)) => l.power(r.as_vector()?), _ => internal_err!(), } } @@ -453,10 +474,12 @@ impl super::object::Pow for Obj { impl std::ops::Rem for Obj { type Output = EvalResult; - fn rem(self, rhs: Self) -> Self::Output { match (self.as_double()?, rhs.as_double()?) { + (Obj::Scalar(l), Obj::Scalar(r)) => Ok(Obj::Scalar(l % r)), (Obj::Vector(l), Obj::Vector(r)) => Ok(Obj::Vector(l % r)), + (l @ Obj::Scalar(_), r @ Obj::Vector(_)) => l.as_vector()? % r, + (l @ Obj::Vector(_), r @ Obj::Scalar(_)) => l % r.as_vector()?, _ => internal_err!(), } } @@ -464,10 +487,16 @@ impl std::ops::Rem for Obj { impl std::ops::BitOr for Obj { type Output = EvalResult; - fn bitor(self, rhs: Self) -> Self::Output { - match (self.as_logical()?, rhs.as_logical()?) { + match (self, rhs) { + (Obj::Scalar(l), Obj::Scalar(r)) => Ok(Obj::Scalar(l | r)), (Obj::Vector(l), Obj::Vector(r)) => Ok(Obj::Vector(l | r)), + (l @ Obj::Scalar(_), r @ Obj::Vector(_)) => { + l.as_vector()?.as_logical()? | r.as_logical()? + } + (l @ Obj::Vector(_), r @ Obj::Scalar(_)) => { + l.as_logical()? | r.as_vector()?.as_logical()? + } _ => internal_err!(), } } @@ -475,10 +504,16 @@ impl std::ops::BitOr for Obj { impl std::ops::BitAnd for Obj { type Output = EvalResult; - fn bitand(self, rhs: Self) -> Self::Output { - match (self.as_logical()?, rhs.as_logical()?) { + match (self, rhs) { + (Obj::Scalar(l), Obj::Scalar(r)) => Ok(Obj::Scalar(l & r)), (Obj::Vector(l), Obj::Vector(r)) => Ok(Obj::Vector(l & r)), + (l @ Obj::Scalar(_), r @ Obj::Vector(_)) => { + l.as_vector()?.as_logical()? & r.as_logical()? + } + (l @ Obj::Vector(_), r @ Obj::Scalar(_)) => { + l.as_logical()? & r.as_vector()?.as_logical()? + } _ => internal_err!(), } } @@ -487,29 +522,41 @@ impl std::ops::BitAnd for Obj { impl VecPartialCmp for Obj { type Output = EvalResult; fn vec_gt(self, rhs: Self) -> Self::Output { - match (self.as_vector()?, rhs.as_vector()?) { + match (self, rhs) { + (Obj::Scalar(l), Obj::Scalar(r)) => Ok(Obj::Scalar(l.vec_gt(r))), (Obj::Vector(l), Obj::Vector(r)) => Ok(Obj::Vector(l.vec_gt(r))), + (l @ Obj::Scalar(_), r @ Obj::Vector(_)) => l.as_vector()?.vec_gt(r), + (l @ Obj::Vector(_), r @ Obj::Scalar(_)) => l.vec_gt(r.as_vector()?), _ => internal_err!(), } } fn vec_gte(self, rhs: Self) -> Self::Output { - match (self.as_vector()?, rhs.as_vector()?) { + match (self, rhs) { + (Obj::Scalar(l), Obj::Scalar(r)) => Ok(Obj::Scalar(l.vec_gte(r))), (Obj::Vector(l), Obj::Vector(r)) => Ok(Obj::Vector(l.vec_gte(r))), + (l @ Obj::Scalar(_), r @ Obj::Vector(_)) => l.as_vector()?.vec_gte(r), + (l @ Obj::Vector(_), r @ Obj::Scalar(_)) => l.vec_gte(r.as_vector()?), _ => internal_err!(), } } fn vec_lt(self, rhs: Self) -> Self::Output { - match (self.as_vector()?, rhs.as_vector()?) { + match (self, rhs) { + (Obj::Scalar(l), Obj::Scalar(r)) => Ok(Obj::Scalar(l.vec_lt(r))), (Obj::Vector(l), Obj::Vector(r)) => Ok(Obj::Vector(l.vec_lt(r))), + (l @ Obj::Scalar(_), r @ Obj::Vector(_)) => l.as_vector()?.vec_lt(r), + (l @ Obj::Vector(_), r @ Obj::Scalar(_)) => l.vec_lt(r.as_vector()?), _ => internal_err!(), } } fn vec_lte(self, rhs: Self) -> Self::Output { - match (self.as_vector()?, rhs.as_vector()?) { + match (self, rhs) { + (Obj::Scalar(l), Obj::Scalar(r)) => Ok(Obj::Scalar(l.vec_lte(r))), (Obj::Vector(l), Obj::Vector(r)) => Ok(Obj::Vector(l.vec_lte(r))), + (l @ Obj::Scalar(_), r @ Obj::Vector(_)) => l.as_vector()?.vec_lte(r), + (l @ Obj::Vector(_), r @ Obj::Scalar(_)) => l.vec_lte(r.as_vector()?), _ => internal_err!(), } } @@ -521,7 +568,10 @@ impl VecPartialCmp for Obj { (lhs @ Obj::Function(..), rhs @ Obj::Function(..)) => Ok((lhs == rhs).into()), (lhs @ Obj::Environment(_), rhs @ Obj::Environment(_)) => Ok((lhs == rhs).into()), (lhs, rhs) => match (lhs.as_vector()?, rhs.as_vector()?) { + (Obj::Scalar(l), Obj::Scalar(r)) => Ok(Obj::Scalar(l.vec_eq(r))), (Obj::Vector(l), Obj::Vector(r)) => Ok(Obj::Vector(l.vec_eq(r))), + (l @ Obj::Scalar(_), r @ Obj::Vector(_)) => l.as_vector()?.vec_eq(r), + (l @ Obj::Vector(_), r @ Obj::Scalar(_)) => l.vec_eq(r.as_vector()?), _ => internal_err!(), }, } @@ -534,7 +584,10 @@ impl VecPartialCmp for Obj { (lhs @ Obj::Function(..), rhs @ Obj::Function(..)) => Ok((lhs != rhs).into()), (lhs @ Obj::Environment(_), rhs @ Obj::Environment(_)) => Ok((lhs != rhs).into()), (lhs, rhs) => match (lhs.as_vector()?, rhs.as_vector()?) { + (Obj::Scalar(l), Obj::Scalar(r)) => Ok(Obj::Scalar(l.vec_neq(r))), (Obj::Vector(l), Obj::Vector(r)) => Ok(Obj::Vector(l.vec_neq(r))), + (l @ Obj::Scalar(_), r @ Obj::Vector(_)) => l.as_vector()?.vec_neq(r), + (l @ Obj::Vector(_), r @ Obj::Scalar(_)) => l.vec_neq(r.as_vector()?), _ => internal_err!(), }, } @@ -913,10 +966,10 @@ impl Context for Obj { Expr::Inf => Ok(Obj::Vector(Vector::from(vec![OptionNA::Some( f64::INFINITY, )]))), - Expr::Number(x) => Ok(Obj::Vector(Vector::from(vec![x]))), - Expr::Integer(x) => Ok(Obj::Vector(Vector::from(vec![x]))), - Expr::Bool(x) => Ok(Obj::Vector(Vector::from(vec![OptionNA::Some(x)]))), - Expr::String(x) => Ok(Obj::Vector(Vector::from(vec![OptionNA::Some(x)]))), + Expr::Number(x) => Ok(Obj::Scalar(Scalar::F64(ScalarType(x)))), + Expr::Integer(x) => Ok(Obj::Scalar(Scalar::I32(ScalarType(x)))), + Expr::Bool(x) => Ok(Obj::Scalar(Scalar::Bool(ScalarType(x)))), + Expr::String(x) => Ok(Obj::Scalar(Scalar::String(ScalarType(x)))), Expr::Function(formals, body) => Ok(Obj::Function(formals, *body, self.env().clone())), Expr::Symbol(name) => self.get(name), Expr::Break => Err(Signal::Condition(Cond::Break)), @@ -953,13 +1006,11 @@ impl Context for Rc { match expr { Expr::Null => Ok(Obj::Null), Expr::NA => Ok(Obj::Vector(Vector::from(vec![OptionNA::NA as Logical]))), - Expr::Inf => Ok(Obj::Vector(Vector::from(vec![OptionNA::Some( - f64::INFINITY, - )]))), - Expr::Number(x) => Ok(Obj::Vector(Vector::from(vec![x]))), - Expr::Integer(x) => Ok(Obj::Vector(Vector::from(vec![x]))), - Expr::Bool(x) => Ok(Obj::Vector(Vector::from(vec![OptionNA::Some(x)]))), - Expr::String(x) => Ok(Obj::Vector(Vector::from(vec![OptionNA::Some(x)]))), + Expr::Inf => Ok(Obj::Scalar(Scalar::F64(ScalarType(f64::INFINITY)))), + Expr::Number(x) => Ok(Obj::Scalar(Scalar::F64(ScalarType(x)))), + Expr::Integer(x) => Ok(Obj::Scalar(Scalar::I32(ScalarType(x)))), + Expr::Bool(x) => Ok(Obj::Scalar(Scalar::Bool(ScalarType(x)))), + Expr::String(x) => Ok(Obj::Scalar(Scalar::String(ScalarType(x)))), Expr::Function(formals, body) => Ok(Obj::Function( assert_formals(&Session::default(), formals)?, *body, diff --git a/src/object/core.rs b/src/object/core.rs index e39ce10c..1c0e7a3e 100644 --- a/src/object/core.rs +++ b/src/object/core.rs @@ -11,6 +11,7 @@ pub enum Obj { // Data structures #[default] Null, + Scalar(Scalar), Vector(Vector), List(List), diff --git a/src/object/mod.rs b/src/object/mod.rs index 6d24f817..e297555d 100644 --- a/src/object/mod.rs +++ b/src/object/mod.rs @@ -7,8 +7,11 @@ pub use ast::*; mod environment; pub use environment::*; -mod vector; -pub use vector::*; - mod list; pub use list::*; + +mod scalar; +pub use scalar::*; + +mod vector; +pub use vector::*; diff --git a/src/object/scalar.rs b/src/object/scalar.rs new file mode 100644 index 00000000..24d1b6ff --- /dev/null +++ b/src/object/scalar.rs @@ -0,0 +1,761 @@ +use std::fmt::Display; + +use crate::{ + lang::{EvalResult, Signal}, + object::vector::rep::Rep, + object::{coercion::CoercibleInto, Obj, Vector}, +}; + +use super::{ + coercion::{Atomic, CommonCmp, CommonNum, MinimallyNumeric}, + VecPartialCmp, +}; + +#[derive(Debug, Clone, PartialEq)] +pub struct ScalarType(pub T); + +impl Display for ScalarType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ScalarType(inner) => write!(f, "{inner}"), + } + } +} + +#[derive(Debug, Clone, PartialEq)] +pub enum Scalar { + Bool(ScalarType), + I32(ScalarType), + F64(ScalarType), + String(ScalarType), + NA, + NEGINF, + INF, +} + +impl Display for Scalar { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use Scalar::*; + match self { + Bool(x) => write!(f, "{x}"), + I32(x) => write!(f, "{x}"), + F64(x) => write!(f, "{x}"), + String(x) => write!(f, "{x}"), + NA => write!(f, "NA"), + INF => write!(f, "inf"), + NEGINF => write!(f, "-inf"), + } + } +} + +impl Default for Scalar { + fn default() -> Self { + Self::Bool(ScalarType(true)) + } +} + +impl ScalarType { + pub fn as_integer(self) -> EvalResult + where + T: CoercibleInto, + { + match self { + ScalarType(inner) => Ok(Obj::Scalar(Scalar::I32(ScalarType(inner.coerce_into())))), + } + } + + pub fn as_double(self) -> EvalResult + where + T: CoercibleInto, + { + match self { + ScalarType(inner) => Ok(Obj::Scalar(Scalar::F64(ScalarType(inner.coerce_into())))), + } + } + + pub fn as_logical(self) -> EvalResult + where + T: CoercibleInto, + { + match self { + ScalarType(inner) => Ok(Obj::Scalar(Scalar::Bool(ScalarType(inner.coerce_into())))), + } + } + + pub fn as_character(self) -> EvalResult + where + T: CoercibleInto, + { + match self { + ScalarType(inner) => Ok(Obj::Scalar(Scalar::String(ScalarType(inner.coerce_into())))), + } + } +} + +impl Scalar { + pub fn as_vector(self) -> EvalResult { + use Scalar::*; + match self { + Bool(ScalarType(x)) => Ok(Obj::Vector(Vector::from(vec![x]))), + I32(ScalarType(x)) => Ok(Obj::Vector(Vector::from(vec![x]))), + F64(ScalarType(x)) => Ok(Obj::Vector(Vector::from(vec![x]))), + String(ScalarType(x)) => Ok(Obj::Vector(Vector::from(vec![x]))), + NA => todo!(), + INF => todo!(), + NEGINF => todo!(), + } + } + + pub fn as_integer(self) -> EvalResult { + use crate::error::Error::*; + use Scalar::*; + match self { + Bool(x) => x.as_integer(), + I32(_) => Ok(Obj::Scalar(self)), + F64(x) => x.as_integer(), + String(_) => CannotBeCoercedToInteger.into(), + NA => todo!(), + INF => todo!(), + NEGINF => todo!(), + } + } + + pub fn as_double(self) -> EvalResult { + use crate::error::Error::*; + use Scalar::*; + match self { + Bool(x) => x.as_double(), + I32(x) => x.as_double(), + F64(_) => Ok(Obj::Scalar(self)), + String(_) => CannotBeCoercedToDouble.into(), + NA => todo!(), + INF => todo!(), + NEGINF => todo!(), + } + } + + pub fn as_logical(self) -> EvalResult { + use crate::error::Error::*; + use Scalar::*; + match self { + Bool(_) => Ok(Obj::Scalar(self)), + I32(x) => x.as_logical(), + F64(x) => x.as_logical(), + String(_) => CannotBeCoercedToLogical.into(), + NA => todo!(), + INF => todo!(), + NEGINF => todo!(), + } + } + + pub fn as_character(self) -> EvalResult { + use Scalar::*; + match self { + Bool(x) => x.as_character(), + I32(x) => x.as_character(), + F64(x) => x.as_character(), + String(_) => Ok(Obj::Scalar(self)), + NA => todo!(), + INF => todo!(), + NEGINF => todo!(), + } + } +} + +impl TryInto for Rep { + type Error = Signal; + fn try_into(self) -> Result { + match self { + Rep::Subset(_, _) => todo!(), + } + } +} + +impl From for bool { + fn from(value: Scalar) -> Self { + match value { + Scalar::Bool(ScalarType(x)) => x, + Scalar::I32(ScalarType(x)) => x != 0, + Scalar::F64(ScalarType(x)) => x.round() as i32 != 0, + Scalar::String(ScalarType(_)) => todo!(), + Scalar::NA => todo!(), + Scalar::NEGINF => todo!(), + Scalar::INF => todo!(), + } + } +} + +impl From for Scalar { + fn from(val: bool) -> Self { + Scalar::Bool(ScalarType(val)) + } +} + +impl From for Scalar { + fn from(val: i32) -> Self { + Scalar::I32(ScalarType(val)) + } +} + +impl From for Scalar { + fn from(val: f64) -> Self { + Scalar::F64(ScalarType(val)) + } +} + +impl From for Scalar { + fn from(val: String) -> Self { + Scalar::String(ScalarType(val)) + } +} + +impl std::ops::Neg for Scalar { + type Output = Scalar; + fn neg(self) -> Self::Output { + match self { + Scalar::Bool(ScalarType(x)) => { + Scalar::I32(ScalarType(-CoercibleInto::::coerce_into(x))) + } + Scalar::I32(ScalarType(x)) => Scalar::I32(ScalarType(-x)), + Scalar::F64(ScalarType(x)) => Scalar::F64(ScalarType(-x)), + Scalar::NA => Scalar::NA, + Scalar::INF => Scalar::NEGINF, + Scalar::NEGINF => Scalar::INF, + _ => todo!(), + } + } +} + +impl std::ops::Add for Scalar { + type Output = Scalar; + fn add(self, rhs: Self) -> Self::Output { + match (self, rhs) { + (Scalar::Bool(l), Scalar::Bool(r)) => (l + r).into(), + (Scalar::Bool(l), Scalar::I32(r)) => (l + r).into(), + (Scalar::Bool(l), Scalar::F64(r)) => (l + r).into(), + (Scalar::I32(l), Scalar::Bool(r)) => (l + r).into(), + (Scalar::I32(l), Scalar::I32(r)) => (l + r).into(), + (Scalar::I32(l), Scalar::F64(r)) => (l + r).into(), + (Scalar::F64(l), Scalar::Bool(r)) => (l + r).into(), + (Scalar::F64(l), Scalar::I32(r)) => (l + r).into(), + (Scalar::F64(l), Scalar::F64(r)) => (l + r).into(), + (Scalar::NA, _) => Scalar::NA, + (_, Scalar::NA) => Scalar::NA, + (Scalar::INF, _) => Scalar::INF, + (_, Scalar::INF) => Scalar::INF, + _ => todo!(), + } + } +} + +impl std::ops::Add> for ScalarType +where + L: Atomic + MinimallyNumeric + CoercibleInto, + R: Atomic + MinimallyNumeric + CoercibleInto, + (LNum, RNum): CommonNum, + C: std::ops::Add, +{ + type Output = O; + fn add(self, rhs: ScalarType) -> Self::Output { + let ScalarType(l_inner) = self; + let ScalarType(r_inner) = rhs; + let (l_common, r_common) = ( + CoercibleInto::::coerce_into(l_inner), + CoercibleInto::::coerce_into(r_inner), + ) + .into_common(); + + l_common + r_common + } +} + +impl std::ops::Sub for Scalar { + type Output = Scalar; + fn sub(self, rhs: Self) -> Self::Output { + match (self, rhs) { + (Scalar::Bool(l), Scalar::Bool(r)) => (l - r).into(), + (Scalar::Bool(l), Scalar::I32(r)) => (l - r).into(), + (Scalar::Bool(l), Scalar::F64(r)) => (l - r).into(), + (Scalar::I32(l), Scalar::Bool(r)) => (l - r).into(), + (Scalar::I32(l), Scalar::I32(r)) => (l - r).into(), + (Scalar::I32(l), Scalar::F64(r)) => (l - r).into(), + (Scalar::F64(l), Scalar::Bool(r)) => (l - r).into(), + (Scalar::F64(l), Scalar::I32(r)) => (l - r).into(), + (Scalar::F64(l), Scalar::F64(r)) => (l - r).into(), + (Scalar::NA, _) => Scalar::NA, + (_, Scalar::NA) => Scalar::NA, + (Scalar::INF, _) => Scalar::INF, + (_, Scalar::INF) => Scalar::NEGINF, + (Scalar::NEGINF, _) => Scalar::NEGINF, + (_, Scalar::NEGINF) => Scalar::INF, + _ => todo!(), + } + } +} + +impl std::ops::Sub> for ScalarType +where + L: Atomic + MinimallyNumeric + CoercibleInto, + R: Atomic + MinimallyNumeric + CoercibleInto, + (LNum, RNum): CommonNum, + C: std::ops::Sub, +{ + type Output = O; + fn sub(self, rhs: ScalarType) -> Self::Output { + let ScalarType(l_inner) = self; + let ScalarType(r_inner) = rhs; + let (l_common, r_common) = ( + CoercibleInto::::coerce_into(l_inner), + CoercibleInto::::coerce_into(r_inner), + ) + .into_common(); + + l_common - r_common + } +} +impl std::ops::Mul for Scalar { + type Output = Scalar; + fn mul(self, rhs: Self) -> Self::Output { + match (self, rhs) { + (Scalar::Bool(l), Scalar::Bool(r)) => (l * r).into(), + (Scalar::Bool(l), Scalar::I32(r)) => (l * r).into(), + (Scalar::Bool(l), Scalar::F64(r)) => (l * r).into(), + (Scalar::I32(l), Scalar::Bool(r)) => (l * r).into(), + (Scalar::I32(l), Scalar::I32(r)) => (l * r).into(), + (Scalar::I32(l), Scalar::F64(r)) => (l * r).into(), + (Scalar::F64(l), Scalar::Bool(r)) => (l * r).into(), + (Scalar::F64(l), Scalar::I32(r)) => (l * r).into(), + (Scalar::F64(l), Scalar::F64(r)) => (l * r).into(), + (Scalar::NA, _) => Scalar::NA, + (_, Scalar::NA) => Scalar::NA, + (Scalar::INF, _) => Scalar::INF, + (_, Scalar::INF) => Scalar::INF, + (Scalar::NEGINF, _) => Scalar::NEGINF, + (_, Scalar::NEGINF) => Scalar::NEGINF, + _ => todo!(), + } + } +} + +impl std::ops::Mul> for ScalarType +where + L: Atomic + MinimallyNumeric + CoercibleInto, + R: Atomic + MinimallyNumeric + CoercibleInto, + (LNum, RNum): CommonNum, + C: std::ops::Mul, +{ + type Output = O; + fn mul(self, rhs: ScalarType) -> Self::Output { + let ScalarType(l_inner) = self; + let ScalarType(r_inner) = rhs; + let (l_common, r_common) = ( + CoercibleInto::::coerce_into(l_inner), + CoercibleInto::::coerce_into(r_inner), + ) + .into_common(); + + l_common * r_common + } +} + +impl std::ops::Div for Scalar { + type Output = Scalar; + fn div(self, rhs: Self) -> Self::Output { + match (self, rhs) { + (Scalar::Bool(l), Scalar::Bool(r)) => (l / r).into(), + (Scalar::Bool(l), Scalar::I32(r)) => (l / r).into(), + (Scalar::Bool(l), Scalar::F64(r)) => (l / r).into(), + (Scalar::I32(l), Scalar::Bool(r)) => (l / r).into(), + (Scalar::I32(l), Scalar::I32(r)) => (l / r).into(), + (Scalar::I32(l), Scalar::F64(r)) => (l / r).into(), + (Scalar::F64(l), Scalar::Bool(r)) => (l / r).into(), + (Scalar::F64(l), Scalar::I32(r)) => (l / r).into(), + (Scalar::F64(l), Scalar::F64(r)) => (l / r).into(), + (Scalar::NA, _) => Scalar::NA, + (_, Scalar::NA) => Scalar::NA, + (Scalar::INF, _) => Scalar::INF, + (_, Scalar::INF) => Scalar::F64(ScalarType(0.0)), + (Scalar::NEGINF, _) => Scalar::NEGINF, + (_, Scalar::NEGINF) => Scalar::F64(ScalarType(-0.0)), + _ => todo!(), + } + } +} + +impl std::ops::Div> for ScalarType +where + L: Atomic + MinimallyNumeric + CoercibleInto, + R: Atomic + MinimallyNumeric + CoercibleInto, + (LNum, RNum): CommonNum, + C: std::ops::Div, +{ + type Output = O; + fn div(self, rhs: ScalarType) -> Self::Output { + let ScalarType(l_inner) = self; + let ScalarType(r_inner) = rhs; + let (l_common, r_common) = ( + CoercibleInto::::coerce_into(l_inner), + CoercibleInto::::coerce_into(r_inner), + ) + .into_common(); + + l_common / r_common + } +} + +impl super::Pow for Scalar { + type Output = Scalar; + fn power(self, rhs: Self) -> Self::Output { + match (self, rhs) { + (Scalar::Bool(l), Scalar::Bool(r)) => (l.power(r)).into(), + (Scalar::Bool(l), Scalar::I32(r)) => (l.power(r)).into(), + (Scalar::Bool(l), Scalar::F64(r)) => (l.power(r)).into(), + (Scalar::I32(l), Scalar::Bool(r)) => (l.power(r)).into(), + (Scalar::I32(l), Scalar::I32(r)) => (l.power(r)).into(), + (Scalar::I32(l), Scalar::F64(r)) => (l.power(r)).into(), + (Scalar::F64(l), Scalar::Bool(r)) => (l.power(r)).into(), + (Scalar::F64(l), Scalar::I32(r)) => (l.power(r)).into(), + (Scalar::F64(l), Scalar::F64(r)) => (l.power(r)).into(), + (Scalar::NA, _) => Scalar::NA, + (_, Scalar::NA) => Scalar::NA, + (Scalar::INF, _) => Scalar::INF, + (_, Scalar::INF) => Scalar::F64(ScalarType(0.0)), + (Scalar::NEGINF, _) => Scalar::NEGINF, + (_, Scalar::NEGINF) => Scalar::F64(ScalarType(-0.0)), + _ => todo!(), + } + } +} + +impl super::Pow> for ScalarType +where + L: Atomic + MinimallyNumeric + CoercibleInto, + R: Atomic + MinimallyNumeric + CoercibleInto, + (LNum, RNum): CommonNum, + C: super::Pow, +{ + type Output = O; + fn power(self, rhs: ScalarType) -> Self::Output { + let ScalarType(l_inner) = self; + let ScalarType(r_inner) = rhs; + let (l_common, r_common) = ( + CoercibleInto::::coerce_into(l_inner), + CoercibleInto::::coerce_into(r_inner), + ) + .into_common(); + + l_common.power(r_common) + } +} + +impl std::ops::Rem for Scalar { + type Output = Scalar; + fn rem(self, rhs: Self) -> Self::Output { + match (self, rhs) { + (Scalar::Bool(l), Scalar::Bool(r)) => (l % r).into(), + (Scalar::Bool(l), Scalar::I32(r)) => (l % r).into(), + (Scalar::Bool(l), Scalar::F64(r)) => (l % r).into(), + (Scalar::I32(l), Scalar::Bool(r)) => (l % r).into(), + (Scalar::I32(l), Scalar::I32(r)) => (l % r).into(), + (Scalar::I32(l), Scalar::F64(r)) => (l % r).into(), + (Scalar::F64(l), Scalar::Bool(r)) => (l % r).into(), + (Scalar::F64(l), Scalar::I32(r)) => (l % r).into(), + (Scalar::F64(l), Scalar::F64(r)) => (l % r).into(), + (Scalar::NA, _) => Scalar::NA, + (_, Scalar::NA) => Scalar::NA, + (Scalar::INF, _) => Scalar::INF, + (_, Scalar::INF) => Scalar::F64(ScalarType(0.0)), + (Scalar::NEGINF, _) => Scalar::NEGINF, + (_, Scalar::NEGINF) => Scalar::F64(ScalarType(-0.0)), + _ => todo!(), + } + } +} + +impl std::ops::Rem> for ScalarType +where + L: Atomic + MinimallyNumeric + CoercibleInto, + R: Atomic + MinimallyNumeric + CoercibleInto, + (LNum, RNum): CommonNum, + C: std::ops::Rem, +{ + type Output = O; + fn rem(self, rhs: ScalarType) -> Self::Output { + let ScalarType(l_inner) = self; + let ScalarType(r_inner) = rhs; + let (l_common, r_common) = ( + CoercibleInto::::coerce_into(l_inner), + CoercibleInto::::coerce_into(r_inner), + ) + .into_common(); + + l_common % r_common + } +} + +impl std::ops::BitOr for Scalar { + type Output = Scalar; + fn bitor(self, rhs: Self) -> Self::Output { + match (self, rhs) { + (Scalar::Bool(l), Scalar::Bool(r)) => (l | r).into(), + (Scalar::Bool(l), Scalar::I32(r)) => (l | r).into(), + (Scalar::Bool(l), Scalar::F64(r)) => (l | r).into(), + (Scalar::I32(l), Scalar::Bool(r)) => (l | r).into(), + (Scalar::I32(l), Scalar::I32(r)) => (l | r).into(), + (Scalar::I32(l), Scalar::F64(r)) => (l | r).into(), + (Scalar::F64(l), Scalar::Bool(r)) => (l | r).into(), + (Scalar::F64(l), Scalar::I32(r)) => (l | r).into(), + (Scalar::F64(l), Scalar::F64(r)) => (l | r).into(), + (Scalar::NA, _) => Scalar::NA, + (_, Scalar::NA) => Scalar::NA, + (Scalar::INF, _) => Scalar::INF, + (_, Scalar::INF) => Scalar::F64(ScalarType(0.0)), + (Scalar::NEGINF, _) => Scalar::NEGINF, + (_, Scalar::NEGINF) => Scalar::F64(ScalarType(-0.0)), + _ => todo!(), + } + } +} + +impl std::ops::BitOr> for ScalarType +where + L: Atomic + CoercibleInto, + R: Atomic + CoercibleInto, + bool: std::ops::BitOr, +{ + type Output = bool; + fn bitor(self, rhs: ScalarType) -> Self::Output { + let ScalarType(l_inner) = self; + let ScalarType(r_inner) = rhs; + CoercibleInto::::coerce_into(l_inner) | CoercibleInto::::coerce_into(r_inner) + } +} + +impl std::ops::BitAnd for Scalar { + type Output = Scalar; + fn bitand(self, rhs: Self) -> Self::Output { + match (self, rhs) { + (Scalar::Bool(l), Scalar::Bool(r)) => (l & r).into(), + (Scalar::Bool(l), Scalar::I32(r)) => (l & r).into(), + (Scalar::Bool(l), Scalar::F64(r)) => (l & r).into(), + (Scalar::I32(l), Scalar::Bool(r)) => (l & r).into(), + (Scalar::I32(l), Scalar::I32(r)) => (l & r).into(), + (Scalar::I32(l), Scalar::F64(r)) => (l & r).into(), + (Scalar::F64(l), Scalar::Bool(r)) => (l & r).into(), + (Scalar::F64(l), Scalar::I32(r)) => (l & r).into(), + (Scalar::F64(l), Scalar::F64(r)) => (l & r).into(), + (Scalar::NA, _) => Scalar::NA, + (_, Scalar::NA) => Scalar::NA, + (Scalar::INF, _) => Scalar::INF, + (_, Scalar::INF) => Scalar::F64(ScalarType(0.0)), + (Scalar::NEGINF, _) => Scalar::NEGINF, + (_, Scalar::NEGINF) => Scalar::F64(ScalarType(-0.0)), + _ => todo!(), + } + } +} + +impl std::ops::BitAnd> for ScalarType +where + L: Atomic + CoercibleInto, + R: Atomic + CoercibleInto, + bool: std::ops::BitAnd, +{ + type Output = bool; + fn bitand(self, rhs: ScalarType) -> Self::Output { + let ScalarType(l_inner) = self; + let ScalarType(r_inner) = rhs; + CoercibleInto::::coerce_into(l_inner) & CoercibleInto::::coerce_into(r_inner) + } +} + +impl VecPartialCmp for Scalar { + type Output = Scalar; + fn vec_gt(self, rhs: Scalar) -> Self::Output { + match (self, rhs) { + (Scalar::Bool(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_gt(r)), + (Scalar::Bool(l), Scalar::I32(r)) => Scalar::Bool(l.vec_gt(r)), + (Scalar::Bool(l), Scalar::F64(r)) => Scalar::Bool(l.vec_gt(r)), + (Scalar::I32(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_gt(r)), + (Scalar::I32(l), Scalar::I32(r)) => Scalar::Bool(l.vec_gt(r)), + (Scalar::I32(l), Scalar::F64(r)) => Scalar::Bool(l.vec_gt(r)), + (Scalar::F64(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_gt(r)), + (Scalar::F64(l), Scalar::I32(r)) => Scalar::Bool(l.vec_gt(r)), + (Scalar::F64(l), Scalar::F64(r)) => Scalar::Bool(l.vec_gt(r)), + (Scalar::NA, _) => Scalar::NA, + (_, Scalar::NA) => Scalar::NA, + (Scalar::INF, _) => Scalar::Bool(ScalarType(true)), + (_, Scalar::INF) => Scalar::Bool(ScalarType(false)), + (Scalar::NEGINF, _) => Scalar::Bool(ScalarType(false)), + (_, Scalar::NEGINF) => Scalar::Bool(ScalarType(true)), + _ => todo!(), + } + } + + fn vec_gte(self, rhs: Scalar) -> Self::Output { + match (self, rhs) { + (Scalar::Bool(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_gte(r)), + (Scalar::Bool(l), Scalar::I32(r)) => Scalar::Bool(l.vec_gte(r)), + (Scalar::Bool(l), Scalar::F64(r)) => Scalar::Bool(l.vec_gte(r)), + (Scalar::I32(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_gte(r)), + (Scalar::I32(l), Scalar::I32(r)) => Scalar::Bool(l.vec_gte(r)), + (Scalar::I32(l), Scalar::F64(r)) => Scalar::Bool(l.vec_gte(r)), + (Scalar::F64(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_gte(r)), + (Scalar::F64(l), Scalar::I32(r)) => Scalar::Bool(l.vec_gte(r)), + (Scalar::F64(l), Scalar::F64(r)) => Scalar::Bool(l.vec_gte(r)), + (Scalar::NA, _) => Scalar::NA, + (_, Scalar::NA) => Scalar::NA, + (Scalar::INF, _) => Scalar::Bool(ScalarType(true)), + (_, Scalar::INF) => Scalar::Bool(ScalarType(false)), + (Scalar::NEGINF, _) => Scalar::Bool(ScalarType(false)), + (_, Scalar::NEGINF) => Scalar::Bool(ScalarType(true)), + _ => todo!(), + } + } + + fn vec_lt(self, rhs: Scalar) -> Self::Output { + match (self, rhs) { + (Scalar::Bool(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_lt(r)), + (Scalar::Bool(l), Scalar::I32(r)) => Scalar::Bool(l.vec_lt(r)), + (Scalar::Bool(l), Scalar::F64(r)) => Scalar::Bool(l.vec_lt(r)), + (Scalar::I32(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_lt(r)), + (Scalar::I32(l), Scalar::I32(r)) => Scalar::Bool(l.vec_lt(r)), + (Scalar::I32(l), Scalar::F64(r)) => Scalar::Bool(l.vec_lt(r)), + (Scalar::F64(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_lt(r)), + (Scalar::F64(l), Scalar::I32(r)) => Scalar::Bool(l.vec_lt(r)), + (Scalar::F64(l), Scalar::F64(r)) => Scalar::Bool(l.vec_lt(r)), + (Scalar::NA, _) => Scalar::NA, + (_, Scalar::NA) => Scalar::NA, + (Scalar::INF, _) => Scalar::Bool(ScalarType(false)), + (_, Scalar::INF) => Scalar::Bool(ScalarType(true)), + (Scalar::NEGINF, _) => Scalar::Bool(ScalarType(true)), + (_, Scalar::NEGINF) => Scalar::Bool(ScalarType(false)), + _ => todo!(), + } + } + + fn vec_lte(self, rhs: Scalar) -> Self::Output { + match (self, rhs) { + (Scalar::Bool(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_lte(r)), + (Scalar::Bool(l), Scalar::I32(r)) => Scalar::Bool(l.vec_lte(r)), + (Scalar::Bool(l), Scalar::F64(r)) => Scalar::Bool(l.vec_lte(r)), + (Scalar::I32(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_lte(r)), + (Scalar::I32(l), Scalar::I32(r)) => Scalar::Bool(l.vec_lte(r)), + (Scalar::I32(l), Scalar::F64(r)) => Scalar::Bool(l.vec_lte(r)), + (Scalar::F64(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_lte(r)), + (Scalar::F64(l), Scalar::I32(r)) => Scalar::Bool(l.vec_lte(r)), + (Scalar::F64(l), Scalar::F64(r)) => Scalar::Bool(l.vec_lte(r)), + (Scalar::NA, _) => Scalar::NA, + (_, Scalar::NA) => Scalar::NA, + (Scalar::INF, _) => Scalar::Bool(ScalarType(false)), + (_, Scalar::INF) => Scalar::Bool(ScalarType(true)), + (Scalar::NEGINF, _) => Scalar::Bool(ScalarType(true)), + (_, Scalar::NEGINF) => Scalar::Bool(ScalarType(false)), + _ => todo!(), + } + } + + fn vec_eq(self, rhs: Scalar) -> Self::Output { + match (self, rhs) { + (Scalar::Bool(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_eq(r)), + (Scalar::Bool(l), Scalar::I32(r)) => Scalar::Bool(l.vec_eq(r)), + (Scalar::Bool(l), Scalar::F64(r)) => Scalar::Bool(l.vec_eq(r)), + (Scalar::I32(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_eq(r)), + (Scalar::I32(l), Scalar::I32(r)) => Scalar::Bool(l.vec_eq(r)), + (Scalar::I32(l), Scalar::F64(r)) => Scalar::Bool(l.vec_eq(r)), + (Scalar::F64(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_eq(r)), + (Scalar::F64(l), Scalar::I32(r)) => Scalar::Bool(l.vec_eq(r)), + (Scalar::F64(l), Scalar::F64(r)) => Scalar::Bool(l.vec_eq(r)), + (Scalar::NA, _) => Scalar::NA, + (_, Scalar::NA) => Scalar::NA, + (Scalar::INF, Scalar::INF) => Scalar::Bool(ScalarType(true)), + (Scalar::INF, _) => Scalar::Bool(ScalarType(false)), + (_, Scalar::INF) => Scalar::Bool(ScalarType(false)), + (Scalar::NEGINF, Scalar::NEGINF) => Scalar::Bool(ScalarType(true)), + (Scalar::NEGINF, _) => Scalar::Bool(ScalarType(false)), + (_, Scalar::NEGINF) => Scalar::Bool(ScalarType(false)), + _ => todo!(), + } + } + + fn vec_neq(self, rhs: Scalar) -> Self::Output { + match (self, rhs) { + (Scalar::Bool(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_neq(r)), + (Scalar::Bool(l), Scalar::I32(r)) => Scalar::Bool(l.vec_neq(r)), + (Scalar::Bool(l), Scalar::F64(r)) => Scalar::Bool(l.vec_neq(r)), + (Scalar::I32(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_neq(r)), + (Scalar::I32(l), Scalar::I32(r)) => Scalar::Bool(l.vec_neq(r)), + (Scalar::I32(l), Scalar::F64(r)) => Scalar::Bool(l.vec_neq(r)), + (Scalar::F64(l), Scalar::Bool(r)) => Scalar::Bool(l.vec_neq(r)), + (Scalar::F64(l), Scalar::I32(r)) => Scalar::Bool(l.vec_neq(r)), + (Scalar::F64(l), Scalar::F64(r)) => Scalar::Bool(l.vec_neq(r)), + (Scalar::NA, _) => Scalar::NA, + (_, Scalar::NA) => Scalar::NA, + (Scalar::INF, Scalar::INF) => Scalar::Bool(ScalarType(false)), + (Scalar::INF, _) => Scalar::Bool(ScalarType(true)), + (_, Scalar::INF) => Scalar::Bool(ScalarType(true)), + (Scalar::NEGINF, Scalar::NEGINF) => Scalar::Bool(ScalarType(false)), + (Scalar::NEGINF, _) => Scalar::Bool(ScalarType(true)), + (_, Scalar::NEGINF) => Scalar::Bool(ScalarType(true)), + _ => todo!(), + } + } +} + +impl VecPartialCmp> for ScalarType +where + L: Atomic + CoercibleInto, + R: Atomic + CoercibleInto, + (L, R): CommonCmp, + C: PartialOrd, +{ + type Output = ScalarType; + + fn vec_gt(self, rhs: ScalarType) -> Self::Output { + let ScalarType(l_inner) = self; + let ScalarType(r_inner) = rhs; + ScalarType( + CoercibleInto::::coerce_into(l_inner) > CoercibleInto::::coerce_into(r_inner), + ) + } + + fn vec_gte(self, rhs: ScalarType) -> Self::Output { + let ScalarType(l_inner) = self; + let ScalarType(r_inner) = rhs; + ScalarType( + CoercibleInto::::coerce_into(l_inner) >= CoercibleInto::::coerce_into(r_inner), + ) + } + + fn vec_lt(self, rhs: ScalarType) -> Self::Output { + let ScalarType(l_inner) = self; + let ScalarType(r_inner) = rhs; + ScalarType( + CoercibleInto::::coerce_into(l_inner) < CoercibleInto::::coerce_into(r_inner), + ) + } + + fn vec_lte(self, rhs: ScalarType) -> Self::Output { + let ScalarType(l_inner) = self; + let ScalarType(r_inner) = rhs; + ScalarType( + CoercibleInto::::coerce_into(l_inner) <= CoercibleInto::::coerce_into(r_inner), + ) + } + + fn vec_eq(self, rhs: ScalarType) -> Self::Output { + let ScalarType(l_inner) = self; + let ScalarType(r_inner) = rhs; + ScalarType( + CoercibleInto::::coerce_into(l_inner) == CoercibleInto::::coerce_into(r_inner), + ) + } + + fn vec_neq(self, rhs: ScalarType) -> Self::Output { + let ScalarType(l_inner) = self; + let ScalarType(r_inner) = rhs; + ScalarType( + CoercibleInto::::coerce_into(l_inner) != CoercibleInto::::coerce_into(r_inner), + ) + } +} diff --git a/src/object/vector/coercion.rs b/src/object/vector/coercion.rs index 934e5d51..c19f0411 100644 --- a/src/object/vector/coercion.rs +++ b/src/object/vector/coercion.rs @@ -2,7 +2,7 @@ use std::str::FromStr; use super::OptionNA; -pub trait AtomicMode { +pub trait Atomic: std::fmt::Debug + Default + Clone { fn is_double() -> bool { false } diff --git a/src/object/vector/core.rs b/src/object/vector/core.rs index 736755dd..efcd3cec 100644 --- a/src/object/vector/core.rs +++ b/src/object/vector/core.rs @@ -4,6 +4,8 @@ use std::fmt::Display; use crate::error::Error; use crate::lang::EvalResult; use crate::object::Obj; +use crate::object::Scalar; +use crate::object::ScalarType; use super::coercion::CoercibleInto; use super::rep::Rep; @@ -17,6 +19,8 @@ pub enum OptionNA { Some(T), } +impl Copy for OptionNA where T: Copy {} + impl PartialOrd for OptionNA where T: PartialOrd, @@ -39,6 +43,13 @@ impl OptionNA { OptionNA::NA => OptionNA::NA, } } + + pub fn unwrap_or(self, default: T) -> T { + match self { + OptionNA::Some(x) => x, + OptionNA::NA => default, + } + } } #[derive(Debug, Clone, PartialEq)] @@ -65,20 +76,70 @@ impl Vector { pub fn try_get(&self, index: Obj) -> EvalResult { let err = Error::Other("Vector index cannot be coerced into a valid indexing type.".to_string()); - match (self, index.as_vector()?) { - (Vector::Double(v), Obj::Vector(i)) => { - Ok(Obj::Vector(Vector::from(v.subset(i.try_into()?)))) - } - (Vector::Integer(v), Obj::Vector(i)) => { - Ok(Obj::Vector(Vector::from(v.subset(i.try_into()?)))) - } - (Vector::Logical(v), Obj::Vector(i)) => { - Ok(Obj::Vector(Vector::from(v.subset(i.try_into()?)))) + + if let Obj::Scalar(s) = index { + match self { + Vector::Double(x) => Ok(Obj::Scalar( + x.subset(s.try_into()?) + .inner() + .clone() + .borrow() + .first() + .map_or(Scalar::NA, |x| match *x { + OptionNA::Some(value) => Scalar::F64(ScalarType(value)), + OptionNA::NA => Scalar::NA, + }), + )), + Vector::Integer(x) => Ok(Obj::Scalar( + x.subset(s.try_into()?) + .inner() + .clone() + .borrow() + .first() + .map_or(Scalar::NA, |x| match *x { + OptionNA::Some(value) => Scalar::I32(ScalarType(value)), + OptionNA::NA => Scalar::NA, + }), + )), + Vector::Logical(x) => Ok(Obj::Scalar( + x.subset(s.try_into()?) + .inner() + .clone() + .borrow() + .first() + .map_or(Scalar::NA, |x| match *x { + OptionNA::Some(value) => Scalar::Bool(ScalarType(value)), + OptionNA::NA => Scalar::NA, + }), + )), + Vector::Character(x) => Ok(Obj::Scalar( + x.subset(s.try_into()?) + .inner() + .clone() + .borrow() + .first() + .map_or(Scalar::NA, |x| match x.clone() { + OptionNA::Some(value) => Scalar::String(ScalarType(value)), + OptionNA::NA => Scalar::NA, + }), + )), } - (Vector::Character(v), Obj::Vector(i)) => { - Ok(Obj::Vector(Vector::from(v.subset(i.try_into()?)))) + } else { + match (self, index.as_vector()?) { + (Vector::Double(v), Obj::Vector(i)) => { + Ok(Obj::Vector(Vector::from(v.subset(i.try_into()?)))) + } + (Vector::Integer(v), Obj::Vector(i)) => { + Ok(Obj::Vector(Vector::from(v.subset(i.try_into()?)))) + } + (Vector::Logical(v), Obj::Vector(i)) => { + Ok(Obj::Vector(Vector::from(v.subset(i.try_into()?)))) + } + (Vector::Character(v), Obj::Vector(i)) => { + Ok(Obj::Vector(Vector::from(v.subset(i.try_into()?)))) + } + _ => Err(err.into()), } - _ => Err(err.into()), } } diff --git a/src/object/vector/rep.rs b/src/object/vector/rep.rs index 445eefc6..96041f13 100644 --- a/src/object/vector/rep.rs +++ b/src/object/vector/rep.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::fmt::{Debug, Display}; use std::rc::Rc; -use super::coercion::{AtomicMode, CoercibleInto, CommonCmp, CommonNum, MinimallyNumeric}; +use super::coercion::{Atomic, CoercibleInto, CommonCmp, CommonNum, MinimallyNumeric}; use super::iterators::{map_common_numeric, zip_recycle}; use super::subset::Subset; use super::subsets::Subsets; @@ -18,13 +18,13 @@ pub enum Rep { // Iter(Box>) } -impl Default for Rep { +impl Default for Rep { fn default() -> Self { Self::new() } } -impl Rep { +impl Rep { /// Create an empty vector /// /// The primary use case for this function is to support testing, and there @@ -272,8 +272,8 @@ impl Rep { /// pub fn vectorized_partial_cmp(self, other: Rep) -> Vec> where - T: AtomicMode + Default + Clone + CoercibleInto, - R: AtomicMode + Default + Clone + CoercibleInto, + T: Atomic + Default + Clone + CoercibleInto, + R: Atomic + Default + Clone + CoercibleInto, (T, R): CommonCmp, C: PartialOrd, { @@ -308,7 +308,7 @@ impl Rep { impl TryInto for Rep> where - OptionNA: AtomicMode + Clone + CoercibleInto>, + OptionNA: Atomic + Clone + CoercibleInto>, { type Error = (); fn try_into(self) -> Result { @@ -391,7 +391,7 @@ where impl Display for Rep where - T: AtomicMode + Debug + Default + Clone, + T: Atomic + Debug + Default + Clone, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let n = self.len(); @@ -456,7 +456,7 @@ where impl std::ops::Neg for Rep where - L: AtomicMode + Default + Clone + MinimallyNumeric + CoercibleInto, + L: Atomic + Default + Clone + MinimallyNumeric + CoercibleInto, LNum: std::ops::Neg, Rep: From>, { @@ -475,8 +475,8 @@ where impl std::ops::Add> for Rep where - L: AtomicMode + Default + Clone + MinimallyNumeric + CoercibleInto, - R: AtomicMode + Default + Clone + MinimallyNumeric + CoercibleInto, + L: Atomic + Default + Clone + MinimallyNumeric + CoercibleInto, + R: Atomic + Default + Clone + MinimallyNumeric + CoercibleInto, (LNum, RNum): CommonNum, C: Clone + std::ops::Add, Rep: From>, @@ -501,8 +501,8 @@ where impl std::ops::Sub> for Rep where - L: AtomicMode + Default + Clone + MinimallyNumeric + CoercibleInto, - R: AtomicMode + Default + Clone + MinimallyNumeric + CoercibleInto, + L: Atomic + Default + Clone + MinimallyNumeric + CoercibleInto, + R: Atomic + Default + Clone + MinimallyNumeric + CoercibleInto, (LNum, RNum): CommonNum, C: std::ops::Sub, Rep: From>, @@ -527,8 +527,8 @@ where impl std::ops::Mul> for Rep where - L: AtomicMode + Default + Clone + MinimallyNumeric + CoercibleInto, - R: AtomicMode + Default + Clone + MinimallyNumeric + CoercibleInto, + L: Atomic + Default + Clone + MinimallyNumeric + CoercibleInto, + R: Atomic + Default + Clone + MinimallyNumeric + CoercibleInto, (LNum, RNum): CommonNum, C: std::ops::Mul, Rep: From>, @@ -553,8 +553,8 @@ where impl std::ops::Div> for Rep where - L: AtomicMode + Default + Clone + MinimallyNumeric + CoercibleInto, - R: AtomicMode + Default + Clone + MinimallyNumeric + CoercibleInto, + L: Atomic + Default + Clone + MinimallyNumeric + CoercibleInto, + R: Atomic + Default + Clone + MinimallyNumeric + CoercibleInto, (LNum, RNum): CommonNum, C: std::ops::Div, Rep: From>, @@ -579,8 +579,8 @@ where impl std::ops::Rem> for Rep where - L: AtomicMode + Default + Clone + MinimallyNumeric + CoercibleInto, - R: AtomicMode + Default + Clone + MinimallyNumeric + CoercibleInto, + L: Atomic + Default + Clone + MinimallyNumeric + CoercibleInto, + R: Atomic + Default + Clone + MinimallyNumeric + CoercibleInto, (LNum, RNum): CommonNum, C: std::ops::Rem, Rep: From>, @@ -605,8 +605,8 @@ where impl Pow> for Rep where - L: AtomicMode + Default + Clone + MinimallyNumeric + CoercibleInto, - R: AtomicMode + Default + Clone + MinimallyNumeric + CoercibleInto, + L: Atomic + Default + Clone + MinimallyNumeric + CoercibleInto, + R: Atomic + Default + Clone + MinimallyNumeric + CoercibleInto, LNum: Pow, Rep: From>, { @@ -630,8 +630,8 @@ where impl std::ops::BitOr> for Rep where - L: AtomicMode + Default + Clone + CoercibleInto, - R: AtomicMode + Default + Clone + CoercibleInto, + L: Atomic + Default + Clone + CoercibleInto, + R: Atomic + Default + Clone + CoercibleInto, Logical: std::ops::BitOr, Rep: From>, { @@ -655,8 +655,8 @@ where impl std::ops::BitAnd> for Rep where - L: AtomicMode + Default + Clone + CoercibleInto, - R: AtomicMode + Default + Clone + CoercibleInto, + L: Atomic + Default + Clone + CoercibleInto, + R: Atomic + Default + Clone + CoercibleInto, Logical: std::ops::BitAnd, Rep: From>, { @@ -680,8 +680,8 @@ where impl VecPartialCmp> for Rep where - L: AtomicMode + Default + Clone + CoercibleInto, - R: AtomicMode + Default + Clone + CoercibleInto, + L: Atomic + Default + Clone + CoercibleInto, + R: Atomic + Default + Clone + CoercibleInto, (L, R): CommonCmp, C: PartialOrd, { diff --git a/src/object/vector/subset.rs b/src/object/vector/subset.rs index b7f9f2de..52d9e351 100644 --- a/src/object/vector/subset.rs +++ b/src/object/vector/subset.rs @@ -2,7 +2,10 @@ use std::cell::RefCell; use std::ops::Range; use std::rc::Rc; -use crate::lang::Signal; +use crate::{ + lang::Signal, + object::{coercion::CoercibleInto, Scalar, ScalarType}, +}; use super::{types::*, OptionNA, Vector}; @@ -13,6 +16,7 @@ use super::{types::*, OptionNA, Vector}; /// #[derive(Debug, Clone, PartialEq)] pub enum Subset { + Index(i32), Indices(Rc>>), Mask(Rc>>), Names(Rc>>), @@ -22,6 +26,13 @@ pub enum Subset { impl Subset { pub fn get_index_at(&self, index: usize) -> Option { match self { + Subset::Index(ind) => { + if index == 1 { + Some(*ind as usize) + } else { + None + } + } Subset::Indices(indices) => indices.clone().borrow().get(index).and_then(|i| match i { OptionNA::Some(i) => Some((*i as usize).saturating_sub(1)), OptionNA::NA => None, @@ -51,6 +62,7 @@ impl Subset { pub fn len(&self) -> usize { match self { + Subset::Index(_) => 1, Subset::Indices(i) => i.clone().borrow().len(), Subset::Range(r) => r.end - r.start, Subset::Mask(_) => usize::MAX, @@ -71,6 +83,7 @@ impl Subset { I: Iterator)> + 'a, { match self.clone() { + Subset::Index(i) => Box::new(iter.nth(i as usize).into_iter()), Subset::Indices(i) => { let l = self.len(); @@ -209,6 +222,26 @@ impl From> for Subset { } } +impl TryFrom for Subset { + type Error = Signal; + fn try_from(value: i32) -> Result { + Ok(Subset::Index(value - 1)) + } +} + +impl TryFrom for Subset { + type Error = Signal; + fn try_from(value: Scalar) -> Result { + use crate::error::Error::*; + match value { + Scalar::I32(ScalarType(x)) => Ok(Subset::Index(x - 1)), + Scalar::Bool(ScalarType(x)) => Subset::try_from(CoercibleInto::::coerce_into(x)), + Scalar::F64(ScalarType(x)) => Subset::try_from(CoercibleInto::::coerce_into(x)), + _ => Err(Signal::Error(CannotBeCoercedToInteger)), + } + } +} + impl TryFrom for Subset { type Error = Signal; fn try_from(value: Vector) -> Result { diff --git a/src/object/vector/types.rs b/src/object/vector/types.rs index fec490c9..950726b2 100644 --- a/src/object/vector/types.rs +++ b/src/object/vector/types.rs @@ -1,29 +1,52 @@ -use super::coercion::AtomicMode; +use super::coercion::Atomic; use super::OptionNA; pub type Double = OptionNA; -impl AtomicMode for Double { +impl Atomic for Double { + fn is_double() -> bool { + true + } +} + +impl Atomic for f64 { fn is_double() -> bool { true } } pub type Integer = OptionNA; -impl AtomicMode for Integer { +impl Atomic for Integer { + fn is_integer() -> bool { + true + } +} + +impl Atomic for i32 { fn is_integer() -> bool { true } } pub type Logical = OptionNA; -impl AtomicMode for Logical { +impl Atomic for Logical { + fn is_logical() -> bool { + true + } +} + +impl Atomic for bool { fn is_logical() -> bool { true } } pub type Character = OptionNA; -impl AtomicMode for Character { +impl Atomic for Character { + fn is_character() -> bool { + true + } +} +impl Atomic for String { fn is_character() -> bool { true } diff --git a/src/parser/core.rs b/src/parser/core.rs index 89cead36..c428bbff 100644 --- a/src/parser/core.rs +++ b/src/parser/core.rs @@ -384,10 +384,10 @@ where { match pair.as_rule().into() { en::Rule::call => Ok((Expr::Null, parse_pairlist(session, parser, pratt, pair)?)), - en::Rule::index => { - let args = parse_pairlist(session, parser, pratt, pair)?; - Ok((Expr::as_primitive(PostfixIndex), args)) - } + // en::Rule::index => { + // let args = parse_pairlist(session, parser, pratt, pair)?; + // Ok((Expr::as_primitive(PostfixIndex), args)) + // } en::Rule::vector_index => Ok(( Expr::as_primitive(PostfixVecIndex), parse_pairlist(session, parser, pratt, pair)?, diff --git a/src/parser/localization/languages.rs b/src/parser/localization/languages.rs index 555cf6d1..29e526af 100644 --- a/src/parser/localization/languages.rs +++ b/src/parser/localization/languages.rs @@ -5,7 +5,6 @@ pub mod en { #[grammar = "grammar/grammar.pest"] pub struct Parser; - use crate::parser::Style; impl From for Style { fn from(rule: Rule) -> Self { match rule {