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
2 changes: 1 addition & 1 deletion src/typechecker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pub mod type_environment;
pub mod variable_type;

pub use checker::{TypecheckResult, Typechecker};
pub use path_type::{Direction, PathType};
pub use path_type::PathType;
pub use schema::Schema;
pub use type_environment::TypeEnvironment;
pub use variable_type::{EdgeKind, EdgeType, NodeType, VariableType};
17 changes: 3 additions & 14 deletions src/typechecker/checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::ast::{
};
use crate::parser;

use super::path_type::{Direction, PathType};
use super::path_type::PathType;
use super::schema::Schema;
use super::type_environment::TypeEnvironment;
use super::variable_type::{EdgeKind, EdgeType, NodeType, VariableType};
Expand Down Expand Up @@ -103,15 +103,14 @@ impl Typechecker {
match node {
PathPattern::Node(desc) => {
let t = self.refine_pattern_node(desc);
let p = PathType::to_path_type(&t, Direction::Any);
let p = PathType::to_path_type(&t, EdgeDirection::Any);
let c = TypeEnvironment::create_context(desc, t);
TypecheckResult::new(p, c)
}

PathPattern::Edge(dir, desc) => {
let t = self.refine_pattern_edge(dir, desc);
let path_dir = Self::to_path_direction(dir);
let p = PathType::to_path_type(&t, path_dir);
let p = PathType::to_path_type(&t, *dir);
let c = TypeEnvironment::create_context(desc, t);
TypecheckResult::new(p, c)
}
Expand Down Expand Up @@ -332,16 +331,6 @@ impl Typechecker {
// Helpers
// -----------------------------------------------

/// Converts an AST `EdgeDirection` to a path `Direction`.
fn to_path_direction(dir: &EdgeDirection) -> Direction {
match dir {
EdgeDirection::Right => Direction::Right,
EdgeDirection::Left => Direction::Left,
EdgeDirection::Any => Direction::Any,
EdgeDirection::None => Direction::Undirected,
}
}

/// Extracts the lower bound from a quantifier.
fn lower_bound(q: &Quantifier) -> u64 {
match q {
Expand Down
70 changes: 35 additions & 35 deletions src/typechecker/path_type.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
use crate::ast::EdgeDirection;

use super::schema::Schema;
use super::variable_type::{EdgeKind, EdgeType, VariableType};

/// Edge direction in a path.
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum Direction {
Right,
Left,
Undirected,
Any,
}

/// Path types representing sequences of nodes and edges.
#[derive(PartialEq, Clone, Debug)]
pub enum PathType {
Expand All @@ -32,6 +25,28 @@ impl Default for PathType {
}
}

impl From<&EdgeType> for PathType {
fn from(edge: &EdgeType) -> Self {
match edge.kind {
EdgeKind::Directed => PathType::Edge {
path: Box::new(PathType::Node(edge.left.clone().into())),
node: edge.right.clone().into(),
},
EdgeKind::Undirected => {
let forward = edge.to_directed(false);
let reversed = edge.to_directed(true);
PathType::union(PathType::from(&forward), PathType::from(&reversed))
}
}
}
}

impl From<EdgeType> for PathType {
fn from(edge: EdgeType) -> Self {
PathType::from(&edge)
}
}

impl PathType {
/// Creates a node path type.
pub fn node(n: VariableType) -> Self {
Expand Down Expand Up @@ -87,37 +102,22 @@ impl PathType {
}

/// Converts a VariableType to a PathType given a direction.
pub fn to_path_type(t: &VariableType, direction: Direction) -> PathType {
pub fn to_path_type(t: &VariableType, direction: EdgeDirection) -> PathType {
match t {
VariableType::Node(_) => PathType::Node(t.clone()),
VariableType::Edge(edge) => match edge.kind {
EdgeKind::Directed => match direction {
Direction::Right => PathType::Edge {
path: Box::new(PathType::Node(edge.left.clone().into())),
node: edge.right.clone().into(),
},
Direction::Left => {
let flipped = VariableType::Edge(EdgeType::directed(
edge.descriptor.clone(),
edge.right.clone(),
edge.left.clone(),
));
PathType::to_path_type(&flipped, Direction::Right)
EdgeKind::Directed => {
let forward = edge.to_directed(false);
let reversed = edge.to_directed(true);
match direction {
EdgeDirection::Right => PathType::from(&forward),
EdgeDirection::Left => PathType::from(&reversed),
EdgeDirection::Any | EdgeDirection::None => {
PathType::union(PathType::from(&forward), PathType::from(&reversed))
}
}
Direction::Any => PathType::union(
PathType::to_path_type(t, Direction::Right),
PathType::to_path_type(t, Direction::Left),
),
Direction::Undirected => PathType::to_path_type(t, Direction::Any),
},
EdgeKind::Undirected => {
let as_directed = VariableType::Edge(EdgeType::directed(
edge.descriptor.clone(),
edge.left.clone(),
edge.right.clone(),
));
PathType::to_path_type(&as_directed, Direction::Any)
}
EdgeKind::Undirected => PathType::from(edge),
},
VariableType::Union(t1, t2) => PathType::union(
PathType::to_path_type(t1, direction),
Expand Down
52 changes: 22 additions & 30 deletions src/typechecker/variable_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,18 @@ impl EdgeType {
kind: EdgeKind::Undirected,
}
}

/// Converts this edge to a directed edge.
///
/// If `reverse` is true, endpoint order is swapped.
pub fn to_directed(&self, reverse: bool) -> Self {
let (left, right) = if reverse {
(self.right.clone(), self.left.clone())
} else {
(self.left.clone(), self.right.clone())
};
EdgeType::directed(self.descriptor.clone(), left, right)
}
}

/// Represents the inferred or declared types of variables in a GQL query.
Expand Down Expand Up @@ -146,21 +158,11 @@ impl VariableType {
Ok(VariableType::Edge(EdgeType::directed(desc, left, right)))
}
(EdgeKind::Undirected, EdgeKind::Undirected) => {
let as_dir1 = VariableType::Edge(EdgeType::directed(
edge1.descriptor.clone(),
edge1.left.clone(),
edge1.right.clone(),
));
let as_dir2 = VariableType::Edge(EdgeType::directed(
edge2.descriptor.clone(),
edge2.left.clone(),
edge2.right.clone(),
));
let as_dir2_flipped = VariableType::Edge(EdgeType::directed(
edge2.descriptor.clone(),
edge2.right.clone(),
edge2.left.clone(),
));
let as_dir1 = VariableType::Edge(edge1.to_directed(false));
let edge2_a = edge2.to_directed(false);
let edge2_b = edge2.to_directed(true);
let as_dir2 = VariableType::Edge(edge2_a);
let as_dir2_flipped = VariableType::Edge(edge2_b);

let n1 = VariableType::meet_edge(&as_dir1, &as_dir2);
let n2 = VariableType::meet_edge(&as_dir1, &as_dir2_flipped);
Expand Down Expand Up @@ -253,21 +255,11 @@ impl VariableType {
&& DescriptorType::is_subtype(&e1.right.0, &e2.right.0)
}
(EdgeKind::Undirected, EdgeKind::Undirected) => {
let dir1 = VariableType::Edge(EdgeType::directed(
e1.descriptor.clone(),
e1.left.clone(),
e1.right.clone(),
));
let dir2_normal = VariableType::Edge(EdgeType::directed(
e2.descriptor.clone(),
e2.left.clone(),
e2.right.clone(),
));
let dir2_flipped = VariableType::Edge(EdgeType::directed(
e2.descriptor.clone(),
e2.right.clone(),
e2.left.clone(),
));
let dir1 = VariableType::Edge(e1.to_directed(false));
let e2_a = e2.to_directed(false);
let e2_b = e2.to_directed(true);
let dir2_normal = VariableType::Edge(e2_a);
let dir2_flipped = VariableType::Edge(e2_b);
VariableType::is_subtype(&dir1, &dir2_normal)
|| VariableType::is_subtype(&dir1, &dir2_flipped)
}
Expand Down
Loading