Skip to content

Commit

Permalink
feat: implement Bitwise xor operator
Browse files Browse the repository at this point in the history
  • Loading branch information
AmrDeveloper committed Jun 28, 2024
1 parent a3308bf commit 8db2443
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 82 deletions.
21 changes: 12 additions & 9 deletions crates/gitql-ast/src/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use gitql_core::types::DataType;
use gitql_core::value::Value;

use crate::operator::ArithmeticOperator;
use crate::operator::BitwiseOperator;
use crate::operator::BinaryBitwiseOperator;
use crate::operator::BinaryLogicalOperator;
use crate::operator::ComparisonOperator;
use crate::operator::LogicalOperator;
use crate::operator::PrefixUnaryOperator;

#[derive(PartialEq)]
Expand Down Expand Up @@ -47,7 +47,10 @@ impl dyn Expression {
pub fn is_const(&self) -> bool {
matches!(
self.kind(),
ExpressionKind::Number | ExpressionKind::Boolean | ExpressionKind::String
ExpressionKind::Number
| ExpressionKind::Boolean
| ExpressionKind::String
| ExpressionKind::Null
)
}
}
Expand Down Expand Up @@ -212,21 +215,21 @@ impl Expression for BooleanExpression {
}
}

pub struct PrefixUnary {
pub struct UnaryExpression {
pub right: Box<dyn Expression>,
pub op: PrefixUnaryOperator,
}

impl Expression for PrefixUnary {
impl Expression for UnaryExpression {
fn kind(&self) -> ExpressionKind {
ExpressionKind::PrefixUnary
}

fn expr_type(&self, _scope: &Environment) -> DataType {
fn expr_type(&self, scope: &Environment) -> DataType {
if self.op == PrefixUnaryOperator::Bang {
DataType::Boolean
} else {
DataType::Integer
self.right.expr_type(scope)
}
}

Expand Down Expand Up @@ -381,7 +384,7 @@ impl Expression for GlobExpression {

pub struct LogicalExpression {
pub left: Box<dyn Expression>,
pub operator: LogicalOperator,
pub operator: BinaryLogicalOperator,
pub right: Box<dyn Expression>,
}

Expand All @@ -401,7 +404,7 @@ impl Expression for LogicalExpression {

pub struct BitwiseExpression {
pub left: Box<dyn Expression>,
pub operator: BitwiseOperator,
pub operator: BinaryBitwiseOperator,
pub right: Box<dyn Expression>,
}

Expand Down
5 changes: 3 additions & 2 deletions crates/gitql-ast/src/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pub enum PrefixUnaryOperator {
Minus,
Bang,
Not,
}

#[derive(PartialEq)]
Expand All @@ -25,14 +26,14 @@ pub enum ComparisonOperator {
}

#[derive(PartialEq)]
pub enum LogicalOperator {
pub enum BinaryLogicalOperator {
Or,
And,
Xor,
}

#[derive(PartialEq)]
pub enum BitwiseOperator {
pub enum BinaryBitwiseOperator {
Or,
And,
RightShift,
Expand Down
33 changes: 19 additions & 14 deletions crates/gitql-engine/src/engine_evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,23 @@ use gitql_ast::expression::IsNullExpression;
use gitql_ast::expression::LikeExpression;
use gitql_ast::expression::LogicalExpression;
use gitql_ast::expression::NumberExpression;
use gitql_ast::expression::PrefixUnary;
use gitql_ast::expression::RegexExpression;
use gitql_ast::expression::SliceExpression;
use gitql_ast::expression::StringExpression;
use gitql_ast::expression::StringValueType;
use gitql_ast::expression::SymbolExpression;
use gitql_ast::expression::UnaryExpression;
use gitql_ast::operator::ArithmeticOperator;
use gitql_ast::operator::BitwiseOperator;
use gitql_ast::operator::BinaryBitwiseOperator;
use gitql_ast::operator::BinaryLogicalOperator;
use gitql_ast::operator::ComparisonOperator;
use gitql_ast::operator::LogicalOperator;
use gitql_ast::operator::PrefixUnaryOperator;
use gitql_core::environment::Environment;
use gitql_core::types::DataType;
use gitql_core::value::Value;

use regex::Regex;
use std::ops::Not;
use std::string::String;

#[allow(clippy::borrowed_box)]
Expand Down Expand Up @@ -93,7 +94,10 @@ pub fn evaluate_expression(
evaluate_boolean(expr)
}
PrefixUnary => {
let expr = expression.as_any().downcast_ref::<PrefixUnary>().unwrap();
let expr = expression
.as_any()
.downcast_ref::<UnaryExpression>()
.unwrap();
evaluate_prefix_unary(env, expr, titles, object)
}
Index => {
Expand Down Expand Up @@ -385,7 +389,7 @@ fn evaluate_collection_slice(

fn evaluate_prefix_unary(
env: &mut Environment,
expr: &PrefixUnary,
expr: &UnaryExpression,
titles: &[String],
object: &Vec<Value>,
) -> Result<Value, String> {
Expand All @@ -399,6 +403,7 @@ fn evaluate_prefix_unary(
}
}
PrefixUnaryOperator::Bang => Ok(Value::Boolean(!rhs.as_bool())),
PrefixUnaryOperator::Not => Ok(Value::Integer(rhs.as_int().not())),
}
}

Expand Down Expand Up @@ -543,20 +548,20 @@ fn evaluate_logical(
object: &Vec<Value>,
) -> Result<Value, String> {
let lhs = evaluate_expression(env, &expr.left, titles, object)?.as_bool();
if expr.operator == LogicalOperator::And && !lhs {
if expr.operator == BinaryLogicalOperator::And && !lhs {
return Ok(Value::Boolean(false));
}

if expr.operator == LogicalOperator::Or && lhs {
if expr.operator == BinaryLogicalOperator::Or && lhs {
return Ok(Value::Boolean(true));
}

let rhs = evaluate_expression(env, &expr.right, titles, object)?.as_bool();

Ok(Value::Boolean(match expr.operator {
LogicalOperator::And => lhs && rhs,
LogicalOperator::Or => lhs || rhs,
LogicalOperator::Xor => lhs ^ rhs,
BinaryLogicalOperator::And => lhs && rhs,
BinaryLogicalOperator::Or => lhs || rhs,
BinaryLogicalOperator::Xor => lhs ^ rhs,
}))
}

Expand All @@ -570,16 +575,16 @@ fn evaluate_bitwise(
let rhs = evaluate_expression(env, &expr.right, titles, object)?.as_int();

match expr.operator {
BitwiseOperator::Or => Ok(Value::Integer(lhs | rhs)),
BitwiseOperator::And => Ok(Value::Integer(lhs & rhs)),
BitwiseOperator::RightShift => {
BinaryBitwiseOperator::Or => Ok(Value::Integer(lhs | rhs)),
BinaryBitwiseOperator::And => Ok(Value::Integer(lhs & rhs)),
BinaryBitwiseOperator::RightShift => {
if rhs >= 64 {
Err("Attempt to shift right with overflow".to_string())
} else {
Ok(Value::Integer(lhs >> rhs))
}
}
BitwiseOperator::LeftShift => {
BinaryBitwiseOperator::LeftShift => {
if rhs >= 64 {
Err("Attempt to shift left with overflow".to_string())
} else {
Expand Down
Loading

0 comments on commit 8db2443

Please sign in to comment.