From 25ef03221b4c6051b0d6d064144e196c49e2c7f0 Mon Sep 17 00:00:00 2001 From: Sayan Nandan Date: Fri, 3 Feb 2023 07:06:23 -0800 Subject: [PATCH] Make `ASTNode` sensitive to COW style parsing --- server/src/engine/ql/ast/mod.rs | 4 +- server/src/engine/ql/ast/traits.rs | 47 +++++++- server/src/engine/ql/ddl/alt.rs | 4 +- server/src/engine/ql/ddl/crt.rs | 20 ++-- server/src/engine/ql/ddl/drop.rs | 6 +- server/src/engine/ql/ddl/ins.rs | 2 +- server/src/engine/ql/ddl/syn.rs | 50 ++++----- server/src/engine/ql/dml/del.rs | 15 ++- server/src/engine/ql/dml/ins.rs | 122 +++++++++++---------- server/src/engine/ql/dml/mod.rs | 34 +++--- server/src/engine/ql/dml/sel.rs | 15 ++- server/src/engine/ql/dml/upd.rs | 55 ++++++---- server/src/engine/ql/macros.rs | 15 --- server/src/engine/ql/tests/dml_tests.rs | 16 ++- server/src/engine/ql/tests/schema_tests.rs | 18 +-- 15 files changed, 234 insertions(+), 189 deletions(-) diff --git a/server/src/engine/ql/ast/mod.rs b/server/src/engine/ql/ast/mod.rs index b8b45902..89f91324 100644 --- a/server/src/engine/ql/ast/mod.rs +++ b/server/src/engine/ql/ast/mod.rs @@ -523,9 +523,9 @@ pub enum Statement<'a> { /// DDL query to switch between spaces and models Use(Entity<'a>), /// DDL query to create a model - CreateModel(ddl::crt::Model<'a>), + CreateModel(ddl::crt::CreateModel<'a>), /// DDL query to create a space - CreateSpace(ddl::crt::Space<'a>), + CreateSpace(ddl::crt::CreateSpace<'a>), /// DDL query to alter a space (properties) AlterSpace(ddl::alt::AlterSpace<'a>), /// DDL query to alter a model (properties, field types, etc) diff --git a/server/src/engine/ql/ast/traits.rs b/server/src/engine/ql/ast/traits.rs index 7d891ec2..d787f6aa 100644 --- a/server/src/engine/ql/ast/traits.rs +++ b/server/src/engine/ql/ast/traits.rs @@ -28,12 +28,49 @@ use crate::engine::ql::{ast::InplaceData, lex::Token}; use crate::engine::ql::{ ast::{QueryData, State}, - LangResult, + LangError, LangResult, }; +/// An AST node pub trait ASTNode<'a>: Sized { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult; + const VERIFY: bool = false; + /// Parse this AST node from the given state + /// + /// Note to implementors: + /// - If the implementor uses a cow style parse, then set [`ASTNode::VERIFY`] to + /// true + /// - Try to propagate errors via [`State`] if possible + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult; + fn from_state>(state: &mut State<'a, Qd>) -> LangResult { + let r = ::_from_state(state); + if Self::VERIFY { + return if state.okay() { + r + } else { + Err(LangError::UnexpectedToken) + }; + } + r + } + #[cfg(test)] + /// Parse multiple nodes of this AST node type. Intended for the test suite. + fn _multiple_from_state>(_: &mut State<'a, Qd>) -> LangResult> { + unimplemented!() + } #[cfg(test)] + fn multiple_from_state>(state: &mut State<'a, Qd>) -> LangResult> { + let r = ::_multiple_from_state(state); + if Self::VERIFY { + return if state.okay() { + r + } else { + Err(LangError::UnexpectedToken) + }; + } + r + } + #[cfg(test)] + /// Parse this AST node utilizing the full token-stream. Intended for the test suite. fn from_insecure_tokens_full(tok: &'a [Token<'a>]) -> LangResult { let mut state = State::new(tok, InplaceData::new()); let r = ::from_state(&mut state)?; @@ -41,10 +78,8 @@ pub trait ASTNode<'a>: Sized { Ok(r) } #[cfg(test)] - fn multiple_from_state>(_: &mut State<'a, Qd>) -> LangResult> { - unimplemented!() - } - #[cfg(test)] + /// Parse multiple nodes of this AST node type, utilizing the full token stream. + /// Intended for the test suite. fn multiple_from_insecure_tokens_full(tok: &'a [Token<'a>]) -> LangResult> { let mut state = State::new(tok, InplaceData::new()); let r = Self::multiple_from_state(&mut state); diff --git a/server/src/engine/ql/ddl/alt.rs b/server/src/engine/ql/ddl/alt.rs index 0aa6e68d..940bf496 100644 --- a/server/src/engine/ql/ddl/alt.rs +++ b/server/src/engine/ql/ddl/alt.rs @@ -183,12 +183,12 @@ mod impls { LangResult, }; impl<'a> ASTNode<'a> for AlterModel<'a> { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { Self::parse(state) } } impl<'a> ASTNode<'a> for AlterSpace<'a> { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { Self::parse(state) } } diff --git a/server/src/engine/ql/ddl/crt.rs b/server/src/engine/ql/ddl/crt.rs index b57cf93f..c90b24fb 100644 --- a/server/src/engine/ql/ddl/crt.rs +++ b/server/src/engine/ql/ddl/crt.rs @@ -36,14 +36,14 @@ use crate::{ #[derive(Debug, PartialEq)] /// A space -pub struct Space<'a> { +pub struct CreateSpace<'a> { /// the space name pub(super) space_name: Slice<'a>, /// properties pub(super) props: Dict, } -impl<'a> Space<'a> { +impl<'a> CreateSpace<'a> { #[inline(always)] /// Parse space data from the given tokens fn parse>(state: &mut State<'a, Qd>) -> LangResult { @@ -63,7 +63,7 @@ impl<'a> Space<'a> { syn::rfold_dict(DictFoldState::OB, state, &mut d); } if state.okay() { - Ok(Space { + Ok(CreateSpace { space_name: unsafe { extract!(space_name, Token::Ident(ref id) => id.clone()) }, props: d, }) @@ -75,7 +75,7 @@ impl<'a> Space<'a> { #[derive(Debug, PartialEq)] /// A model definition -pub struct Model<'a> { +pub struct CreateModel<'a> { /// the model name model_name: Slice<'a>, /// the fields @@ -91,7 +91,7 @@ pub struct Model<'a> { ) */ -impl<'a> Model<'a> { +impl<'a> CreateModel<'a> { pub fn new(model_name: Slice<'a>, fields: Vec>, props: Dict) -> Self { Self { model_name, @@ -142,18 +142,18 @@ impl<'a> Model<'a> { } mod impls { - use super::{Model, Space}; + use super::{CreateModel, CreateSpace}; use crate::engine::ql::{ ast::{traits::ASTNode, QueryData, State}, LangResult, }; - impl<'a> ASTNode<'a> for Space<'a> { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { + impl<'a> ASTNode<'a> for CreateSpace<'a> { + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { Self::parse(state) } } - impl<'a> ASTNode<'a> for Model<'a> { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { + impl<'a> ASTNode<'a> for CreateModel<'a> { + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { Self::parse(state) } } diff --git a/server/src/engine/ql/ddl/drop.rs b/server/src/engine/ql/ddl/drop.rs index 7b57e499..a1dba5ae 100644 --- a/server/src/engine/ql/ddl/drop.rs +++ b/server/src/engine/ql/ddl/drop.rs @@ -107,19 +107,19 @@ mod impls { LangResult, }; impl<'a> ASTNode<'a> for DropModel<'a> { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { Self::parse(state) } } impl<'a> ASTNode<'a> for DropSpace<'a> { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { Self::parse(state) } } #[derive(sky_macros::Wrapper, Debug)] pub struct DropStatementAST<'a>(Statement<'a>); impl<'a> ASTNode<'a> for DropStatementAST<'a> { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { super::parse_drop(state).map(Self) } } diff --git a/server/src/engine/ql/ddl/ins.rs b/server/src/engine/ql/ddl/ins.rs index 3eae00e1..b49c45b9 100644 --- a/server/src/engine/ql/ddl/ins.rs +++ b/server/src/engine/ql/ddl/ins.rs @@ -72,7 +72,7 @@ mod impls { #[derive(sky_macros::Wrapper, Debug)] pub struct InspectStatementAST<'a>(Statement<'a>); impl<'a> ASTNode<'a> for InspectStatementAST<'a> { - fn from_state>( + fn _from_state>( state: &mut State<'a, Qd>, ) -> crate::engine::ql::LangResult { super::parse_inspect(state).map(Self) diff --git a/server/src/engine/ql/ddl/syn.rs b/server/src/engine/ql/ddl/syn.rs index 1f056be0..9387949d 100644 --- a/server/src/engine/ql/ddl/syn.rs +++ b/server/src/engine/ql/ddl/syn.rs @@ -505,78 +505,70 @@ mod impls { }; use crate::engine::ql::{ ast::{traits::ASTNode, QueryData, State}, - LangError, LangResult, + LangResult, }; impl<'a> ASTNode<'a> for ExpandedField<'a> { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { Self::parse(state) } - fn multiple_from_state>( + fn _multiple_from_state>( state: &mut State<'a, Qd>, ) -> LangResult> { Self::parse_multiple(state).map(Vec::from) } } impl<'a> ASTNode<'a> for Layer<'a> { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { + // important: upstream must verify this + const VERIFY: bool = true; + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { let mut layers = Vec::new(); rfold_layers(LayerFoldState::BEGIN_IDENT, state, &mut layers); assert!(layers.len() == 1); Ok(layers.swap_remove(0)) } - fn multiple_from_state>( + fn _multiple_from_state>( state: &mut State<'a, Qd>, ) -> LangResult> { let mut l = Vec::new(); rfold_layers(LayerFoldState::BEGIN_IDENT, state, &mut l); - if state.okay() { - Ok(l) - } else { - Err(LangError::UnexpectedToken) - } + Ok(l) } } #[derive(sky_macros::Wrapper, Debug)] pub struct DictBasic(Dict); impl<'a> ASTNode<'a> for DictBasic { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { + // important: upstream must verify this + const VERIFY: bool = true; + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { let mut dict = Dict::new(); rfold_dict(DictFoldState::OB, state, &mut dict); - if state.okay() { - Ok(Self(dict)) - } else { - Err(LangError::UnexpectedToken) - } + Ok(Self(dict)) } } #[derive(sky_macros::Wrapper, Debug)] pub struct DictTypeMetaSplit(Dict); impl<'a> ASTNode<'a> for DictTypeMetaSplit { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { + // important: upstream must verify this + const VERIFY: bool = true; + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { let mut dict = Dict::new(); rfold_tymeta(DictFoldState::CB_OR_IDENT, state, &mut dict); - if state.okay() { - Ok(Self(dict)) - } else { - Err(LangError::UnexpectedToken) - } + Ok(Self(dict)) } } #[derive(sky_macros::Wrapper, Debug)] pub struct DictTypeMeta(Dict); impl<'a> ASTNode<'a> for DictTypeMeta { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { + // important: upstream must verify this + const VERIFY: bool = true; + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { let mut dict = Dict::new(); rfold_tymeta(DictFoldState::OB, state, &mut dict); - if state.okay() { - Ok(Self(dict)) - } else { - Err(LangError::UnexpectedToken) - } + Ok(Self(dict)) } } impl<'a> ASTNode<'a> for Field<'a> { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { Self::parse(state) } } diff --git a/server/src/engine/ql/dml/del.rs b/server/src/engine/ql/dml/del.rs index 95f6ed0b..70c955e2 100644 --- a/server/src/engine/ql/dml/del.rs +++ b/server/src/engine/ql/dml/del.rs @@ -30,7 +30,7 @@ use { super::WhereClause, crate::{ engine::ql::{ - ast::{traits::ASTNode, Entity, QueryData, State}, + ast::{Entity, QueryData, State}, LangError, LangResult, }, util::{compiler, MaybeInit}, @@ -94,8 +94,15 @@ impl<'a> DeleteStatement<'a> { } } -impl<'a> ASTNode<'a> for DeleteStatement<'a> { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { - Self::parse_delete(state) +mod impls { + use super::DeleteStatement; + use crate::engine::ql::{ + ast::{traits::ASTNode, QueryData, State}, + LangResult, + }; + impl<'a> ASTNode<'a> for DeleteStatement<'a> { + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { + Self::parse_delete(state) + } } } diff --git a/server/src/engine/ql/dml/ins.rs b/server/src/engine/ql/dml/ins.rs index d911f348..ff586b40 100644 --- a/server/src/engine/ql/dml/ins.rs +++ b/server/src/engine/ql/dml/ins.rs @@ -30,7 +30,7 @@ use { engine::{ core::DataType, ql::{ - ast::{traits::ASTNode, Entity, QueryData, State}, + ast::{Entity, QueryData, State}, lex::Token, LangError, LangResult, }, @@ -207,22 +207,6 @@ unsafe fn handle_func_sub<'a, Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> O ldfunc(func).map(move |f| f()) } -#[cfg(test)] -#[derive(sky_macros::Wrapper, Debug)] -pub struct List(Vec); -#[cfg(test)] -impl<'a> ASTNode<'a> for List { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { - let mut l = Vec::new(); - parse_list(state, &mut l); - if state.okay() { - Ok(List(l)) - } else { - Err(LangError::UnexpectedToken) - } - } -} - /// ## Panics /// - If tt is empty pub(super) fn parse_data_tuple_syntax<'a, Qd: QueryData<'a>>( @@ -270,21 +254,6 @@ pub(super) fn parse_data_tuple_syntax<'a, Qd: QueryData<'a>>( data } -#[cfg(test)] -#[derive(sky_macros::Wrapper, Debug)] -pub struct DataTuple(Vec>); -#[cfg(test)] -impl<'a> ASTNode<'a> for DataTuple { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { - let r = parse_data_tuple_syntax(state); - if state.okay() { - Ok(Self(r)) - } else { - Err(LangError::UnexpectedToken) - } - } -} - /// ## Panics /// Panics if tt is empty pub(super) fn parse_data_map_syntax<'a, Qd: QueryData<'a>>( @@ -341,30 +310,6 @@ pub(super) fn parse_data_map_syntax<'a, Qd: QueryData<'a>>( data } -#[cfg(test)] -#[derive(sky_macros::Wrapper, Debug)] -pub struct DataMap(HashMap, Option>); -#[cfg(test)] -impl<'a> ASTNode<'a> for DataMap { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { - let r = parse_data_map_syntax(state); - if state.okay() { - Ok(Self( - r.into_iter() - .map(|(ident, val)| { - ( - String::from_utf8_lossy(ident).to_string().into_boxed_str(), - val, - ) - }) - .collect(), - )) - } else { - Err(LangError::UnexpectedToken) - } - } -} - #[derive(Debug, PartialEq)] pub enum InsertData<'a> { Ordered(Vec>), @@ -444,8 +389,67 @@ impl<'a> InsertStatement<'a> { } } -impl<'a> ASTNode<'a> for InsertStatement<'a> { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { - Self::parse_insert(state) +#[cfg(test)] +pub use impls::test::{DataMap, DataTuple, List}; +mod impls { + use super::InsertStatement; + use crate::engine::ql::{ + ast::{traits::ASTNode, QueryData, State}, + LangResult, + }; + impl<'a> ASTNode<'a> for InsertStatement<'a> { + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { + Self::parse_insert(state) + } + } + #[cfg(test)] + pub mod test { + use super::super::{ + parse_data_map_syntax, parse_data_tuple_syntax, parse_list, DataType, HashMap, + }; + use crate::engine::ql::{ + ast::{traits::ASTNode, QueryData, State}, + LangResult, + }; + #[derive(sky_macros::Wrapper, Debug)] + pub struct List(Vec); + impl<'a> ASTNode<'a> for List { + // important: upstream must verify this + const VERIFY: bool = true; + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { + let mut l = Vec::new(); + parse_list(state, &mut l); + Ok(List(l)) + } + } + #[derive(sky_macros::Wrapper, Debug)] + pub struct DataTuple(Vec>); + impl<'a> ASTNode<'a> for DataTuple { + // important: upstream must verify this + const VERIFY: bool = true; + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { + let r = parse_data_tuple_syntax(state); + Ok(Self(r)) + } + } + #[derive(sky_macros::Wrapper, Debug)] + pub struct DataMap(HashMap, Option>); + impl<'a> ASTNode<'a> for DataMap { + // important: upstream must verify this + const VERIFY: bool = true; + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { + let r = parse_data_map_syntax(state); + Ok(Self( + r.into_iter() + .map(|(ident, val)| { + ( + String::from_utf8_lossy(ident).to_string().into_boxed_str(), + val, + ) + }) + .collect(), + )) + } + } } } diff --git a/server/src/engine/ql/dml/mod.rs b/server/src/engine/ql/dml/mod.rs index cf7ba7d9..ce0c5725 100644 --- a/server/src/engine/ql/dml/mod.rs +++ b/server/src/engine/ql/dml/mod.rs @@ -36,9 +36,8 @@ pub mod upd; use { super::{ - ast::{traits::ASTNode, QueryData, State}, + ast::{QueryData, State}, lex::{LitIR, Token}, - LangError, LangResult, }, crate::util::compiler, std::collections::HashMap, @@ -119,12 +118,6 @@ impl<'a> RelationalExpr<'a> { } } -impl<'a> ASTNode<'a> for RelationalExpr<'a> { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { - Self::try_parse(state).ok_or(LangError::UnexpectedToken) - } -} - #[derive(Debug, PartialEq)] pub struct WhereClause<'a> { c: WhereClauseCollection<'a>, @@ -164,13 +157,26 @@ impl<'a> WhereClause<'a> { } } -impl<'a> ASTNode<'a> for WhereClause<'a> { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { - let wh = Self::parse_where(state); - if state.okay() { +#[cfg(test)] +mod impls { + use super::{ + super::{ + ast::{traits::ASTNode, QueryData, State}, + LangError, LangResult, + }, + RelationalExpr, WhereClause, + }; + impl<'a> ASTNode<'a> for WhereClause<'a> { + // important: upstream must verify this + const VERIFY: bool = true; + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { + let wh = Self::parse_where(state); Ok(wh) - } else { - Err(LangError::UnexpectedToken) + } + } + impl<'a> ASTNode<'a> for RelationalExpr<'a> { + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { + Self::try_parse(state).ok_or(LangError::UnexpectedToken) } } } diff --git a/server/src/engine/ql/dml/sel.rs b/server/src/engine/ql/dml/sel.rs index 88e78a99..5ad5c687 100644 --- a/server/src/engine/ql/dml/sel.rs +++ b/server/src/engine/ql/dml/sel.rs @@ -28,7 +28,7 @@ use { super::{WhereClause, WhereClauseCollection}, crate::{ engine::ql::{ - ast::{traits::ASTNode, Entity, QueryData, State}, + ast::{Entity, QueryData, State}, lex::Token, LangError, LangResult, }, @@ -134,8 +134,15 @@ impl<'a> SelectStatement<'a> { } } -impl<'a> ASTNode<'a> for SelectStatement<'a> { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { - Self::parse_select(state) +mod impls { + use super::SelectStatement; + use crate::engine::ql::{ + ast::{traits::ASTNode, QueryData, State}, + LangResult, + }; + impl<'a> ASTNode<'a> for SelectStatement<'a> { + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { + Self::parse_select(state) + } } } diff --git a/server/src/engine/ql/dml/upd.rs b/server/src/engine/ql/dml/upd.rs index 2713b150..10d4702b 100644 --- a/server/src/engine/ql/dml/upd.rs +++ b/server/src/engine/ql/dml/upd.rs @@ -25,15 +25,12 @@ */ #[cfg(test)] -use { - super::WhereClauseCollection, - crate::engine::ql::{ast::InplaceData, lex::Token}, -}; +use super::WhereClauseCollection; use { super::{read_ident, u, WhereClause}, crate::{ engine::ql::{ - ast::{traits::ASTNode, Entity, QueryData, State}, + ast::{Entity, QueryData, State}, lex::LitIR, LangError, LangResult, }, @@ -132,20 +129,6 @@ impl<'a> AssignmentExpression<'a> { } } -#[cfg(test)] -pub fn parse_assn_expression_full<'a>(tok: &'a [Token]) -> Option> { - let mut state = State::new(tok, InplaceData::new()); - let mut exprs = Vec::new(); - AssignmentExpression::parse_and_append_expression(&mut state, &mut exprs); - assert_full_tt!(state); - if state.okay() { - assert_eq!(exprs.len(), 1, "expected one expression, found multiple"); - Some(exprs.remove(0)) - } else { - None - } -} - #[derive(Debug, PartialEq)] pub struct UpdateStatement<'a> { pub(super) entity: Entity<'a>, @@ -227,8 +210,36 @@ impl<'a> UpdateStatement<'a> { } } -impl<'a> ASTNode<'a> for UpdateStatement<'a> { - fn from_state>(state: &mut State<'a, Qd>) -> LangResult { - Self::parse_update(state) +mod impls { + use super::UpdateStatement; + use crate::engine::ql::{ + ast::{traits::ASTNode, QueryData, State}, + LangResult, + }; + impl<'a> ASTNode<'a> for UpdateStatement<'a> { + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { + Self::parse_update(state) + } + } + #[cfg(test)] + mod test { + use super::{super::AssignmentExpression, *}; + impl<'a> ASTNode<'a> for AssignmentExpression<'a> { + // important: upstream must verify this + const VERIFY: bool = true; + fn _from_state>(state: &mut State<'a, Qd>) -> LangResult { + let mut expr = Vec::new(); + AssignmentExpression::parse_and_append_expression(state, &mut expr); + state.poison_if_not(expr.len() == 1); + Ok(expr.remove(0)) + } + fn _multiple_from_state>( + state: &mut State<'a, Qd>, + ) -> LangResult> { + let mut expr = Vec::new(); + AssignmentExpression::parse_and_append_expression(state, &mut expr); + Ok(expr) + } + } } } diff --git a/server/src/engine/ql/macros.rs b/server/src/engine/ql/macros.rs index 9adc304e..a158a339 100644 --- a/server/src/engine/ql/macros.rs +++ b/server/src/engine/ql/macros.rs @@ -24,21 +24,6 @@ * */ -#[cfg(test)] -macro_rules! assert_full_tt { - ($a:expr, $b:expr) => { - assert_eq!($a, $b, "full token stream not utilized") - }; - ($a:expr) => { - assert!( - crate::engine::ql::ast::State::exhausted(&$a), - "full tt not utilized at: {}:{}", - ::core::file!(), - ::core::line!() - ) - }; -} - macro_rules! __sym_token { ($ident:ident) => { $crate::engine::ql::lex::Token::Symbol($crate::engine::ql::lex::Symbol::$ident) diff --git a/server/src/engine/ql/tests/dml_tests.rs b/server/src/engine/ql/tests/dml_tests.rs index d3ada309..6c62fd32 100644 --- a/server/src/engine/ql/tests/dml_tests.rs +++ b/server/src/engine/ql/tests/dml_tests.rs @@ -690,17 +690,15 @@ mod expression_tests { use { super::*, crate::engine::ql::{ - dml::{ - self, - upd::{AssignmentExpression, Operator}, - }, + ast::parse_ast_node_full, + dml::upd::{AssignmentExpression, Operator}, lex::LitIR, }, }; #[test] fn expr_assign() { let src = lex_insecure(b"username = 'sayan'").unwrap(); - let r = dml::upd::parse_assn_expression_full(&src).unwrap(); + let r = parse_ast_node_full::(&src).unwrap(); assert_eq!( r, AssignmentExpression::new(b"username", LitIR::Str("sayan"), Operator::Assign) @@ -709,7 +707,7 @@ mod expression_tests { #[test] fn expr_add_assign() { let src = lex_insecure(b"followers += 100").unwrap(); - let r = dml::upd::parse_assn_expression_full(&src).unwrap(); + let r = parse_ast_node_full::(&src).unwrap(); assert_eq!( r, AssignmentExpression::new(b"followers", LitIR::UInt(100), Operator::AddAssign) @@ -718,7 +716,7 @@ mod expression_tests { #[test] fn expr_sub_assign() { let src = lex_insecure(b"following -= 150").unwrap(); - let r = dml::upd::parse_assn_expression_full(&src).unwrap(); + let r = parse_ast_node_full::(&src).unwrap(); assert_eq!( r, AssignmentExpression::new(b"following", LitIR::UInt(150), Operator::SubAssign) @@ -727,7 +725,7 @@ mod expression_tests { #[test] fn expr_mul_assign() { let src = lex_insecure(b"product_qty *= 2").unwrap(); - let r = dml::upd::parse_assn_expression_full(&src).unwrap(); + let r = parse_ast_node_full::(&src).unwrap(); assert_eq!( r, AssignmentExpression::new(b"product_qty", LitIR::UInt(2), Operator::MulAssign) @@ -736,7 +734,7 @@ mod expression_tests { #[test] fn expr_div_assign() { let src = lex_insecure(b"image_crop_factor /= 2").unwrap(); - let r = dml::upd::parse_assn_expression_full(&src).unwrap(); + let r = parse_ast_node_full::(&src).unwrap(); assert_eq!( r, AssignmentExpression::new(b"image_crop_factor", LitIR::UInt(2), Operator::DivAssign) diff --git a/server/src/engine/ql/tests/schema_tests.rs b/server/src/engine/ql/tests/schema_tests.rs index 0ae72e8f..73535c11 100644 --- a/server/src/engine/ql/tests/schema_tests.rs +++ b/server/src/engine/ql/tests/schema_tests.rs @@ -408,7 +408,7 @@ mod schemas { use crate::engine::ql::{ ast::parse_ast_node_full, ddl::{ - crt::Model, + crt::CreateModel, syn::{Field, Layer}, }, }; @@ -426,11 +426,11 @@ mod schemas { let tok = &tok[2..]; // parse model - let model = parse_ast_node_full::(tok).unwrap(); + let model = parse_ast_node_full::(tok).unwrap(); assert_eq!( model, - Model::new( + CreateModel::new( b"mymodel", vec![ Field::new( @@ -465,11 +465,11 @@ mod schemas { let tok = &tok[2..]; // parse model - let model = parse_ast_node_full::(tok).unwrap(); + let model = parse_ast_node_full::(tok).unwrap(); assert_eq!( model, - Model::new( + CreateModel::new( b"mymodel", vec![ Field::new( @@ -515,11 +515,11 @@ mod schemas { let tok = &tok[2..]; // parse model - let model = parse_ast_node_full::(tok).unwrap(); + let model = parse_ast_node_full::(tok).unwrap(); assert_eq!( model, - Model::new( + CreateModel::new( b"mymodel", vec![ Field::new( @@ -584,11 +584,11 @@ mod schemas { let tok = &tok[2..]; // parse model - let model = parse_ast_node_full::(tok).unwrap(); + let model = parse_ast_node_full::(tok).unwrap(); assert_eq!( model, - Model::new( + CreateModel::new( b"mymodel", vec![ Field::new(