mirror of
https://github.com/PaddiM8/kalker.git
synced 2024-12-12 09:30:40 +01:00
Began adding rationals
This commit is contained in:
parent
1cbc5004d5
commit
e9ae651572
@ -184,9 +184,11 @@ pub fn convert_unit(
|
|||||||
.symbol_table
|
.symbol_table
|
||||||
.insert(Stmt::VarDecl(DECL_UNIT.into(), Box::new(expr.clone())));
|
.insert(Stmt::VarDecl(DECL_UNIT.into(), Box::new(expr.clone())));
|
||||||
|
|
||||||
Ok(KalkNum::new(
|
let num = eval_expr(context, &unit_def, "")?;
|
||||||
eval_expr(context, &unit_def, "")?.value,
|
Ok(KalkNum::new_with_rational(
|
||||||
|
num.clone().value,
|
||||||
to_unit.into(),
|
to_unit.into(),
|
||||||
|
num.get_internal_rational(),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
Err(CalcError::InvalidUnit)
|
Err(CalcError::InvalidUnit)
|
||||||
@ -243,7 +245,7 @@ fn eval_fn_call_expr(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some((result, func_unit)) = prelude_func {
|
if let Some((result, func_unit)) = prelude_func {
|
||||||
return Ok(KalkNum::new(
|
return Ok(KalkNum::new_without_rational(
|
||||||
result,
|
result,
|
||||||
if unit.len() > 0 { unit } else { &func_unit },
|
if unit.len() > 0 { unit } else { &func_unit },
|
||||||
));
|
));
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
use crate::ast::Expr;
|
use crate::ast::Expr;
|
||||||
use rug::ops::Pow;
|
use rug::ops::Pow;
|
||||||
use rug::Float;
|
use rug::Float;
|
||||||
|
use rug::Rational;
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Clone)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub struct KalkNum {
|
pub struct KalkNum {
|
||||||
pub(crate) value: Float,
|
pub(crate) value: Float,
|
||||||
pub(crate) unit: String,
|
pub(crate) unit: String,
|
||||||
|
rational: Option<Rational>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ScientificNotation {
|
pub struct ScientificNotation {
|
||||||
@ -34,8 +36,25 @@ impl ScientificNotation {
|
|||||||
impl KalkNum {
|
impl KalkNum {
|
||||||
pub fn new(value: Float, unit: &str) -> Self {
|
pub fn new(value: Float, unit: &str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value,
|
value: value.clone(),
|
||||||
unit: unit.to_string(),
|
unit: unit.to_string(),
|
||||||
|
rational: value.to_rational(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn new_with_rational(value: Float, unit: &str, rational: Option<Rational>) -> Self {
|
||||||
|
Self {
|
||||||
|
value: value.clone(),
|
||||||
|
unit: unit.to_string(),
|
||||||
|
rational: rational,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_without_rational(value: Float, unit: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
value: value.clone(),
|
||||||
|
unit: unit.to_string(),
|
||||||
|
rational: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,6 +87,16 @@ impl KalkNum {
|
|||||||
&self.unit
|
&self.unit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_rational(self) -> Option<(i64, i64)> {
|
||||||
|
let (numer, denom) = self.rational?.into_numer_denom();
|
||||||
|
|
||||||
|
Some((numer.to_i64()?, denom.to_i64()?))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_internal_rational(self) -> Option<Rational> {
|
||||||
|
self.rational
|
||||||
|
}
|
||||||
|
|
||||||
pub fn has_unit(&self) -> bool {
|
pub fn has_unit(&self) -> bool {
|
||||||
self.unit.len() > 0
|
self.unit.len() > 0
|
||||||
}
|
}
|
||||||
@ -109,32 +138,52 @@ impl KalkNum {
|
|||||||
|
|
||||||
pub fn add(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
|
pub fn add(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
|
||||||
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
||||||
KalkNum::new(self.value + right.value, &right.unit)
|
let mut num = KalkNum::new_without_rational(self.value + right.value, &right.unit);
|
||||||
|
if let (Some(left_rational), Some(right_rational)) = (self.rational, right.rational) {
|
||||||
|
num.rational = Some(left_rational + right_rational);
|
||||||
|
};
|
||||||
|
|
||||||
|
num
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sub(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
|
pub fn sub(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
|
||||||
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
||||||
KalkNum::new(self.value - right.value, &right.unit)
|
let mut num = KalkNum::new_without_rational(self.value - right.value, &right.unit);
|
||||||
|
if let (Some(left_rational), Some(right_rational)) = (self.rational, right.rational) {
|
||||||
|
num.rational = Some(left_rational - right_rational);
|
||||||
|
};
|
||||||
|
|
||||||
|
num
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mul(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
|
pub fn mul(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
|
||||||
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
||||||
KalkNum::new(self.value * right.value, &right.unit)
|
let mut num = KalkNum::new_without_rational(self.value * right.value, &right.unit);
|
||||||
|
if let (Some(left_rational), Some(right_rational)) = (self.rational, right.rational) {
|
||||||
|
num.rational = Some(left_rational * right_rational);
|
||||||
|
};
|
||||||
|
|
||||||
|
num
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn div(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
|
pub fn div(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
|
||||||
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
||||||
KalkNum::new(self.value / right.value, &right.unit)
|
let mut num = KalkNum::new_without_rational(self.value / right.value, &right.unit);
|
||||||
|
if let (Some(left_rational), Some(right_rational)) = (self.rational, right.rational) {
|
||||||
|
num.rational = Some(left_rational / right_rational);
|
||||||
|
};
|
||||||
|
|
||||||
|
num
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rem(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
|
pub fn rem(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
|
||||||
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
||||||
KalkNum::new(self.value % right.value, &right.unit)
|
KalkNum::new_without_rational(self.value % right.value, &right.unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pow(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
|
pub fn pow(self, context: &mut crate::interpreter::Context, rhs: KalkNum) -> KalkNum {
|
||||||
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
|
||||||
KalkNum::new(self.value.pow(right.value), &right.unit)
|
KalkNum::new_without_rational(self.value.pow(right.value), &right.unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +195,11 @@ fn calculate_unit(
|
|||||||
if left.has_unit() && right.has_unit() {
|
if left.has_unit() && right.has_unit() {
|
||||||
right.convert_to_unit(context, &left.unit)
|
right.convert_to_unit(context, &left.unit)
|
||||||
} else {
|
} else {
|
||||||
Some(KalkNum::new(right.value, &left.unit))
|
Some(KalkNum::new_with_rational(
|
||||||
|
right.value,
|
||||||
|
&left.unit,
|
||||||
|
right.rational,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,12 @@ pub fn eval(parser: &mut parser::Context, input: &str) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
println!("{} {}", result_str, result.get_unit());
|
println!("{} {}", result_str, result.get_unit());
|
||||||
|
|
||||||
|
if result_str.contains(".") {
|
||||||
|
if let Some((numer, denom)) = result.get_rational() {
|
||||||
|
println!("{}/{}", numer, denom);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(None) => print!(""),
|
Ok(None) => print!(""),
|
||||||
Err(err) => print_calc_err(err),
|
Err(err) => print_calc_err(err),
|
||||||
|
Loading…
Reference in New Issue
Block a user