Skip to content

Commit

Permalink
feat: Implement CompositeType and MemberAcccess Expression
Browse files Browse the repository at this point in the history
  • Loading branch information
AmrDeveloper committed Nov 2, 2024
1 parent 3b83aae commit d85bddd
Show file tree
Hide file tree
Showing 10 changed files with 291 additions and 10 deletions.
42 changes: 42 additions & 0 deletions crates/gitql-ast/src/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ pub enum ExprKind {
IsNull,
Null,
Cast,
Grouping,
MemberAccess,
}

dyn_clone::clone_trait_object!(Expr);
Expand Down Expand Up @@ -629,3 +631,43 @@ impl Expr for CastExpr {
self
}
}

#[derive(Clone)]
pub struct GroupExpr {
pub expr: Box<dyn Expr>,
}

impl Expr for GroupExpr {
fn kind(&self) -> ExprKind {
ExprKind::Grouping
}

fn expr_type(&self) -> Box<dyn DataType> {
self.expr.expr_type().clone()
}

fn as_any(&self) -> &dyn Any {
self
}
}

#[derive(Clone)]
pub struct MemberAccessExpr {
pub composite: Box<dyn Expr>,
pub member_name: String,
pub member_type: Box<dyn DataType>,
}

impl Expr for MemberAccessExpr {
fn kind(&self) -> ExprKind {
ExprKind::MemberAccess
}

fn expr_type(&self) -> Box<dyn DataType> {
self.member_type.clone()
}

fn as_any(&self) -> &dyn Any {
self
}
}
6 changes: 6 additions & 0 deletions crates/gitql-ast/src/types/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::expression::Expr;
use super::any::AnyType;
use super::array::ArrayType;
use super::boolean::BoolType;
use super::composite::CompositeType;
use super::date::DateType;
use super::datetime::DateTimeType;
use super::float::FloatType;
Expand Down Expand Up @@ -502,6 +503,11 @@ impl dyn DataType {
self.as_any().downcast_ref::<VariantType>().is_some()
}

/// Return true if this type is [`CompositeType`]
pub fn is_composite(&self) -> bool {
self.as_any().downcast_ref::<CompositeType>().is_some()
}

/// Return true if this type is [`UndefType`]
pub fn is_undefined(&self) -> bool {
self.as_any().downcast_ref::<UndefType>().is_some()
Expand Down
41 changes: 41 additions & 0 deletions crates/gitql-ast/src/types/composite.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use std::any::Any;
use std::collections::HashMap;

use super::base::DataType;

#[derive(Clone)]
pub struct CompositeType {
pub name: String,
pub members: HashMap<String, Box<dyn DataType>>,
}

impl DataType for CompositeType {
fn literal(&self) -> String {
self.name.to_string()
}

fn equals(&self, other: &Box<dyn DataType>) -> bool {
if other.is_any() {
return true;
}

let composite_type: Box<dyn DataType> = Box::new(self.clone());
if other.is_variant_contains(&composite_type) {
return true;
}

if let Some(other_composite) = other.as_any().downcast_ref::<CompositeType>() {
if self.name.ne(&other_composite.name) {
return false;
}

return self.members.eq(&other_composite.members);
}

false
}

fn as_any(&self) -> &dyn Any {
self
}
}
1 change: 1 addition & 0 deletions crates/gitql-ast/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod any;
pub mod array;
pub mod base;
pub mod boolean;
pub mod composite;
pub mod date;
pub mod datetime;
pub mod dynamic;
Expand Down
5 changes: 3 additions & 2 deletions crates/gitql-cli/src/printer/table_printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@ fn print_group_as_table(titles: &[String], table_headers: Vec<comfy_table::Cell>
for row in rows {
let mut table_row: Vec<comfy_table::Cell> = vec![];
for index in 0..titles_len {
let value = row.values.get(index).unwrap();
table_row.push(comfy_table::Cell::new(value.literal()));
if let Some(value) = row.values.get(index) {
table_row.push(comfy_table::Cell::new(value.literal()));
}
}
table.add_row(table_row);
}
Expand Down
6 changes: 6 additions & 0 deletions crates/gitql-core/src/values/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use gitql_ast::types::base::DataType;

use super::array::ArrayValue;
use super::boolean::BoolValue;
use super::composite::CompositeValue;
use super::date::DateValue;
use super::datetime::DateTimeValue;
use super::float::FloatValue;
Expand Down Expand Up @@ -405,6 +406,11 @@ impl dyn Value {
pub fn is_null(&self) -> bool {
self.as_any().downcast_ref::<NullValue>().is_some()
}

/// Return true if this value is [`CompositeValue`]
pub fn is_composite(&self) -> bool {
self.as_any().downcast_ref::<CompositeValue>().is_some()
}
}

impl fmt::Display for Box<dyn Value> {
Expand Down
55 changes: 55 additions & 0 deletions crates/gitql-core/src/values/composite.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use std::any::Any;
use std::cmp::Ordering;
use std::collections::HashMap;

use gitql_ast::types::base::DataType;
use gitql_ast::types::composite::CompositeType;

use super::base::Value;

#[derive(Clone)]
pub struct CompositeValue {
pub name: String,
pub members: HashMap<String, Box<dyn Value>>,
}

impl Value for CompositeValue {
fn literal(&self) -> String {
let mut str = String::new();
let last_position = self.members.len() - 1;
str += "(";
for (pos, member) in self.members.iter().enumerate() {
str += &member.1.literal();
if pos != last_position {
str += ", ";
}
}
str += ")";
str
}

fn equals(&self, other: &Box<dyn Value>) -> bool {
if let Some(other_composite) = other.as_any().downcast_ref::<CompositeValue>() {
return self.name.eq(&other_composite.name)
&& self.members.eq(&other_composite.members);
}
false
}

fn compare(&self, _other: &Box<dyn Value>) -> Option<Ordering> {
None
}

fn data_type(&self) -> Box<dyn DataType> {
let name = self.name.to_string();
let mut members: HashMap<String, Box<dyn DataType>> = HashMap::new();
for member in self.members.iter() {
members.insert(member.0.to_string(), member.1.data_type().clone());
}
Box::new(CompositeType { name, members })
}

fn as_any(&self) -> &dyn Any {
self
}
}
1 change: 1 addition & 0 deletions crates/gitql-core/src/values/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod array;
pub mod base;
pub mod boolean;
pub mod composite;
pub mod converters;
pub mod date;
pub mod datetime;
Expand Down
38 changes: 38 additions & 0 deletions crates/gitql-engine/src/engine_evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ use gitql_ast::expression::Expr;
use gitql_ast::expression::ExprKind::*;
use gitql_ast::expression::GlobExpr;
use gitql_ast::expression::GlobalVariableExpr;
use gitql_ast::expression::GroupExpr;
use gitql_ast::expression::InExpr;
use gitql_ast::expression::IndexExpr;
use gitql_ast::expression::IsNullExpr;
use gitql_ast::expression::LikeExpr;
use gitql_ast::expression::LogicalExpr;
use gitql_ast::expression::MemberAccessExpr;
use gitql_ast::expression::Number;
use gitql_ast::expression::NumberExpr;
use gitql_ast::expression::RegexExpr;
Expand All @@ -36,6 +38,7 @@ use gitql_core::environment::Environment;
use gitql_core::values::array::ArrayValue;
use gitql_core::values::base::Value;
use gitql_core::values::boolean::BoolValue;
use gitql_core::values::composite::CompositeValue;
use gitql_core::values::float::FloatValue;
use gitql_core::values::integer::IntValue;
use gitql_core::values::null::NullValue;
Expand Down Expand Up @@ -175,6 +178,17 @@ pub fn evaluate_expression(
let expr = expression.as_any().downcast_ref::<CastExpr>().unwrap();
evaluate_cast(env, expr, titles, object)
}
Grouping => {
let expr = expression.as_any().downcast_ref::<GroupExpr>().unwrap();
evaluate_grouping(env, expr, titles, object)
}
MemberAccess => {
let expr = expression
.as_any()
.downcast_ref::<MemberAccessExpr>()
.unwrap();
evaluate_member_access(env, expr, titles, object)
}
Null => Ok(Box::new(NullValue)),
}
}
Expand Down Expand Up @@ -612,3 +626,27 @@ fn evaluate_cast(
let value = evaluate_expression(env, &expr.value, titles, object)?;
value.cast_op(&expr.result_type)
}

fn evaluate_grouping(
env: &mut Environment,
expr: &GroupExpr,
titles: &[String],
object: &Vec<Box<dyn Value>>,
) -> Result<Box<dyn Value>, String> {
let value = evaluate_expression(env, &expr.expr, titles, object)?;
Ok(value)
}

fn evaluate_member_access(
env: &mut Environment,
expr: &MemberAccessExpr,
titles: &[String],
object: &Vec<Box<dyn Value>>,
) -> Result<Box<dyn Value>, String> {
let value = evaluate_expression(env, &expr.composite, titles, object)?;
if let Some(composite_value) = value.as_any().downcast_ref::<CompositeValue>() {
let member_name = &expr.member_name;
return Ok(composite_value.members.get(member_name).unwrap().clone());
}
Err("Invalid value for Member access expression".to_owned())
}
Loading

0 comments on commit d85bddd

Please sign in to comment.