diff --git a/lykiadb-lang/src/ast/expr.rs b/lykiadb-lang/src/ast/expr.rs index fd24b10..fc1f7e1 100644 --- a/lykiadb-lang/src/ast/expr.rs +++ b/lykiadb-lang/src/ast/expr.rs @@ -13,7 +13,7 @@ use super::{ use crate::Literal; -#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)] #[serde(tag = "@type")] pub enum Operation { Add, @@ -37,7 +37,7 @@ pub enum Operation { NotLike, } -#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)] #[serde(tag = "@type")] pub enum RangeKind { Between, @@ -46,16 +46,18 @@ pub enum RangeKind { #[derive(Debug, Serialize, Deserialize, Clone, Derivative)] #[serde(tag = "@type")] -#[derivative(Eq, PartialEq)] +#[derivative(Eq, PartialEq, Hash)] pub enum Expr { #[serde(rename = "Expr::Select")] Select { query: SqlSelect, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] id: usize, }, #[serde(rename = "Expr::Insert")] @@ -63,9 +65,11 @@ pub enum Expr { command: SqlInsert, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] id: usize, }, #[serde(rename = "Expr::Update")] @@ -73,9 +77,11 @@ pub enum Expr { command: SqlUpdate, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] id: usize, }, #[serde(rename = "Expr::Delete")] @@ -83,9 +89,11 @@ pub enum Expr { command: SqlDelete, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] id: usize, }, #[serde(rename = "Expr::Variable")] @@ -93,9 +101,11 @@ pub enum Expr { name: Identifier, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] id: usize, }, #[serde(rename = "Expr::Grouping")] @@ -103,9 +113,11 @@ pub enum Expr { expr: Box, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] id: usize, }, #[serde(rename = "Expr::Literal")] @@ -114,9 +126,11 @@ pub enum Expr { raw: String, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] id: usize, }, #[serde(rename = "Expr::Function")] @@ -126,9 +140,11 @@ pub enum Expr { body: Arc>, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] id: usize, }, #[serde(rename = "Expr::Between")] @@ -139,9 +155,11 @@ pub enum Expr { kind: RangeKind, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] id: usize, }, #[serde(rename = "Expr::Binary")] @@ -151,9 +169,11 @@ pub enum Expr { right: Box, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] id: usize, }, #[serde(rename = "Expr::Unary")] @@ -162,9 +182,11 @@ pub enum Expr { expr: Box, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] id: usize, }, #[serde(rename = "Expr::Assignment")] @@ -173,9 +195,11 @@ pub enum Expr { expr: Box, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] id: usize, }, #[serde(rename = "Expr::Logical")] @@ -185,9 +209,11 @@ pub enum Expr { right: Box, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] id: usize, }, #[serde(rename = "Expr::Call")] @@ -196,9 +222,11 @@ pub enum Expr { args: Vec, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] id: usize, }, #[serde(rename = "Expr::Get")] @@ -207,9 +235,11 @@ pub enum Expr { name: Identifier, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] id: usize, }, #[serde(rename = "Expr::Set")] @@ -219,9 +249,11 @@ pub enum Expr { value: Box, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] id: usize, }, } diff --git a/lykiadb-lang/src/ast/sql.rs b/lykiadb-lang/src/ast/sql.rs index 30e09f3..e8cfd61 100644 --- a/lykiadb-lang/src/ast/sql.rs +++ b/lykiadb-lang/src/ast/sql.rs @@ -5,7 +5,7 @@ use super::expr::Expr; // Enums -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, Hash)] #[serde(tag = "@type")] pub enum SqlDistinct { #[serde(rename = "SqlDistinct::ImplicitAll")] @@ -16,7 +16,7 @@ pub enum SqlDistinct { Distinct, } -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, Hash)] #[serde(tag = "@type")] pub enum SqlJoinType { #[serde(rename = "SqlJoinType::Left")] @@ -29,7 +29,7 @@ pub enum SqlJoinType { Cross, } -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, Hash)] #[serde(tag = "@type")] pub enum SqlCompoundOperator { #[serde(rename = "SqlCompoundOperator::Union")] @@ -42,7 +42,7 @@ pub enum SqlCompoundOperator { Except, } -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, Hash)] #[serde(tag = "@type")] pub enum SqlOrdering { #[serde(rename = "SqlOrdering::Asc")] @@ -52,7 +52,7 @@ pub enum SqlOrdering { } // -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, Hash)] #[serde(tag = "@type")] pub struct SqlCollectionIdentifier { pub namespace: Option, @@ -60,7 +60,7 @@ pub struct SqlCollectionIdentifier { pub alias: Option, } -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, Hash)] #[serde(tag = "@type")] pub enum SqlProjection { #[serde(rename = "SqlProjection::All")] @@ -72,28 +72,28 @@ pub enum SqlProjection { }, } -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, Hash)] #[serde(tag = "@type")] pub struct SqlLimitClause { pub count: Box, pub offset: Option>, } -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, Hash)] #[serde(tag = "@type")] pub struct SqlOrderByClause { pub expr: Box, pub ordering: SqlOrdering, } -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, Hash)] #[serde(tag = "@type")] pub struct SqlSelectCompound { pub operator: SqlCompoundOperator, pub core: SqlSelectCore, } -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, Hash)] #[serde(tag = "@type")] pub enum SqlFrom { #[serde(rename = "SqlFrom::Group")] @@ -114,7 +114,7 @@ pub enum SqlFrom { }, } -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, Hash)] #[serde(tag = "@type")] pub struct SqlSelectCore { pub distinct: SqlDistinct, @@ -126,7 +126,7 @@ pub struct SqlSelectCore { pub compound: Option>, } -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, Hash)] #[serde(tag = "@type")] pub struct SqlSelect { pub core: SqlSelectCore, @@ -134,7 +134,7 @@ pub struct SqlSelect { pub limit: Option, } -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, Hash)] #[serde(tag = "@type")] pub enum SqlValues { #[serde(rename = "SqlValues::Values")] @@ -143,14 +143,14 @@ pub enum SqlValues { Select(SqlSelect), } -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, Hash)] #[serde(tag = "@type")] pub struct SqlInsert { pub collection: SqlCollectionIdentifier, pub values: SqlValues, } -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, Hash)] #[serde(tag = "@type")] pub struct SqlUpdate { pub collection: SqlCollectionIdentifier, @@ -158,7 +158,7 @@ pub struct SqlUpdate { pub r#where: Option>, } -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, Hash)] #[serde(tag = "@type")] pub struct SqlDelete { pub collection: SqlCollectionIdentifier, diff --git a/lykiadb-lang/src/ast/stmt.rs b/lykiadb-lang/src/ast/stmt.rs index 99ca5be..f109aea 100644 --- a/lykiadb-lang/src/ast/stmt.rs +++ b/lykiadb-lang/src/ast/stmt.rs @@ -7,13 +7,14 @@ use super::expr::Expr; #[derive(Debug, Serialize, Deserialize, Clone, Derivative)] #[serde(tag = "@type")] -#[derivative(Eq, PartialEq)] +#[derivative(Eq, PartialEq, Hash)] pub enum Stmt { #[serde(rename = "Stmt::Program")] Program { body: Vec, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, }, #[serde(rename = "Stmt::Expression")] @@ -21,18 +22,21 @@ pub enum Stmt { expr: Box, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, }, #[serde(rename = "Stmt::Break")] Break { #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, }, #[serde(rename = "Stmt::Continue")] Continue { #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, }, #[serde(rename = "Stmt::Block")] @@ -40,6 +44,7 @@ pub enum Stmt { body: Vec, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, }, #[serde(rename = "Stmt::Declaration")] @@ -48,6 +53,7 @@ pub enum Stmt { expr: Box, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, }, #[serde(rename = "Stmt::If")] @@ -57,6 +63,7 @@ pub enum Stmt { r#else_body: Option>, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, }, #[serde(rename = "Stmt::Loop")] @@ -66,6 +73,7 @@ pub enum Stmt { post: Option>, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, }, #[serde(rename = "Stmt::Return")] @@ -73,6 +81,7 @@ pub enum Stmt { expr: Option>, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] span: Span, }, } diff --git a/lykiadb-lang/src/lib.rs b/lykiadb-lang/src/lib.rs index 7269ebe..ae9ae1b 100644 --- a/lykiadb-lang/src/lib.rs +++ b/lykiadb-lang/src/lib.rs @@ -1,6 +1,7 @@ use std::{ fmt::{Display, Formatter, Result}, sync::Arc, + hash::Hash }; use ast::expr::Expr; @@ -15,7 +16,7 @@ pub mod tokenizer; pub type Scopes = Vec>; pub type Locals = FxHashMap; -#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)] +#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, Hash)] pub struct Span { pub start: usize, pub end: usize, @@ -65,16 +66,33 @@ impl Literal { } } +impl Hash for Literal { + fn hash(&self, state: &mut H) { + match self { + Literal::Str(s) => s.hash(state), + Literal::Num(n) => n.to_bits().hash(state), + Literal::Bool(b) => b.hash(state), + Literal::Object(o) => (o as *const _ as usize).hash(state), + Literal::Array(a) => a.hash(state), + // + Literal::Undefined => "undefined".hash(state), + Literal::NaN => "NaN".hash(state), + Literal::Null => "null".hash(state), + } + } +} + impl Eq for Literal {} #[derive(Debug, Clone, Serialize, Deserialize, Derivative)] #[serde(tag = "@type")] -#[derivative(Eq, PartialEq)] +#[derivative(Eq, PartialEq, Hash)] pub struct Identifier { pub name: String, pub dollar: bool, #[serde(skip)] #[derivative(PartialEq = "ignore")] + #[derivative(Hash = "ignore")] pub span: Span, } diff --git a/lykiadb-lang/tests/lang/generic/expr.rs b/lykiadb-lang/tests/lang/generic/expr.rs index d6aec15..0aaa851 100644 --- a/lykiadb-lang/tests/lang/generic/expr.rs +++ b/lykiadb-lang/tests/lang/generic/expr.rs @@ -1,3 +1,5 @@ +use std::collections::HashSet; + use lykiadb_lang::{ast::expr::Expr, Literal, Span}; fn create_simple_add_expr(id: usize, left: f64, right: f64) -> Expr { @@ -27,6 +29,13 @@ fn identical_exprs_should_be_equal_when_ids_are_different() { let e1 = create_simple_add_expr(1, 1.0, 2.0); assert_eq!(e0, e1); + + let mut set: HashSet = HashSet::new(); + + set.insert(e0); + + assert!(set.contains(&e1)); + }