Skip to content

Commit

Permalink
Vitaly's fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Innokenty committed Nov 8, 2024
1 parent 9eb027b commit bbc8cca
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 30 deletions.
4 changes: 2 additions & 2 deletions lib/src/metta/runner/stdlib.metta
Original file line number Diff line number Diff line change
Expand Up @@ -418,13 +418,13 @@
(@doc min-atom
(@desc "Returns atom with min value in the expression (first argument). Only numbers allowed")
(@params (
(@param "Expression")))
(@param "Expression which contains atoms of Number type")))
(@return "Min value in the expression. Error if expression contains non-numeric value or is empty"))

(@doc max-atom
(@desc "Returns atom with max value in the expression (first argument). Only numbers allowed")
(@params (
(@param "Expression")))
(@param "Expression which contains atoms of Number type")))
(@return "Max value in the expression. Error if expression contains non-numeric value or is empty"))

(@doc size-atom
Expand Down
50 changes: 26 additions & 24 deletions lib/src/metta/runner/stdlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1167,7 +1167,7 @@ grounded_op!(MaxAtomOp, "max-atom");

impl Grounded for MaxAtomOp {
fn type_(&self) -> Atom {
Atom::expr([ARROW_SYMBOL, ATOM_TYPE_EXPRESSION, ATOM_TYPE_ATOM])
Atom::expr([ARROW_SYMBOL, ATOM_TYPE_EXPRESSION, ATOM_TYPE_NUMBER])
}

fn as_execute(&self) -> Option<&dyn CustomExecute> {
Expand All @@ -1179,16 +1179,17 @@ impl CustomExecute for MaxAtomOp {
fn execute(&self, args: &[Atom]) -> Result<Vec<Atom>, ExecError> {
let arg_error = || ExecError::from("max-atom expects one argument: expression");
let children = TryInto::<&ExpressionAtom>::try_into(args.get(0).ok_or_else(arg_error)?)?.children();
for x in children.iter() {
match AsPrimitive::from_atom(x).as_number() {
None => Err(ExecError::from("Only numbers allowed in expression")),
_ => Ok({}),
}?
};
match children.into_iter().map(|x| Into::<f64>::into(AsPrimitive::from_atom(x).as_number().unwrap())).reduce(f64::max) {
Some(max) => Ok(vec![Atom::gnd(Number::Float(max))]),
None => Err(ExecError::from("Empty expression")),
}
if children.is_empty() {
Err(ExecError::from("Empty expression"))
} else {
children.into_iter().fold(Ok(f64::NEG_INFINITY), |res, x| {
match (res, AsPrimitive::from_atom(x).as_number()) {
(res @ Err(_), _) => res,
(_, None) => Err(ExecError::from("Only numbers are allowed in expression")),
(Ok(max), Some(x)) => Ok(f64::max(max, x.into())),
}
})
}.map(|max| vec![Atom::gnd(Number::Float(max))])
}
}

Expand All @@ -1199,7 +1200,7 @@ grounded_op!(MinAtomOp, "min-atom");

impl Grounded for MinAtomOp {
fn type_(&self) -> Atom {
Atom::expr([ARROW_SYMBOL, ATOM_TYPE_EXPRESSION, ATOM_TYPE_ATOM])
Atom::expr([ARROW_SYMBOL, ATOM_TYPE_EXPRESSION, ATOM_TYPE_NUMBER])
}

fn as_execute(&self) -> Option<&dyn CustomExecute> {
Expand All @@ -1211,16 +1212,17 @@ impl CustomExecute for MinAtomOp {
fn execute(&self, args: &[Atom]) -> Result<Vec<Atom>, ExecError> {
let arg_error = || ExecError::from("min-atom expects one argument: expression");
let children = TryInto::<&ExpressionAtom>::try_into(args.get(0).ok_or_else(arg_error)?)?.children();
for x in children.iter() {
match AsPrimitive::from_atom(x).as_number() {
None => Err(ExecError::from("Only numbers allowed in expression")),
_ => Ok({}),
}?
};
match children.into_iter().map(|x| Into::<f64>::into(AsPrimitive::from_atom(x).as_number().unwrap())).reduce(f64::min) {
Some(min) => Ok(vec![Atom::gnd(Number::Float(min))]),
None => Err(ExecError::from("Empty expression")),
}
if children.is_empty() {
Err(ExecError::from("Empty expression"))
} else {
children.into_iter().fold(Ok(f64::INFINITY), |res, x| {
match (res, AsPrimitive::from_atom(x).as_number()) {
(res @ Err(_), _) => res,
(_, None) => Err(ExecError::from("Only numbers are allowed in expression")),
(Ok(min), Some(x)) => Ok(f64::min(min, x.into())),
}
})
}.map(|min| vec![Atom::gnd(Number::Float(min))])
}
}

Expand Down Expand Up @@ -2160,7 +2162,7 @@ mod tests {
let res = MinAtomOp{}.execute(&mut vec![expr!({Number::Integer(5)} {Number::Integer(4)} {Number::Float(5.5)})]).expect("No result returned");
assert_eq!(res, vec![expr!({Number::Integer(4)})]);
let res = MinAtomOp{}.execute(&mut vec![expr!({Number::Integer(5)} {Number::Integer(4)} "A")]);
assert_eq!(res, Err(ExecError::from("Only numbers allowed in expression")));
assert_eq!(res, Err(ExecError::from("Only numbers are allowed in expression")));
let res = MinAtomOp{}.execute(&mut vec![expr!()]);
assert_eq!(res, Err(ExecError::from("Empty expression")));
}
Expand All @@ -2170,7 +2172,7 @@ mod tests {
let res = MaxAtomOp{}.execute(&mut vec![expr!({Number::Integer(5)} {Number::Integer(4)} {Number::Float(5.5)})]).expect("No result returned");
assert_eq!(res, vec![expr!({Number::Float(5.5)})]);
let res = MaxAtomOp{}.execute(&mut vec![expr!({Number::Integer(5)} {Number::Integer(4)} "A")]);
assert_eq!(res, Err(ExecError::from("Only numbers allowed in expression")));
assert_eq!(res, Err(ExecError::from("Only numbers are allowed in expression")));
let res = MaxAtomOp{}.execute(&mut vec![expr!()]);
assert_eq!(res, Err(ExecError::from("Empty expression")));
}
Expand Down
4 changes: 2 additions & 2 deletions lib/src/metta/runner/stdlib_minimal.metta
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,13 @@
(@doc min-atom
(@desc "Returns atom with min value in the expression (first argument). Only numbers allowed")
(@params (
(@param "Expression")))
(@param "Expression which contains atoms of Number type")))
(@return "Min value in the expression. Error if expression contains non-numeric value or is empty"))

(@doc max-atom
(@desc "Returns atom with max value in the expression (first argument). Only numbers allowed")
(@params (
(@param "Expression")))
(@param "Expression which contains atoms of Number type")))
(@return "Max value in the expression. Error if expression contains non-numeric value or is empty"))

(@doc size-atom
Expand Down
4 changes: 2 additions & 2 deletions lib/src/metta/runner/stdlib_minimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,14 +633,14 @@ mod tests {
fn metta_min_atom() {
assert_eq!(run_program(&format!("!(min-atom (5 4 5.5))")), Ok(vec![vec![expr!({Number::Integer(4)})]]));
assert_eq!(run_program(&format!("!(min-atom ())")), Ok(vec![vec![expr!("Error" ({ stdlib::MinAtomOp{} } ()) "Empty expression")]]));
assert_eq!(run_program(&format!("!(min-atom (3 A B 5))")), Ok(vec![vec![expr!("Error" ({ stdlib::MinAtomOp{} } ({Number::Integer(3)} "A" "B" {Number::Integer(5)})) "Only numbers allowed in expression")]]));
assert_eq!(run_program(&format!("!(min-atom (3 A B 5))")), Ok(vec![vec![expr!("Error" ({ stdlib::MinAtomOp{} } ({Number::Integer(3)} "A" "B" {Number::Integer(5)})) "Only numbers are allowed in expression")]]));
}

#[test]
fn metta_max_atom() {
assert_eq!(run_program(&format!("!(max-atom (5 4 5.5))")), Ok(vec![vec![expr!({Number::Float(5.5)})]]));
assert_eq!(run_program(&format!("!(max-atom ())")), Ok(vec![vec![expr!("Error" ({ stdlib::MaxAtomOp{} } ()) "Empty expression")]]));
assert_eq!(run_program(&format!("!(max-atom (3 A B 5))")), Ok(vec![vec![expr!("Error" ({ stdlib::MaxAtomOp{} } ({Number::Integer(3)} "A" "B" {Number::Integer(5)})) "Only numbers allowed in expression")]]));
assert_eq!(run_program(&format!("!(max-atom (3 A B 5))")), Ok(vec![vec![expr!("Error" ({ stdlib::MaxAtomOp{} } ({Number::Integer(3)} "A" "B" {Number::Integer(5)})) "Only numbers are allowed in expression")]]));
}

#[test]
Expand Down

0 comments on commit bbc8cca

Please sign in to comment.