From 6fec57311ac42ffea3e1a013c83a21d82e8435f5 Mon Sep 17 00:00:00 2001 From: Alex Ivliev Date: Mon, 13 Jan 2025 10:45:29 +0100 Subject: [PATCH 1/3] add cast to iri function --- nemo-physical/src/function/definitions.rs | 3 +++ .../src/function/definitions/casting.rs | 24 +++++++++++++++++++ nemo-physical/src/function/evaluation.rs | 3 +++ nemo-physical/src/function/tree.rs | 12 +++++++++- .../planning/operations/operation.rs | 1 + .../term/operation/operation_kind.rs | 7 +++++- nemo/src/syntax.rs | 4 +++- 7 files changed, 51 insertions(+), 3 deletions(-) diff --git a/nemo-physical/src/function/definitions.rs b/nemo-physical/src/function/definitions.rs index 4e51c61ba..88515b0da 100644 --- a/nemo-physical/src/function/definitions.rs +++ b/nemo-physical/src/function/definitions.rs @@ -8,6 +8,7 @@ pub(crate) mod language; pub(crate) mod numeric; pub(crate) mod string; +use casting::CastingIntoIri; use delegate::delegate; use crate::{ @@ -132,6 +133,7 @@ pub enum UnaryFunctionEnum { CastingIntoInteger64(CastingIntoInteger64), CastingIntoDouble(CastingIntoDouble), CastingIntoFloat(CastingIntoFloat), + CastingIntoIri(CastingIntoIri), CheckIsDouble(CheckIsDouble), CheckIsFloat(CheckIsFloat), CheckIsInteger(CheckIsInteger), @@ -167,6 +169,7 @@ impl UnaryFunction for UnaryFunctionEnum { Self::CastingIntoInteger64(function) => function, Self::CastingIntoFloat(function) => function, Self::CastingIntoDouble(function) => function, + Self::CastingIntoIri(function) => function, Self::CheckIsDouble(function) => function, Self::CheckIsFloat(function) => function, Self::CheckIsInteger(function) => function, diff --git a/nemo-physical/src/function/definitions/casting.rs b/nemo-physical/src/function/definitions/casting.rs index a5a52ba64..ffd4b227a 100644 --- a/nemo-physical/src/function/definitions/casting.rs +++ b/nemo-physical/src/function/definitions/casting.rs @@ -197,3 +197,27 @@ impl UnaryFunction for CastingIntoDouble { FunctionTypePropagation::KnownOutput(StorageTypeName::Double.bitset()) } } + +/// Casting of a string value into an IRI +/// +/// Returns am IRI with the same content as the given string. +/// +/// Returns `None` when called on values other than plain strings. +#[derive(Debug, Copy, Clone)] +pub struct CastingIntoIri; +impl UnaryFunction for CastingIntoIri { + fn evaluate(&self, parameter: AnyDataValue) -> Option { + parameter + .to_plain_string() + .or_else(|| parameter.to_iri()) + .map(AnyDataValue::new_iri) + } + + fn type_propagation(&self) -> FunctionTypePropagation { + FunctionTypePropagation::KnownOutput( + StorageTypeName::Id32 + .bitset() + .union(StorageTypeName::Id64.bitset()), + ) + } +} diff --git a/nemo-physical/src/function/evaluation.rs b/nemo-physical/src/function/evaluation.rs index 84ad35313..128d7d710 100644 --- a/nemo-physical/src/function/evaluation.rs +++ b/nemo-physical/src/function/evaluation.rs @@ -873,6 +873,9 @@ mod test { let tree_to_double = Function::casting_to_double(Function::constant(any_int(4))); evaluate_expect(&tree_to_double, Some(any_double(4.0))); + + let tree_to_iri = Function::casting_to_iri(Function::constant(any_string("test"))); + evaluate_expect(&tree_to_iri, Some(any_iri("test"))); } #[test] diff --git a/nemo-physical/src/function/tree.rs b/nemo-physical/src/function/tree.rs index 4717e2ab5..47178db49 100644 --- a/nemo-physical/src/function/tree.rs +++ b/nemo-physical/src/function/tree.rs @@ -7,7 +7,7 @@ use crate::datavalues::AnyDataValue; use super::{ definitions::{ boolean::{BooleanConjunction, BooleanDisjunction, BooleanNegation}, - casting::{CastingIntoDouble, CastingIntoFloat, CastingIntoInteger64}, + casting::{CastingIntoDouble, CastingIntoFloat, CastingIntoInteger64, CastingIntoIri}, checktype::{ CheckIsDouble, CheckIsFloat, CheckIsInteger, CheckIsIri, CheckIsNull, CheckIsNumeric, CheckIsString, @@ -374,6 +374,16 @@ where ) } + /// Create a tree node representing casting a plain string value into an IRI. + /// + /// This evaluates to an IRI with the same content as `sub`. + pub fn casting_to_iri(sub: Self) -> Self { + Self::Unary( + UnaryFunctionEnum::CastingIntoIri(CastingIntoIri), + Box::new(sub), + ) + } + /// Create a tree node representing addition between numbers. /// /// This evaluates to the sum of the values of the diff --git a/nemo/src/execution/planning/operations/operation.rs b/nemo/src/execution/planning/operations/operation.rs index 72d934d29..2765a4026 100644 --- a/nemo/src/execution/planning/operations/operation.rs +++ b/nemo/src/execution/planning/operations/operation.rs @@ -103,6 +103,7 @@ pub(crate) fn operation_to_function_tree( OperationKind::CastToDouble => unary!(casting_to_double, sub), OperationKind::CastToFloat => unary!(casting_to_float, sub), OperationKind::CastToInteger => unary!(casting_to_integer64, sub), + OperationKind::CastToIRI => unary!(casting_to_iri, sub), OperationKind::CanonicalString => unary!(canonical_string, sub), OperationKind::CheckIsInteger => unary!(check_is_integer, sub), OperationKind::CheckIsFloat => unary!(check_is_float, sub), diff --git a/nemo/src/rule_model/components/term/operation/operation_kind.rs b/nemo/src/rule_model/components/term/operation/operation_kind.rs index 533fc09f0..db02acbbf 100644 --- a/nemo/src/rule_model/components/term/operation/operation_kind.rs +++ b/nemo/src/rule_model/components/term/operation/operation_kind.rs @@ -196,6 +196,11 @@ pub enum OperationKind { #[assoc(num_arguments = OperationNumArguments::Unary)] #[assoc(return_type = ValueType::Number)] CastToInteger, + /// Cast to IRI + #[assoc(name = function::IRI)] + #[assoc(num_arguments = OperationNumArguments::Unary)] + #[assoc(return_type = ValueType::Constant)] + CastToIRI, /// Canonical string representation of a value #[assoc(name = function::FULLSTR)] #[assoc(num_arguments = OperationNumArguments::Unary)] @@ -267,7 +272,7 @@ pub enum OperationKind { #[assoc(return_type = ValueType::Number)] NumericFloor, /// Additive inverse of a numeric value - #[assoc(name = function::INVERSE)] + #[assoc(name = function::INVERTSIGN)] #[assoc(num_arguments = OperationNumArguments::Unary)] #[assoc(return_type = ValueType::Number)] NumericNegation, diff --git a/nemo/src/syntax.rs b/nemo/src/syntax.rs index 39ea06f8a..fd942c4a1 100644 --- a/nemo/src/syntax.rs +++ b/nemo/src/syntax.rs @@ -264,6 +264,8 @@ pub mod builtin { pub(crate) const DOUBLE: &str = "DOUBLE"; /// Convert the value to a 32bit floating point number pub(crate) const FLOAT: &str = "FLOAT"; + /// Convert a plain string into an IRI + pub(crate) const IRI: &str = "IRI"; /// Compute the logarithm of the numerical value pub(crate) const LOGARITHM: &str = "LOG"; /// Raise the numerical value to a power @@ -307,7 +309,7 @@ pub mod builtin { /// Compute the quotient of two numeric values pub(crate) const DIVISION: &str = "DIVISION"; /// Compute the multiplicative inverse of a numeric value - pub(crate) const INVERSE: &str = "INVERSE"; + pub(crate) const INVERTSIGN: &str = "INVERTSIGN"; /// Compute the logical and between boolean values pub(crate) const AND: &str = "AND"; /// Compute the logical or between boolean values From 1009712101dfbed8ffa28ee4c644df3544032381 Mon Sep 17 00:00:00 2001 From: Alex Ivliev Date: Mon, 13 Jan 2025 10:45:36 +0100 Subject: [PATCH 2/3] add test case --- resources/testcases/arithmetic/builtins.rls | 10 ++++++---- resources/testcases/arithmetic/builtins/result.csv | 3 +++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/resources/testcases/arithmetic/builtins.rls b/resources/testcases/arithmetic/builtins.rls index cebf7d31c..4e6ba1000 100644 --- a/resources/testcases/arithmetic/builtins.rls +++ b/resources/testcases/arithmetic/builtins.rls @@ -5,8 +5,8 @@ strings("Hello", "World"). doubles(2.0E0, 1.5E0, 0.5E0). integers(1, 2, 3). tagged("test"@en). -iri(constant). -null(!V) :- iri(?X). +constant(constant). +null(!V) :- constant(?X). @import uri_strings :- csv{resource="sources/uri_strings.csv"}. % Datatype check @@ -15,7 +15,7 @@ result(isint, ?R) :- integers(?A, _, _), ?R = isInteger(?A). result(isfloat, ?R) :- doubles(?A, _, _), ?R = isFloat(?A). result(isdouble, ?R) :- doubles(?A, _, _), ?R = isDouble(?A). result(isnumeric, ?R) :- integers(?A, _, _), ?R = isNumeric(?A). -result(isiri, ?R) :- iri(?A), ?R = isIri(?A). +result(isiri, ?R) :- constant(?A), ?R = isIri(?A). result(isnull, ?R) :- null(?A), ?R = isNull(?A). % String representation @@ -31,17 +31,19 @@ result(fullstring, ?R) :- tagged(?A), ?R = fullStr(?A). % Get language tag result(tag, ?R) :- tagged(?L), ?R = LANG(?L). -% Numeric casts +% Casts cast(3.0). cast(4.2). cast(5). cast(test). cast("2023"^^xsd:gYear). cast("40"). +cast("https://example.org"). result(int, ?R) :- cast(?A), ?R = INT(?A). result(float, ?R) :- cast(?A), ?R = FLOAT(?A). result(double, ?R) :- cast(?A), ?R = DOUBLE(?A). +result(iri, ?R) :- cast(?A), ?R = IRI(?A). % Cast within numeric operations diff --git a/resources/testcases/arithmetic/builtins/result.csv b/resources/testcases/arithmetic/builtins/result.csv index 51e558c43..6cbf1ff9f 100644 --- a/resources/testcases/arithmetic/builtins/result.csv +++ b/resources/testcases/arithmetic/builtins/result.csv @@ -26,6 +26,9 @@ double,"""4.2""^^" double,"""5""^^" double,"""40""^^" double,"""2023""^^" +iri,https://example.org +iri,40 +iri,test mixedsum,"""6.5""^^" round,5 round,"""3""^^" From 4cea76af9848bc6e9090361e06e014a571c31e3b Mon Sep 17 00:00:00 2001 From: Alex Ivliev Date: Mon, 13 Jan 2025 13:18:06 +0100 Subject: [PATCH 3/3] fix typo --- nemo-physical/src/function/definitions/casting.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nemo-physical/src/function/definitions/casting.rs b/nemo-physical/src/function/definitions/casting.rs index ffd4b227a..9e362d061 100644 --- a/nemo-physical/src/function/definitions/casting.rs +++ b/nemo-physical/src/function/definitions/casting.rs @@ -200,7 +200,7 @@ impl UnaryFunction for CastingIntoDouble { /// Casting of a string value into an IRI /// -/// Returns am IRI with the same content as the given string. +/// Returns an IRI with the same content as the given string. /// /// Returns `None` when called on values other than plain strings. #[derive(Debug, Copy, Clone)]