Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 17 additions & 52 deletions src/ast/descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,25 @@ impl Descriptor {

impl fmt::Debug for Descriptor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Descriptor({:?}, {:?})",
self.variable, self.descriptor_type
)
if f.alternate() {
// Pretty: use full struct format with newlines
f.debug_struct("Descriptor")
.field("variable", &self.variable)
.field("label", &self.descriptor_type.label)
.field("properties", &self.descriptor_type.properties)
.finish()
} else {
// Compact: flattened tuple format
write!(
f,
"Descriptor({:?}, {:?}, {:?})",
self.variable, self.descriptor_type.label, self.descriptor_type.properties
)
}
}
}

#[derive(PartialEq, Clone, Default)]
#[derive(PartialEq, Clone, Default, Debug)]
pub struct DescriptorType {
pub label: LabelType,
pub properties: PropertyType,
Expand All @@ -69,13 +79,7 @@ impl DescriptorType {
}
}

impl fmt::Debug for DescriptorType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DescriptorType({:?}, {:?})", self.label, self.properties)
}
}

#[derive(PartialEq, Clone)]
#[derive(PartialEq, Clone, Debug)]
pub enum PropertyType {
Open(HashMap<String, SimpleType>),
Closed(HashMap<String, SimpleType>),
Expand All @@ -96,42 +100,3 @@ impl Default for PropertyType {
Self::open()
}
}

impl fmt::Debug for PropertyType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
PropertyType::Open(map) => {
if map.is_empty() {
write!(f, "Open({{}})")
} else {
let mut keys: Vec<_> = map.keys().collect();
keys.sort();
write!(f, "Open({{")?;
for (i, key) in keys.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}: {:?}", key, map[*key])?;
}
write!(f, "}})")
}
}
PropertyType::Closed(map) => {
if map.is_empty() {
write!(f, "Closed({{}})")
} else {
let mut keys: Vec<_> = map.keys().collect();
keys.sort();
write!(f, "Closed({{")?;
for (i, key) in keys.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}: {:?}", key, map[*key])?;
}
write!(f, "}})")
}
}
}
}
}
208 changes: 12 additions & 196 deletions src/ast/expr.rs
Original file line number Diff line number Diff line change
@@ -1,113 +1,34 @@
use super::types::SimpleType;
use super::var::Var;
use std::fmt;

/// Base enum for all expressions in the query language.
/// Expressions are used in filters (e.g., `WHERE` clauses).
#[derive(PartialEq, Clone)]
#[derive(PartialEq, Clone, Debug)]
pub enum Expr {
Constant(Constant),
TypeLiteral(SimpleType),
AttributeLookup(AttributeLookup),
Binop(Binop),
Unop(Unop),
AttributeLookup(Var, Var),
Binop(BinOpKind, Box<Expr>, Box<Expr>),
Unop(UnOpKind, Box<Expr>),
}

impl Expr {
pub fn binop(kind: BinOpKind, left: Expr, right: Expr) -> Self {
Expr::Binop(Binop::new(kind, left, right))
Expr::Binop(kind, Box::new(left), Box::new(right))
}

pub fn unop(kind: UnOpKind, expr: Expr) -> Self {
Expr::Unop(Unop::new(kind, expr))
Expr::Unop(kind, Box::new(expr))
}

pub fn attr_lookup(e: Var, a: Var) -> Self {
Expr::AttributeLookup(AttributeLookup::new(e, a))
}
}

impl fmt::Display for Expr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Expr::Constant(c) => write!(f, "{}", c),
Expr::TypeLiteral(t) => write!(f, "{}", t),
Expr::AttributeLookup(a) => write!(f, "{}", a),
Expr::Binop(b) => write!(f, "{}", b),
Expr::Unop(u) => write!(f, "{}", u),
}
}
}

impl fmt::Debug for Expr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Expr::Constant(c) => write!(f, "Constant({:?})", c),
Expr::TypeLiteral(t) => write!(f, "TypeLiteral({:?})", t),
Expr::AttributeLookup(a) => write!(f, "AttributeLookup({:?})", a),
Expr::Binop(b) => write!(f, "Binop({:?})", b),
Expr::Unop(u) => write!(f, "Unop({:?})", u),
}
}
}

/// Binary operation expression, e.g., `x.age + 9`, `x.running IS bool`
#[derive(PartialEq, Clone)]
pub struct Binop {
pub op: BinOpKind,
pub e1: Box<Expr>,
pub e2: Box<Expr>,
}

impl Binop {
pub fn new(op: BinOpKind, e1: Expr, e2: Expr) -> Self {
Binop {
op,
e1: Box::new(e1),
e2: Box::new(e2),
}
}
}

impl fmt::Display for Binop {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({} {} {})", self.e1, self.op, self.e2)
}
}

impl fmt::Debug for Binop {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Binop({:?}, {:?}, {:?})", self.op, self.e1, self.e2)
}
}

/// Unary operation expression, e.g., `-x.age`, `NOT x.running`.
#[derive(PartialEq, Clone)]
pub struct Unop {
pub op: UnOpKind,
pub e: Box<Expr>,
}

impl Unop {
pub fn new(op: UnOpKind, e: Expr) -> Self {
Unop { op, e: Box::new(e) }
}
}

impl fmt::Display for Unop {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {}", self.op, self.e)
}
}

impl fmt::Debug for Unop {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Unop({:?}, {:?})", self.op, self.e)
/// Creates `entity.attribute` lookup expression
pub fn attr_lookup(entity: Var, attribute: Var) -> Self {
Expr::AttributeLookup(entity, attribute)
}
}

/// Represents a constant expression (string, int, or boolean).
#[derive(PartialEq, Clone)]
#[derive(PartialEq, Clone, Debug)]
pub enum Constant {
String(String),
Int(i64),
Expand Down Expand Up @@ -138,53 +59,8 @@ impl From<bool> for Constant {
}
}

impl fmt::Display for Constant {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Constant::String(s) => write!(f, "{}", s),
Constant::Int(i) => write!(f, "{}", i),
Constant::Bool(b) => write!(f, "{}", b),
}
}
}

impl fmt::Debug for Constant {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Constant::String(s) => write!(f, "'{}'", s),
Constant::Int(i) => write!(f, "{}", i),
Constant::Bool(b) => write!(f, "{}", b),
}
}
}

/// Expression of the form `e.a` that accesses the attribute `a` of the entity `e`.
#[derive(PartialEq, Clone)]
pub struct AttributeLookup {
pub e: Var,
pub a: Var,
}

impl AttributeLookup {
pub fn new(e: Var, a: Var) -> Self {
AttributeLookup { e, a }
}
}

impl fmt::Display for AttributeLookup {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}.{}", self.e.0, self.a.0)
}
}

impl fmt::Debug for AttributeLookup {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "AttributeLookup({:?}, {:?})", self.e, self.a)
}
}

/// Binary operator kinds
#[derive(PartialEq, Clone)]
#[derive(PartialEq, Clone, Debug)]
pub enum BinOpKind {
// Arithmetic
Add,
Expand All @@ -206,69 +82,9 @@ pub enum BinOpKind {
As,
}

impl fmt::Display for BinOpKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
BinOpKind::Add => write!(f, "+"),
BinOpKind::Sub => write!(f, "-"),
BinOpKind::Mul => write!(f, "*"),
BinOpKind::Div => write!(f, "/"),
BinOpKind::Lt => write!(f, "<"),
BinOpKind::Gt => write!(f, ">"),
BinOpKind::Le => write!(f, "<="),
BinOpKind::Ge => write!(f, ">="),
BinOpKind::Eq => write!(f, "="),
BinOpKind::Ne => write!(f, "!="),
BinOpKind::And => write!(f, "AND"),
BinOpKind::Or => write!(f, "OR"),
BinOpKind::Is => write!(f, "IS"),
BinOpKind::As => write!(f, "AS"),
}
}
}

impl fmt::Debug for BinOpKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
BinOpKind::Add => write!(f, "Add"),
BinOpKind::Sub => write!(f, "Sub"),
BinOpKind::Mul => write!(f, "Mul"),
BinOpKind::Div => write!(f, "Div"),
BinOpKind::Lt => write!(f, "Lt"),
BinOpKind::Gt => write!(f, "Gt"),
BinOpKind::Le => write!(f, "Le"),
BinOpKind::Ge => write!(f, "Ge"),
BinOpKind::Eq => write!(f, "Eq"),
BinOpKind::Ne => write!(f, "Ne"),
BinOpKind::And => write!(f, "And"),
BinOpKind::Or => write!(f, "Or"),
BinOpKind::Is => write!(f, "Is"),
BinOpKind::As => write!(f, "As"),
}
}
}

/// Unary operator kinds
#[derive(PartialEq, Clone)]
#[derive(PartialEq, Clone, Debug)]
pub enum UnOpKind {
Neg, // -
Not, // not
}

impl fmt::Display for UnOpKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
UnOpKind::Neg => write!(f, "-"),
UnOpKind::Not => write!(f, "NOT"),
}
}
}

impl fmt::Debug for UnOpKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
UnOpKind::Neg => write!(f, "Neg"),
UnOpKind::Not => write!(f, "Not"),
}
}
}
15 changes: 1 addition & 14 deletions src/ast/label.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use std::fmt;

#[derive(PartialEq, Clone, Default)]
#[derive(PartialEq, Clone, Default, Debug)]
pub enum LabelType {
Label(String),
#[default]
Expand All @@ -18,14 +16,3 @@ impl LabelType {
LabelType::Or(Box::new(l1), Box::new(l2))
}
}

impl fmt::Debug for LabelType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
LabelType::Label(s) => write!(f, "Label({})", s),
LabelType::Star => write!(f, "Star"),
LabelType::And(l1, l2) => write!(f, "And({:?}, {:?})", l1, l2),
LabelType::Or(l1, l2) => write!(f, "Or({:?}, {:?})", l1, l2),
}
}
}
2 changes: 1 addition & 1 deletion src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mod types;
mod var;

pub use descriptor::{Descriptor, DescriptorType, PropertyType};
pub use expr::{AttributeLookup, BinOpKind, Binop, Constant, Expr, UnOpKind, Unop};
pub use expr::{BinOpKind, Constant, Expr, UnOpKind};
pub use label::LabelType;
pub use pattern::{EdgeDirection, PathPattern, Quantifier};
pub use types::{BaseType, SimpleType};
Expand Down
Loading
Loading