use crate::prelude::*;
impl Runtime {
pub fn resolve_obj_to_number(&self, obj: &Obj) -> Option<Number> {
if let Some(number) = obj.evaluate_to_normalized_decimal_number() {
return Some(number);
}
self.get_object_equal_to_normalized_decimal_number(&obj.to_string())
}
pub fn resolve_obj_to_number_resolved(&self, obj: &Obj) -> Option<Number> {
self.resolve_obj_to_number(&self.resolve_obj(obj))
}
pub fn resolve_obj(&self, obj: &Obj) -> Obj {
match obj {
Obj::Number(number) => Obj::Number(number.clone()),
Obj::Add(add) => {
let result = Obj::Add(Add::new(
self.resolve_obj(&add.left),
self.resolve_obj(&add.right),
));
let calculated_result = result.evaluate_to_normalized_decimal_number();
if let Some(calculated_result) = calculated_result {
Obj::Number(calculated_result)
} else {
result
}
}
Obj::Sub(sub) => {
let result = Obj::Sub(Sub::new(
self.resolve_obj(&sub.left),
self.resolve_obj(&sub.right),
));
let calculated_result = result.evaluate_to_normalized_decimal_number();
if let Some(calculated_result) = calculated_result {
Obj::Number(calculated_result)
} else {
result
}
}
Obj::Mul(mul) => {
let result = Obj::Mul(Mul::new(
self.resolve_obj(&mul.left),
self.resolve_obj(&mul.right),
));
let calculated_result = result.evaluate_to_normalized_decimal_number();
if let Some(calculated_result) = calculated_result {
Obj::Number(calculated_result)
} else {
result
}
}
Obj::Mod(mod_obj) => {
let result = Obj::Mod(Mod::new(
self.resolve_obj(&mod_obj.left),
self.resolve_obj(&mod_obj.right),
));
let calculated_result = result.evaluate_to_normalized_decimal_number();
if let Some(calculated_result) = calculated_result {
Obj::Number(calculated_result)
} else {
result
}
}
Obj::Pow(pow) => {
let result = Obj::Pow(Pow::new(
self.resolve_obj(&pow.base),
self.resolve_obj(&pow.exponent),
));
let calculated_result = result.evaluate_to_normalized_decimal_number();
if let Some(calculated_result) = calculated_result {
Obj::Number(calculated_result)
} else {
result
}
}
Obj::Div(div) => {
let result = Obj::Div(Div::new(
self.resolve_obj(&div.left),
self.resolve_obj(&div.right),
));
let calculated_result = result.evaluate_to_normalized_decimal_number();
if let Some(calculated_result) = calculated_result {
Obj::Number(calculated_result)
} else {
result
}
}
Obj::Identifier(_)
| Obj::IdentifierWithMod(_)
| Obj::FieldAccess(_)
| Obj::FieldAccessWithMod(_)
| Obj::FnObj(_) => {
if let Some(number) = self.resolve_obj_to_number(obj) {
Obj::Number(number)
} else {
obj.clone()
}
}
Obj::Count(count) => match &*count.set {
Obj::ListSet(list_set) => Obj::Number(Number::new(list_set.list.len().to_string())),
_ => obj.clone(),
},
Obj::TupleDim(dim) => match &*dim.arg {
Obj::Tuple(tuple) => Obj::Number(Number::new(tuple.args.len().to_string())),
_ => obj.clone(),
},
Obj::CartDim(cart_dim) => match &*cart_dim.set {
Obj::Cart(cart) => Obj::Number(Number::new(cart.args.len().to_string())),
_ => obj.clone(),
},
Obj::Proj(proj) => match &*proj.set {
Obj::Cart(cart) => {
let projection_index_number = self.resolve_obj_to_number(&proj.dim);
if let Some(projection_index_number) = projection_index_number {
let projection_index_parsed_result =
projection_index_number.normalized_value.parse::<usize>();
if let Ok(projection_index_one_based) = projection_index_parsed_result {
if projection_index_one_based >= 1
&& projection_index_one_based <= cart.args.len()
{
return (*cart.args[projection_index_one_based - 1]).clone();
}
}
}
obj.clone()
}
_ => {
let known_cart_obj = self.get_object_equal_to_cart(&proj.set.to_string());
if let Some(known_cart_obj) = known_cart_obj {
let projection_index_number = self.resolve_obj_to_number(&proj.dim);
if let Some(projection_index_number) = projection_index_number {
let projection_index_parsed_result =
projection_index_number.normalized_value.parse::<usize>();
if let Ok(projection_index_one_based) = projection_index_parsed_result {
if projection_index_one_based >= 1
&& projection_index_one_based <= known_cart_obj.args.len()
{
return (*known_cart_obj.args[projection_index_one_based - 1])
.clone();
}
}
}
}
obj.clone()
}
},
Obj::ObjAtIndex(obj_at_index) => match &*obj_at_index.obj {
Obj::Tuple(tuple) => {
let tuple_index_number = self.resolve_obj_to_number(&obj_at_index.index);
if let Some(tuple_index_number) = tuple_index_number {
let tuple_index_parsed_result =
tuple_index_number.normalized_value.parse::<usize>();
if let Ok(tuple_index_one_based) = tuple_index_parsed_result {
if tuple_index_one_based >= 1
&& tuple_index_one_based <= tuple.args.len()
{
return (*tuple.args[tuple_index_one_based - 1]).clone();
}
}
}
obj.clone()
}
_ => {
let known_tuple_obj =
self.get_obj_equal_to_tuple(&obj_at_index.obj.to_string());
if let Some(known_tuple_obj) = known_tuple_obj {
let tuple_index_number = self.resolve_obj_to_number(&obj_at_index.index);
if let Some(tuple_index_number) = tuple_index_number {
let tuple_index_parsed_result =
tuple_index_number.normalized_value.parse::<usize>();
if let Ok(tuple_index_one_based) = tuple_index_parsed_result {
if tuple_index_one_based >= 1
&& tuple_index_one_based <= known_tuple_obj.args.len()
{
return (*known_tuple_obj.args[tuple_index_one_based - 1])
.clone();
}
}
}
}
obj.clone()
}
},
_ => obj.clone(),
}
}
}