node def parsing again

main
Ziyang Hu 2 years ago
parent 79162f833e
commit 63ed776699

@ -1,10 +1,27 @@
use std::result;
use crate::parser::{Pair, Pairs};
use std::sync::Arc;
use crate::data::eval::EvalError;
use crate::data::expr::Expr;
use crate::data::parser::ExprParseError;
use crate::data::value::{StaticValue, Value};
use crate::parser::{Pair, Pairs, Rule};
#[derive(thiserror::Error, Debug)]
pub enum AlgebraParseError {
pub(crate) enum AlgebraParseError {
#[error("{0} cannot be chained")]
Unchainable(String)
Unchainable(String),
#[error("wrong argument count for {0}")]
WrongArgumentCount(String),
#[error("wrong argument type for {0}: {0}")]
WrongArgumentType(String, String),
#[error(transparent)]
ExprParse(#[from] ExprParseError),
#[error(transparent)]
EvalError(#[from] EvalError),
}
type Result<T> = result::Result<T, AlgebraParseError>;
@ -13,62 +30,80 @@ trait RelationalAlgebra {
fn name(&self) -> &str;
}
const NAME_VALUES: &str = "Values";
const NAME_RA_FROM_VALUES: &str = "Values";
struct RaFromValues;
#[derive(Clone, Debug)]
struct RaFromValues {
values: StaticValue
}
impl RaFromValues {
fn build(prev: Option<()>, args: Pairs) -> Result<Self> {
if prev!= None {
return Err(AlgebraParseError::Unchainable(NAME_VALUES.to_string()))
fn build(prev: Option<Arc<dyn RelationalAlgebra>>, mut args: Pairs) -> Result<Self> {
if !matches!(prev, None) {
return Err(AlgebraParseError::Unchainable(NAME_RA_FROM_VALUES.to_string()));
}
let data = args.next().unwrap().into_inner().next().unwrap();
if data.as_rule() != Rule::expr {
return Err(AlgebraParseError::WrongArgumentType(
NAME_RA_FROM_VALUES.to_string(),
format!("{:?}", data.as_rule())));
}
dbg!(args);
todo!()
if args.next() != None {
return Err(AlgebraParseError::WrongArgumentCount(NAME_RA_FROM_VALUES.to_string()));
}
let data = Expr::try_from(data)?;
let data = data.row_eval(&())?.to_static();
Ok(Self {
values: data
})
}
}
impl RelationalAlgebra for RaFromValues {
fn name(&self) -> &str {
NAME_VALUES
NAME_RA_FROM_VALUES
}
}
const NAME_INSERT: &str = "Insert";
fn build_ra_expr(pair: Pair) {
let built: Option<()> = None;
fn build_ra_expr(pair: Pair) -> Result<Arc<dyn RelationalAlgebra>> {
let mut built: Option<Arc<dyn RelationalAlgebra>> = None;
for pair in pair.into_inner() {
let mut pairs = pair.into_inner();
match pairs.next().unwrap().as_str() {
NAME_INSERT => todo!(),
NAME_VALUES => {
let _res = RaFromValues::build(built, pairs);
},
NAME_RA_FROM_VALUES => {
built = Some(Arc::new(RaFromValues::build(built, pairs)?));
}
_ => unimplemented!()
}
}
todo!()
Ok(built.unwrap())
}
#[cfg(test)]
mod tests {
use crate::parser::{CozoParser, Rule};
use pest::Parser;
use crate::algebra::parser::build_ra_expr;
use super::*;
#[test]
fn parse_ra() {
fn parse_ra() -> Result<()> {
let s = r#"
Values([{x: 1}])
.Insert(f:Friend)
//.Insert(f:Friend)
"#;
build_ra_expr(CozoParser::parse(Rule::ra_expr_all, s).unwrap().into_iter().next().unwrap());
let s = r#"
From(f:Person-[:HasJob]->j:Job,
f.id == 101, j.id > 10)
.Select(f: {*id: f.id})
"#;
build_ra_expr(CozoParser::parse(Rule::ra_expr_all, s).unwrap().into_iter().next().unwrap());
build_ra_expr(CozoParser::parse(Rule::ra_expr_all, s).unwrap().into_iter().next().unwrap())?;
// let s = r#"
// From(f:Person-[:HasJob]->j:Job,
// f.id == 101, j.id > 10)
// .Select(f: {*id: f.id})
// "#;
// build_ra_expr(CozoParser::parse(Rule::ra_expr_all, s).unwrap().into_iter().next().unwrap());
Ok(())
}
}

@ -52,12 +52,12 @@ impl RowEvalContext for () {
}
}
pub(crate) trait ExprEvalContext {
pub(crate) trait PartialEvalContext {
fn resolve<'a>(&'a self, key: &str) -> Option<Expr<'a>>;
fn resolve_table_col<'a>(&'a self, binding: &str, col: &str) -> Option<(TableId, ColId)>;
}
impl ExprEvalContext for () {
impl PartialEvalContext for () {
fn resolve<'a>(&'a self, _key: &str) -> Option<Expr<'a>> {
None
}
@ -79,14 +79,14 @@ fn extract_optimized_u_args(args: Vec<Expr>) -> Expr {
}
impl<'a> Expr<'a> {
pub(crate) fn interpret_eval<C: ExprEvalContext + 'a>(self, ctx: &'a C) -> Result<Value> {
pub(crate) fn interpret_eval<C: PartialEvalContext + 'a>(self, ctx: &'a C) -> Result<Value> {
match self.partial_eval(ctx)? {
Expr::Const(v) => Ok(v),
v => Err(EvalError::IncompleteEvaluation(format!("{:?}", v))),
}
}
pub(crate) fn partial_eval<C: ExprEvalContext + 'a>(self, ctx: &'a C) -> Result<Self> {
pub(crate) fn partial_eval<C: PartialEvalContext + 'a>(self, ctx: &'a C) -> Result<Self> {
let res = match self {
v @ (Expr::Const(_) | Expr::TableCol(_, _) | Expr::TupleSetIdx(_)) => v,
Expr::List(l) => Expr::List(

@ -60,6 +60,102 @@ pub(crate) enum Expr<'a> {
And(Box<(Expr<'a>, Expr<'a>)>),
}
impl<'a> Expr<'a> {
pub(crate) fn to_static(self) -> StaticExpr {
match self {
Expr::Const(v) => Expr::Const(v.to_static()),
Expr::List(l) => Expr::List(l.into_iter().map(|v| v.to_static()).collect()),
Expr::Dict(d) => Expr::Dict(d.into_iter().map(|(k, v)| (k, v.to_static())).collect()),
Expr::Variable(v) => Expr::Variable(v),
Expr::TableCol(tid, cid) => Expr::TableCol(tid, cid),
Expr::TupleSetIdx(idx) => Expr::TupleSetIdx(idx),
Expr::Apply(op, args) => Expr::Apply(op,
args.into_iter().map(|v| v.to_static()).collect()),
Expr::ApplyAgg(op, a_args, args) => Expr::ApplyAgg(
op,
a_args.into_iter().map(|v| v.to_static()).collect(),
args.into_iter().map(|v| v.to_static()).collect(),
),
Expr::FieldAcc(f, arg) => Expr::FieldAcc(f, arg.to_static().into()),
Expr::IdxAcc(i, arg) => Expr::IdxAcc(i, arg.to_static().into()),
Expr::IfExpr(args) => {
let (a, b, c) = *args;
Expr::IfExpr((a.to_static(), b.to_static(), c.to_static()).into())
}
Expr::SwitchExpr(args) => Expr::SwitchExpr(args.into_iter().map(|(a, b)|
(a.to_static(), b.to_static())).collect()),
Expr::Add(args) => {
let (a, b) = *args;
Expr::Add((a.to_static(), b.to_static()).into())
}
Expr::Sub(args) => {
let (a, b) = *args;
Expr::Sub((a.to_static(), b.to_static()).into())
}
Expr::Mul(args) => {
let (a, b) = *args;
Expr::Mul((a.to_static(), b.to_static()).into())
}
Expr::Div(args) => {
let (a, b) = *args;
Expr::Div((a.to_static(), b.to_static()).into())
}
Expr::Pow(args) => {
let (a, b) = *args;
Expr::Pow((a.to_static(), b.to_static()).into())
}
Expr::Mod(args) => {
let (a, b) = *args;
Expr::Mod((a.to_static(), b.to_static()).into())
}
Expr::StrCat(args) => {
let (a, b) = *args;
Expr::StrCat((a.to_static(), b.to_static()).into())
}
Expr::Eq(args) => {
let (a, b) = *args;
Expr::Eq((a.to_static(), b.to_static()).into())
}
Expr::Ne(args) => {
let (a, b) = *args;
Expr::Ne((a.to_static(), b.to_static()).into())
}
Expr::Gt(args) => {
let (a, b) = *args;
Expr::Gt((a.to_static(), b.to_static()).into())
}
Expr::Ge(args) => {
let (a, b) = *args;
Expr::Ge((a.to_static(), b.to_static()).into())
}
Expr::Lt(args) => {
let (a, b) = *args;
Expr::Lt((a.to_static(), b.to_static()).into())
}
Expr::Le(args) => {
let (a, b) = *args;
Expr::Le((a.to_static(), b.to_static()).into())
}
Expr::Not(arg) => Expr::Not(arg.to_static().into()),
Expr::Minus(arg) => Expr::Minus(arg.to_static().into()),
Expr::IsNull(arg) => Expr::IsNull(arg.to_static().into()),
Expr::NotNull(arg) => Expr::NotNull(arg.to_static().into()),
Expr::Coalesce(args) => {
let (a, b) = *args;
Expr::Coalesce((a.to_static(), b.to_static()).into())
}
Expr::Or(args) => {
let (a, b) = *args;
Expr::Or((a.to_static(), b.to_static()).into())
}
Expr::And(args) => {
let (a, b) = *args;
Expr::And((a.to_static(), b.to_static()).into())
}
}
}
}
impl<'a> PartialEq for Expr<'a> {
fn eq(&self, other: &Self) -> bool {
use Expr::*;
@ -317,7 +413,7 @@ fn build_value_from_binop<'a>(name: &str, (left, right): (Expr<'a>, Expr<'a>)) -
Value::from(name.to_string()),
Value::from(vec![Value::from(left), Value::from(right)]),
]
.into(),
.into(),
)
}
@ -328,7 +424,7 @@ fn build_value_from_uop<'a>(name: &str, arg: Expr<'a>) -> Value<'a> {
Value::from(name.to_string()),
Value::from(vec![Value::from(arg)]),
]
.into(),
.into(),
)
}
@ -356,7 +452,7 @@ impl<'a> From<Expr<'a>> for Value<'a> {
cid.is_key.into(),
Value::from(cid.id as i64),
]
.into(),
.into(),
),
Expr::TupleSetIdx(sid) => build_tagged_value(
"TupleSetIdx",
@ -365,7 +461,7 @@ impl<'a> From<Expr<'a>> for Value<'a> {
Value::from(sid.t_set as i64),
Value::from(sid.col_idx as i64),
]
.into(),
.into(),
),
Expr::Add(arg) => build_value_from_binop(OpAdd.name(), *arg),
Expr::Sub(arg) => build_value_from_binop(OpSub.name(), *arg),
@ -393,7 +489,7 @@ impl<'a> From<Expr<'a>> for Value<'a> {
Value::from(op.name().to_string()),
args.into_iter().map(Value::from).collect::<Vec<_>>().into(),
]
.into(),
.into(),
),
Expr::IfExpr(_) => {
todo!()
@ -412,7 +508,7 @@ impl<'a> From<Expr<'a>> for Value<'a> {
.into(),
args.into_iter().map(Value::from).collect::<Vec<_>>().into(),
]
.into(),
.into(),
),
Expr::FieldAcc(f, v) => {
build_tagged_value("FieldAcc", vec![f.into(), Value::from(*v)].into())

@ -4,6 +4,8 @@ mod combine;
mod comparison;
mod control;
mod text;
mod uuid;
mod sequence;
use crate::data::eval::EvalError;
use crate::data::value::{Value};

@ -1,4 +1,4 @@
use crate::data::eval::{EvalError, ExprEvalContext, RowEvalContext};
use crate::data::eval::{EvalError, PartialEvalContext, RowEvalContext};
use crate::data::expr::Expr;
use crate::data::op::Op;
use crate::data::value::{Value};
@ -106,7 +106,7 @@ impl Op for OpOr {
}
}
pub(crate) fn partial_eval_or<'a, T: ExprEvalContext + 'a>(
pub(crate) fn partial_eval_or<'a, T: PartialEvalContext + 'a>(
ctx: &'a T,
args: Vec<Expr<'a>>,
) -> Result<Expr<'a>> {
@ -210,7 +210,7 @@ impl Op for OpAnd {
}
}
pub(crate) fn partial_eval_and<'a, T: ExprEvalContext + 'a>(
pub(crate) fn partial_eval_and<'a, T: PartialEvalContext + 'a>(
ctx: &'a T,
args: Vec<Expr<'a>>,
) -> Result<Expr<'a>> {

@ -1,4 +1,4 @@
use crate::data::eval::{EvalError, ExprEvalContext, RowEvalContext};
use crate::data::eval::{EvalError, PartialEvalContext, RowEvalContext};
use crate::data::expr::Expr;
use crate::data::op::Op;
use crate::data::value::Value;
@ -52,7 +52,7 @@ pub(crate) fn row_eval_coalesce<'a, T: RowEvalContext + 'a>(
pub(crate) const IF_NAME: &str = "if";
pub(crate) fn partial_eval_coalesce<'a, T: ExprEvalContext + 'a>(
pub(crate) fn partial_eval_coalesce<'a, T: PartialEvalContext + 'a>(
ctx: &'a T,
args: Vec<Expr<'a>>,
) -> Result<Expr<'a>> {
@ -94,7 +94,7 @@ pub(crate) fn row_eval_if_expr<'a, T: RowEvalContext + 'a>(
}
}
pub(crate) fn partial_eval_if_expr<'a, T: ExprEvalContext + 'a>(
pub(crate) fn partial_eval_if_expr<'a, T: PartialEvalContext + 'a>(
ctx: &'a T,
cond: Expr<'a>,
if_part: Expr<'a>,
@ -135,7 +135,7 @@ pub(crate) fn row_eval_switch_expr<'a, T: RowEvalContext + 'a>(
default.row_eval(ctx)
}
pub(crate) fn partial_eval_switch_expr<'a, T: ExprEvalContext + 'a>(
pub(crate) fn partial_eval_switch_expr<'a, T: PartialEvalContext + 'a>(
ctx: &'a T,
args: Vec<(Expr<'a>, Expr<'a>)>,
) -> Result<Expr<'a>> {

@ -0,0 +1,28 @@
use crate::data::op::Op;
use crate::data::value::Value;
pub(crate) struct SeqNext;
const NAME_OP_SEQ_NEXT: &str = "seq_next";
impl Op for SeqNext {
fn arity(&self) -> Option<usize> {
Some(1)
}
fn has_side_effect(&self) -> bool {
true
}
fn name(&self) -> &str {
NAME_OP_SEQ_NEXT
}
fn non_null_args(&self) -> bool {
true
}
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
todo!()
}
}

@ -0,0 +1,28 @@
use crate::data::op::Op;
use crate::data::value::Value;
pub(crate) struct OpGenUuidV1;
const NAME_OP_GEN_UUID_V1:&str = "gen_uuid_v1";
impl Op for OpGenUuidV1 {
fn arity(&self) -> Option<usize> {
Some(0)
}
fn has_side_effect(&self) -> bool {
true
}
fn name(&self) -> &str {
NAME_OP_GEN_UUID_V1
}
fn non_null_args(&self) -> bool {
true
}
fn eval<'a>(&self, args: Vec<Value<'a>>) -> crate::data::op::Result<Value<'a>> {
todo!()
}
}

@ -0,0 +1 @@
pub(crate) mod parser;

@ -0,0 +1,189 @@
use std::result;
use crate::data::expr::{Expr, StaticExpr};
use crate::data::parser::ExprParseError;
use crate::data::typing::{Typing, TypingError};
use crate::data::value::Value;
use crate::parser::{Pair, Rule};
use crate::parser::text_identifier::{build_name_in_def, TextParseError};
#[derive(thiserror::Error, Debug)]
pub(crate) enum DdlParseError {
#[error(transparent)]
TextParse(#[from] TextParseError),
#[error(transparent)]
Typing(#[from] TypingError),
#[error(transparent)]
ExprParse(#[from] ExprParseError)
}
type Result<T> = result::Result<T, DdlParseError>;
#[derive(Debug, Clone)]
pub(crate) struct ColSchema {
name: String,
typing: Typing,
default: StaticExpr,
}
#[derive(Debug, Clone)]
pub(crate) struct NodeSchema {
name: String,
keys: Vec<ColSchema>,
vals: Vec<ColSchema>,
}
#[derive(Debug, Clone)]
pub(crate) struct EdgeSchema {
name: String,
src_name: String,
dst_name: String,
keys: Vec<ColSchema>,
vals: Vec<ColSchema>,
}
#[derive(Debug, Clone)]
pub(crate) struct AssocSchema {
name: String,
src_name: String,
vals: Vec<ColSchema>,
}
#[derive(Debug, Clone)]
pub(crate) enum IndexCol {
Simple(String),
Computed(StaticExpr),
}
#[derive(Debug, Clone)]
pub(crate) struct IndexSchema {
name: String,
src_name: String,
index: Vec<IndexCol>,
}
#[derive(Debug, Clone)]
pub(crate) struct SequenceSchema {
name: String,
}
#[derive(Debug, Clone)]
pub(crate) enum DdlSchema {
Node(NodeSchema),
Edge(EdgeSchema),
Assoc(AssocSchema),
Index(IndexSchema),
Sequence(SequenceSchema)
}
impl<'a> TryFrom<Pair<'a>> for DdlSchema {
type Error = DdlParseError;
fn try_from(pair: Pair<'a>) -> result::Result<Self, Self::Error> {
Ok(match pair.as_rule() {
Rule::node_def => DdlSchema::Node(pair.try_into()?),
_ => todo!()
})
}
}
impl<'a> TryFrom<Pair<'a>> for NodeSchema {
type Error = DdlParseError;
fn try_from(pair: Pair) -> Result<Self> {
let mut pairs = pair.into_inner();
let name = build_name_in_def(pairs.next().unwrap(), true)?;
let col_pair = pairs.next().unwrap();
let (keys, vals) = parse_cols(col_pair)?;
Ok(Self {
name,
keys,
vals,
})
}
}
impl<'a> TryFrom<Pair<'a>> for EdgeSchema {
type Error = DdlParseError;
fn try_from(value: Pair) -> Result<Self> {
todo!()
}
}
impl<'a> TryFrom<Pair<'a>> for AssocSchema {
type Error = DdlParseError;
fn try_from(value: Pair) -> Result<Self> {
todo!()
}
}
impl<'a> TryFrom<Pair<'a>> for IndexSchema {
type Error = DdlParseError;
fn try_from(value: Pair) -> Result<Self> {
todo!()
}
}
fn parse_cols(pair: Pair) -> Result<(Vec<ColSchema>, Vec<ColSchema>)> {
let mut keys = vec![];
let mut vals = vec![];
for pair in pair.into_inner() {
match parse_col_entry(pair)? {
(true, res) => keys.push(res),
(false, res) => vals.push(res)
}
}
Ok((keys, vals))
}
fn parse_col_entry(pair: Pair) -> Result<(bool, ColSchema)> {
let mut pairs = pair.into_inner();
let (is_key, name) = parse_col_name(pairs.next().unwrap())?;
let typing = Typing::try_from(pairs.next().unwrap())?;
let default = match pairs.next() {
None => Expr::Const(Value::Null),
Some(pair) => Expr::try_from(pair)?.to_static(),
};
Ok((is_key, ColSchema {
name,
typing,
default
}))
}
fn parse_col_name(pair: Pair) -> Result<(bool, String)> {
let mut pairs = pair.into_inner();
let mut nxt = pairs.next().unwrap();
let is_key = match nxt.as_rule() {
Rule::key_marker => {
nxt = pairs.next().unwrap();
true
},
_ => false
};
let name = build_name_in_def(nxt, true)?;
Ok((is_key, name))
}
#[cfg(test)]
mod tests {
use crate::parser::CozoParser;
use pest::Parser;
use super::*;
#[test]
fn parse_ddl() -> Result<()> {
let s = r#"
node Job {
*id: Int,
title: Text,
min_salary: Float = 0,
max_salary: Float
}
"#;
let p = CozoParser::parse(Rule::definition_all, s).unwrap().next().unwrap();
dbg!(DdlSchema::try_from(p)?);
Ok(())
}
}

@ -175,10 +175,12 @@ associate_def = { "assoc" ~ name_in_def ~ ":" ~ name_in_def ~ cols_def ~ ";"? }
edge_def = { "edge" ~
"(" ~ name_in_def ~ ")" ~ "-" ~ "[" ~ name_in_def ~ "]" ~ "->" ~ "(" ~ name_in_def ~ ")"
~ cols_def? ~ ";"? }
index_def = { "index" ~ (name_in_def ~ ":")? ~ name_in_def ~ col_list ~ ";"? }
type_def = { "type" ~ name_in_def ~ "=" ~ typing ~ ";"? }
index_def = { "index" ~ (name_in_def ~ ":")? ~ name_in_def ~ ("+" ~ name_in_def)* ~ "[" ~ (expr ~ ",")* ~ expr? ~ "]" ~ ";"? }
seq_def = { "seq" ~ (name_in_def) ~ ";" }
type_def = { "type" ~ name_in_def ~ "=" ~ typing ~ ";" }
definition = _{ node_def | associate_def | edge_def | type_def | index_def }
definition = _{ node_def | associate_def | edge_def | index_def | seq_def }
definition_all = _{SOI ~ definition ~ EOI}
global_def = { "create" ~ definition }
local_def = { "local" ~ definition }
statement = _{ global_def | local_def }

@ -3,5 +3,6 @@ pub(crate) mod logger;
pub(crate) mod parser;
pub(crate) mod runtime;
pub(crate) mod algebra;
pub(crate) mod ddl;
pub use runtime::instance::DbInstance;

Loading…
Cancel
Save