use gitql_ast::{
date_utils::{is_valid_date_format, is_valid_datetime_format, is_valid_time_format},
enviroment::Enviroment,
expression::{Expression, ExpressionKind, StringExpression, StringValueType},
};
pub enum TypeCheckResult {
Equals,
NotEqualAndCantImplicitCast,
RightSideCasted(Box<dyn Expression>),
LeftSideCasted(Box<dyn Expression>),
}
#[allow(clippy::borrowed_box)]
pub fn are_types_equals(
scope: &Enviroment,
lhs: &Box<dyn Expression>,
rhs: &Box<dyn Expression>,
) -> TypeCheckResult {
let lhs_type = lhs.expr_type(scope);
let rhs_type = rhs.expr_type(scope);
if lhs_type == rhs_type {
return TypeCheckResult::Equals;
}
if lhs_type.is_time() && rhs_type.is_text() && rhs.expression_kind() == ExpressionKind::String {
let expr = rhs.as_any().downcast_ref::<StringExpression>().unwrap();
let string_literal_value = &expr.value;
if !is_valid_time_format(string_literal_value) {
return TypeCheckResult::NotEqualAndCantImplicitCast;
}
return TypeCheckResult::RightSideCasted(Box::new(StringExpression {
value: string_literal_value.to_owned(),
value_type: StringValueType::Time,
}));
}
if lhs_type.is_text() && rhs_type.is_time() && lhs.expression_kind() == ExpressionKind::String {
let expr = lhs.as_any().downcast_ref::<StringExpression>().unwrap();
let string_literal_value = &expr.value;
if !is_valid_time_format(string_literal_value) {
return TypeCheckResult::NotEqualAndCantImplicitCast;
}
return TypeCheckResult::LeftSideCasted(Box::new(StringExpression {
value: string_literal_value.to_owned(),
value_type: StringValueType::Time,
}));
}
if lhs_type.is_date() && rhs_type.is_text() && rhs.expression_kind() == ExpressionKind::String {
let expr = rhs.as_any().downcast_ref::<StringExpression>().unwrap();
let string_literal_value = &expr.value;
if !is_valid_date_format(string_literal_value) {
return TypeCheckResult::NotEqualAndCantImplicitCast;
}
return TypeCheckResult::RightSideCasted(Box::new(StringExpression {
value: string_literal_value.to_owned(),
value_type: StringValueType::Date,
}));
}
if lhs_type.is_text() && rhs_type.is_date() && lhs.expression_kind() == ExpressionKind::String {
let expr = lhs.as_any().downcast_ref::<StringExpression>().unwrap();
let string_literal_value = &expr.value;
if !is_valid_date_format(string_literal_value) {
return TypeCheckResult::NotEqualAndCantImplicitCast;
}
return TypeCheckResult::LeftSideCasted(Box::new(StringExpression {
value: string_literal_value.to_owned(),
value_type: StringValueType::Date,
}));
}
if lhs_type.is_datetime()
&& rhs_type.is_text()
&& rhs.expression_kind() == ExpressionKind::String
{
let expr = rhs.as_any().downcast_ref::<StringExpression>().unwrap();
let string_literal_value = &expr.value;
if !is_valid_datetime_format(string_literal_value) {
return TypeCheckResult::NotEqualAndCantImplicitCast;
}
return TypeCheckResult::RightSideCasted(Box::new(StringExpression {
value: string_literal_value.to_owned(),
value_type: StringValueType::DateTime,
}));
}
if lhs_type.is_text()
&& rhs_type.is_datetime()
&& lhs.expression_kind() == ExpressionKind::String
{
let expr = lhs.as_any().downcast_ref::<StringExpression>().unwrap();
let string_literal_value = &expr.value;
if !is_valid_datetime_format(string_literal_value) {
return TypeCheckResult::NotEqualAndCantImplicitCast;
}
return TypeCheckResult::LeftSideCasted(Box::new(StringExpression {
value: string_literal_value.to_owned(),
value_type: StringValueType::DateTime,
}));
}
TypeCheckResult::NotEqualAndCantImplicitCast
}