new tuple type
parent
ffb24a612a
commit
ab272b85ac
@ -1,315 +1,316 @@
|
||||
use std::sync::Arc;
|
||||
use pest::iterators::{Pair};
|
||||
use pest::Parser as PestParser;
|
||||
use pest::prec_climber::{Assoc, PrecClimber, Operator};
|
||||
use crate::parser::Parser;
|
||||
use crate::parser::Rule;
|
||||
use lazy_static::lazy_static;
|
||||
use crate::ast::Expr::{Apply, Const};
|
||||
use crate::error::CozoError;
|
||||
use crate::error::Result;
|
||||
use crate::value::Value;
|
||||
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum Op {
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
Eq,
|
||||
Neq,
|
||||
Gt,
|
||||
Lt,
|
||||
Ge,
|
||||
Le,
|
||||
Neg,
|
||||
Minus,
|
||||
Mod,
|
||||
Or,
|
||||
And,
|
||||
Coalesce,
|
||||
Pow,
|
||||
Call,
|
||||
IsNull,
|
||||
NotNull,
|
||||
}
|
||||
|
||||
|
||||
lazy_static! {
|
||||
static ref PREC_CLIMBER: PrecClimber<Rule> = {
|
||||
use Assoc::*;
|
||||
|
||||
PrecClimber::new(vec![
|
||||
Operator::new(Rule::op_or, Left),
|
||||
Operator::new(Rule::op_and, Left),
|
||||
Operator::new(Rule::op_gt, Left) | Operator::new(Rule::op_lt, Left) | Operator::new(Rule::op_ge,Left) | Operator::new(Rule::op_le, Left),
|
||||
Operator::new(Rule::op_mod, Left),
|
||||
Operator::new(Rule::op_eq, Left) | Operator::new(Rule::op_ne, Left),
|
||||
Operator::new(Rule::op_add, Left) | Operator::new(Rule::op_sub, Left),
|
||||
Operator::new(Rule::op_mul, Left) | Operator::new(Rule::op_div, Left),
|
||||
Operator::new(Rule::op_pow, Assoc::Right),
|
||||
Operator::new(Rule::op_coalesce, Assoc::Left)
|
||||
])
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum Expr<'a> {
|
||||
List(Vec<Expr<'a>>),
|
||||
Dict(Vec<String>, Vec<Expr<'a>>),
|
||||
Apply(Op, Vec<Expr<'a>>),
|
||||
Ident(String),
|
||||
Const(Value<'a>),
|
||||
}
|
||||
|
||||
pub trait ExprVisitor<'a, T> {
|
||||
fn visit_expr(&self, ex: &Expr<'a>) -> T;
|
||||
}
|
||||
|
||||
|
||||
fn build_expr_infix<'a>(lhs: Result<Expr<'a>>, op: Pair<Rule>, rhs: Result<Expr<'a>>) -> Result<Expr<'a>> {
|
||||
let lhs = lhs?;
|
||||
let rhs = rhs?;
|
||||
let op = match op.as_rule() {
|
||||
Rule::op_add => Op::Add,
|
||||
Rule::op_sub => Op::Sub,
|
||||
Rule::op_mul => Op::Mul,
|
||||
Rule::op_div => Op::Div,
|
||||
Rule::op_eq => Op::Eq,
|
||||
Rule::op_ne => Op::Neq,
|
||||
Rule::op_or => Op::Or,
|
||||
Rule::op_and => Op::And,
|
||||
Rule::op_mod => Op::Mod,
|
||||
Rule::op_gt => Op::Gt,
|
||||
Rule::op_ge => Op::Ge,
|
||||
Rule::op_lt => Op::Lt,
|
||||
Rule::op_le => Op::Le,
|
||||
Rule::op_pow => Op::Pow,
|
||||
Rule::op_coalesce => Op::Coalesce,
|
||||
_ => unreachable!()
|
||||
};
|
||||
Ok(Apply(op, vec![lhs, rhs]))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_int(s: &str, radix: u32) -> i64 {
|
||||
i64::from_str_radix(&s[2..].replace('_', ""), radix).unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_raw_string(pair: Pair<Rule>) -> Result<String> {
|
||||
Ok(pair.into_inner().into_iter().next().unwrap().as_str().to_string())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_quoted_string(pair: Pair<Rule>) -> Result<String> {
|
||||
let pairs = pair.into_inner().next().unwrap().into_inner();
|
||||
let mut ret = String::with_capacity(pairs.as_str().len());
|
||||
for pair in pairs {
|
||||
let s = pair.as_str();
|
||||
match s {
|
||||
r#"\""# => ret.push('"'),
|
||||
r"\\" => ret.push('\\'),
|
||||
r"\/" => ret.push('/'),
|
||||
r"\b" => ret.push('\x08'),
|
||||
r"\f" => ret.push('\x0c'),
|
||||
r"\n" => ret.push('\n'),
|
||||
r"\r" => ret.push('\r'),
|
||||
r"\t" => ret.push('\t'),
|
||||
s if s.starts_with(r"\u") => {
|
||||
let code = parse_int(s, 16) as u32;
|
||||
let ch = char::from_u32(code).ok_or(CozoError::InvalidUtfCode)?;
|
||||
ret.push(ch);
|
||||
}
|
||||
s if s.starts_with('\\') => return Err(CozoError::InvalidEscapeSequence),
|
||||
s => ret.push_str(s)
|
||||
}
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
fn parse_s_quoted_string(pair: Pair<Rule>) -> Result<String> {
|
||||
let pairs = pair.into_inner().next().unwrap().into_inner();
|
||||
let mut ret = String::with_capacity(pairs.as_str().len());
|
||||
for pair in pairs {
|
||||
let s = pair.as_str();
|
||||
match s {
|
||||
r#"\'"# => ret.push('\''),
|
||||
r"\\" => ret.push('\\'),
|
||||
r"\/" => ret.push('/'),
|
||||
r"\b" => ret.push('\x08'),
|
||||
r"\f" => ret.push('\x0c'),
|
||||
r"\n" => ret.push('\n'),
|
||||
r"\r" => ret.push('\r'),
|
||||
r"\t" => ret.push('\t'),
|
||||
s if s.starts_with(r"\u") => {
|
||||
let code = parse_int(s, 16) as u32;
|
||||
let ch = char::from_u32(code).ok_or(CozoError::InvalidUtfCode)?;
|
||||
ret.push(ch);
|
||||
}
|
||||
s if s.starts_with('\\') => return Err(CozoError::InvalidEscapeSequence),
|
||||
s => ret.push_str(s)
|
||||
}
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn parse_string(pair: Pair<Rule>) -> Result<String> {
|
||||
match pair.as_rule() {
|
||||
Rule::quoted_string => Ok(parse_quoted_string(pair)?),
|
||||
Rule::s_quoted_string => Ok(parse_s_quoted_string(pair)?),
|
||||
Rule::raw_string => Ok(parse_raw_string(pair)?),
|
||||
Rule::ident => Ok(pair.as_str().to_string()),
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
fn build_expr_primary(pair: Pair<Rule>) -> Result<Expr> {
|
||||
match pair.as_rule() {
|
||||
Rule::expr => build_expr_primary(pair.into_inner().next().unwrap()),
|
||||
Rule::term => build_expr_primary(pair.into_inner().next().unwrap()),
|
||||
Rule::grouping => build_expr(pair.into_inner().next().unwrap()),
|
||||
|
||||
Rule::unary => {
|
||||
let mut inner = pair.into_inner();
|
||||
let op = inner.next().unwrap().as_rule();
|
||||
let term = build_expr_primary(inner.next().unwrap())?;
|
||||
Ok(Apply(match op {
|
||||
Rule::negate => Op::Neg,
|
||||
Rule::minus => Op::Minus,
|
||||
_ => unreachable!()
|
||||
}, vec![term]))
|
||||
}
|
||||
|
||||
Rule::pos_int => Ok(Const(Value::Int(pair.as_str().replace('_', "").parse::<i64>()?))),
|
||||
Rule::hex_pos_int => Ok(Const(Value::Int(parse_int(pair.as_str(), 16)))),
|
||||
Rule::octo_pos_int => Ok(Const(Value::Int(parse_int(pair.as_str(), 8)))),
|
||||
Rule::bin_pos_int => Ok(Const(Value::Int(parse_int(pair.as_str(), 2)))),
|
||||
Rule::dot_float | Rule::sci_float => Ok(Const(Value::Float(pair.as_str().replace('_', "").parse::<f64>()?))),
|
||||
Rule::null => Ok(Const(Value::Null)),
|
||||
Rule::boolean => Ok(Const(Value::Bool(pair.as_str() == "true"))),
|
||||
Rule::quoted_string | Rule::s_quoted_string | Rule::raw_string => Ok(
|
||||
Const(Value::OwnString(Arc::new(parse_string(pair)?)))),
|
||||
Rule::list => {
|
||||
let mut vals = vec![];
|
||||
let mut has_apply = false;
|
||||
for p in pair.into_inner() {
|
||||
let res = build_expr_primary(p)?;
|
||||
match res {
|
||||
v @ Const(_) => { vals.push(v) }
|
||||
v => {
|
||||
has_apply = true;
|
||||
vals.push(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
if has_apply {
|
||||
Ok(Expr::List(vals))
|
||||
} else {
|
||||
Ok(Const(Value::List(Arc::new(vals.into_iter().map(|v| {
|
||||
match v {
|
||||
Apply(_, _) => { unreachable!() }
|
||||
Expr::List(_) => { unreachable!() }
|
||||
Expr::Dict(_, _) => { unreachable!() }
|
||||
Const(v) => { v }
|
||||
Expr::Ident(_) => unimplemented!()
|
||||
}
|
||||
}).collect()))))
|
||||
}
|
||||
}
|
||||
Rule::dict => {
|
||||
// let mut res = BTreeMap::new();
|
||||
let mut keys = vec![];
|
||||
let mut vals = vec![];
|
||||
let mut has_apply = false;
|
||||
for p in pair.into_inner() {
|
||||
match p.as_rule() {
|
||||
Rule::dict_pair => {
|
||||
let mut inner = p.into_inner();
|
||||
let name = parse_string(inner.next().unwrap())?;
|
||||
keys.push(name);
|
||||
match build_expr_primary(inner.next().unwrap())? {
|
||||
v @ Const(_) => {
|
||||
vals.push(v);
|
||||
}
|
||||
v => {
|
||||
has_apply = true;
|
||||
vals.push(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
if has_apply {
|
||||
Ok(Expr::Dict(keys, vals))
|
||||
} else {
|
||||
Ok(Const(Value::Dict(Arc::new(keys.into_iter().zip(vals.into_iter()).map(|(k, v)| {
|
||||
match v {
|
||||
Expr::List(_) => { unreachable!() }
|
||||
Expr::Dict(_, _) => { unreachable!() }
|
||||
Apply(_, _) => { unreachable!() }
|
||||
Const(v) => {
|
||||
(k.into(), v)
|
||||
}
|
||||
Expr::Ident(_) => unimplemented!()
|
||||
}
|
||||
}).collect()))))
|
||||
}
|
||||
}
|
||||
Rule::param => {
|
||||
Ok(Expr::Ident(pair.as_str().to_string()))
|
||||
}
|
||||
_ => {
|
||||
println!("Unhandled rule {:?}", pair.as_rule());
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_expr(pair: Pair<Rule>) -> Result<Expr> {
|
||||
PREC_CLIMBER.climb(pair.into_inner(), build_expr_primary, build_expr_infix)
|
||||
}
|
||||
|
||||
pub fn parse_expr_from_str(inp: &str) -> Result<Expr> {
|
||||
let expr_tree = Parser::parse(Rule::expr, inp)?.next().unwrap();
|
||||
build_expr(expr_tree)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn raw_string() {
|
||||
println!("{:#?}", parse_expr_from_str(r#####"r#"x"#"#####))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_literals() {
|
||||
assert_eq!(parse_expr_from_str("1").unwrap(), Const(Value::Int(1)));
|
||||
assert_eq!(parse_expr_from_str("12_3").unwrap(), Const(Value::Int(123)));
|
||||
assert_eq!(parse_expr_from_str("0xaf").unwrap(), Const(Value::Int(0xaf)));
|
||||
assert_eq!(parse_expr_from_str("0xafcE_f").unwrap(), Const(Value::Int(0xafcef)));
|
||||
assert_eq!(parse_expr_from_str("0o1234_567").unwrap(), Const(Value::Int(0o1234567)));
|
||||
assert_eq!(parse_expr_from_str("0o0001234_567").unwrap(), Const(Value::Int(0o1234567)));
|
||||
assert_eq!(parse_expr_from_str("0b101010").unwrap(), Const(Value::Int(0b101010)));
|
||||
|
||||
assert_eq!(parse_expr_from_str("0.0").unwrap(), Const(Value::Float(0.)));
|
||||
assert_eq!(parse_expr_from_str("10.022_3").unwrap(), Const(Value::Float(10.0223)));
|
||||
assert_eq!(parse_expr_from_str("10.022_3e-100").unwrap(), Const(Value::Float(10.0223e-100)));
|
||||
|
||||
assert_eq!(parse_expr_from_str("null").unwrap(), Const(Value::Null));
|
||||
assert_eq!(parse_expr_from_str("true").unwrap(), Const(Value::Bool(true)));
|
||||
assert_eq!(parse_expr_from_str("false").unwrap(), Const(Value::Bool(false)));
|
||||
assert_eq!(parse_expr_from_str(r#""x \n \ty \"""#).unwrap(), Const(Value::RefString("x \n \ty \"")));
|
||||
assert_eq!(parse_expr_from_str(r#""x'""#).unwrap(), Const(Value::RefString("x'")));
|
||||
assert_eq!(parse_expr_from_str(r#"'"x"'"#).unwrap(), Const(Value::RefString(r##""x""##)));
|
||||
assert_eq!(parse_expr_from_str(r#####"r###"x"yz"###"#####).unwrap(), Const(Value::RefString(r##"x"yz"##)));
|
||||
}
|
||||
}
|
||||
// use std::borrow::Cow;
|
||||
// use std::sync::Arc;
|
||||
// use pest::iterators::{Pair};
|
||||
// use pest::Parser as PestParser;
|
||||
// use pest::prec_climber::{Assoc, PrecClimber, Operator};
|
||||
// use crate::parser::Parser;
|
||||
// use crate::parser::Rule;
|
||||
// use lazy_static::lazy_static;
|
||||
// use crate::ast::Expr::{Apply, Const};
|
||||
// use crate::error::CozoError;
|
||||
// use crate::error::Result;
|
||||
// use crate::value::Value;
|
||||
//
|
||||
//
|
||||
// #[derive(PartialEq, Debug)]
|
||||
// pub enum Op {
|
||||
// Add,
|
||||
// Sub,
|
||||
// Mul,
|
||||
// Div,
|
||||
// Eq,
|
||||
// Neq,
|
||||
// Gt,
|
||||
// Lt,
|
||||
// Ge,
|
||||
// Le,
|
||||
// Neg,
|
||||
// Minus,
|
||||
// Mod,
|
||||
// Or,
|
||||
// And,
|
||||
// Coalesce,
|
||||
// Pow,
|
||||
// Call,
|
||||
// IsNull,
|
||||
// NotNull,
|
||||
// }
|
||||
//
|
||||
//
|
||||
// lazy_static! {
|
||||
// static ref PREC_CLIMBER: PrecClimber<Rule> = {
|
||||
// use Assoc::*;
|
||||
//
|
||||
// PrecClimber::new(vec![
|
||||
// Operator::new(Rule::op_or, Left),
|
||||
// Operator::new(Rule::op_and, Left),
|
||||
// Operator::new(Rule::op_gt, Left) | Operator::new(Rule::op_lt, Left) | Operator::new(Rule::op_ge,Left) | Operator::new(Rule::op_le, Left),
|
||||
// Operator::new(Rule::op_mod, Left),
|
||||
// Operator::new(Rule::op_eq, Left) | Operator::new(Rule::op_ne, Left),
|
||||
// Operator::new(Rule::op_add, Left) | Operator::new(Rule::op_sub, Left),
|
||||
// Operator::new(Rule::op_mul, Left) | Operator::new(Rule::op_div, Left),
|
||||
// Operator::new(Rule::op_pow, Assoc::Right),
|
||||
// Operator::new(Rule::op_coalesce, Assoc::Left)
|
||||
// ])
|
||||
// };
|
||||
// }
|
||||
//
|
||||
//
|
||||
// #[derive(PartialEq, Debug)]
|
||||
// pub enum Expr<'a> {
|
||||
// List(Vec<Expr<'a>>),
|
||||
// Dict(Vec<String>, Vec<Expr<'a>>),
|
||||
// Apply(Op, Vec<Expr<'a>>),
|
||||
// Ident(String),
|
||||
// Const(Value<'a>),
|
||||
// }
|
||||
//
|
||||
// pub trait ExprVisitor<'a, T> {
|
||||
// fn visit_expr(&self, ex: &Expr<'a>) -> T;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// fn build_expr_infix<'a>(lhs: Result<Expr<'a>>, op: Pair<Rule>, rhs: Result<Expr<'a>>) -> Result<Expr<'a>> {
|
||||
// let lhs = lhs?;
|
||||
// let rhs = rhs?;
|
||||
// let op = match op.as_rule() {
|
||||
// Rule::op_add => Op::Add,
|
||||
// Rule::op_sub => Op::Sub,
|
||||
// Rule::op_mul => Op::Mul,
|
||||
// Rule::op_div => Op::Div,
|
||||
// Rule::op_eq => Op::Eq,
|
||||
// Rule::op_ne => Op::Neq,
|
||||
// Rule::op_or => Op::Or,
|
||||
// Rule::op_and => Op::And,
|
||||
// Rule::op_mod => Op::Mod,
|
||||
// Rule::op_gt => Op::Gt,
|
||||
// Rule::op_ge => Op::Ge,
|
||||
// Rule::op_lt => Op::Lt,
|
||||
// Rule::op_le => Op::Le,
|
||||
// Rule::op_pow => Op::Pow,
|
||||
// Rule::op_coalesce => Op::Coalesce,
|
||||
// _ => unreachable!()
|
||||
// };
|
||||
// Ok(Apply(op, vec![lhs, rhs]))
|
||||
// }
|
||||
//
|
||||
// #[inline]
|
||||
// fn parse_int(s: &str, radix: u32) -> i64 {
|
||||
// i64::from_str_radix(&s[2..].replace('_', ""), radix).unwrap()
|
||||
// }
|
||||
//
|
||||
// #[inline]
|
||||
// fn parse_raw_string(pair: Pair<Rule>) -> Result<String> {
|
||||
// Ok(pair.into_inner().into_iter().next().unwrap().as_str().to_string())
|
||||
// }
|
||||
//
|
||||
// #[inline]
|
||||
// fn parse_quoted_string(pair: Pair<Rule>) -> Result<String> {
|
||||
// let pairs = pair.into_inner().next().unwrap().into_inner();
|
||||
// let mut ret = String::with_capacity(pairs.as_str().len());
|
||||
// for pair in pairs {
|
||||
// let s = pair.as_str();
|
||||
// match s {
|
||||
// r#"\""# => ret.push('"'),
|
||||
// r"\\" => ret.push('\\'),
|
||||
// r"\/" => ret.push('/'),
|
||||
// r"\b" => ret.push('\x08'),
|
||||
// r"\f" => ret.push('\x0c'),
|
||||
// r"\n" => ret.push('\n'),
|
||||
// r"\r" => ret.push('\r'),
|
||||
// r"\t" => ret.push('\t'),
|
||||
// s if s.starts_with(r"\u") => {
|
||||
// let code = parse_int(s, 16) as u32;
|
||||
// let ch = char::from_u32(code).ok_or(CozoError::InvalidUtfCode)?;
|
||||
// ret.push(ch);
|
||||
// }
|
||||
// s if s.starts_with('\\') => return Err(CozoError::InvalidEscapeSequence),
|
||||
// s => ret.push_str(s)
|
||||
// }
|
||||
// }
|
||||
// Ok(ret)
|
||||
// }
|
||||
//
|
||||
//
|
||||
// #[inline]
|
||||
// fn parse_s_quoted_string(pair: Pair<Rule>) -> Result<String> {
|
||||
// let pairs = pair.into_inner().next().unwrap().into_inner();
|
||||
// let mut ret = String::with_capacity(pairs.as_str().len());
|
||||
// for pair in pairs {
|
||||
// let s = pair.as_str();
|
||||
// match s {
|
||||
// r#"\'"# => ret.push('\''),
|
||||
// r"\\" => ret.push('\\'),
|
||||
// r"\/" => ret.push('/'),
|
||||
// r"\b" => ret.push('\x08'),
|
||||
// r"\f" => ret.push('\x0c'),
|
||||
// r"\n" => ret.push('\n'),
|
||||
// r"\r" => ret.push('\r'),
|
||||
// r"\t" => ret.push('\t'),
|
||||
// s if s.starts_with(r"\u") => {
|
||||
// let code = parse_int(s, 16) as u32;
|
||||
// let ch = char::from_u32(code).ok_or(CozoError::InvalidUtfCode)?;
|
||||
// ret.push(ch);
|
||||
// }
|
||||
// s if s.starts_with('\\') => return Err(CozoError::InvalidEscapeSequence),
|
||||
// s => ret.push_str(s)
|
||||
// }
|
||||
// }
|
||||
// Ok(ret)
|
||||
// }
|
||||
//
|
||||
// #[inline]
|
||||
// pub fn parse_string(pair: Pair<Rule>) -> Result<String> {
|
||||
// match pair.as_rule() {
|
||||
// Rule::quoted_string => Ok(parse_quoted_string(pair)?),
|
||||
// Rule::s_quoted_string => Ok(parse_s_quoted_string(pair)?),
|
||||
// Rule::raw_string => Ok(parse_raw_string(pair)?),
|
||||
// Rule::ident => Ok(pair.as_str().to_string()),
|
||||
// _ => unreachable!()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fn build_expr_primary(pair: Pair<Rule>) -> Result<Expr> {
|
||||
// match pair.as_rule() {
|
||||
// Rule::expr => build_expr_primary(pair.into_inner().next().unwrap()),
|
||||
// Rule::term => build_expr_primary(pair.into_inner().next().unwrap()),
|
||||
// Rule::grouping => build_expr(pair.into_inner().next().unwrap()),
|
||||
//
|
||||
// Rule::unary => {
|
||||
// let mut inner = pair.into_inner();
|
||||
// let op = inner.next().unwrap().as_rule();
|
||||
// let term = build_expr_primary(inner.next().unwrap())?;
|
||||
// Ok(Apply(match op {
|
||||
// Rule::negate => Op::Neg,
|
||||
// Rule::minus => Op::Minus,
|
||||
// _ => unreachable!()
|
||||
// }, vec![term]))
|
||||
// }
|
||||
//
|
||||
// Rule::pos_int => Ok(Const(Value::Int(pair.as_str().replace('_', "").parse::<i64>()?))),
|
||||
// Rule::hex_pos_int => Ok(Const(Value::Int(parse_int(pair.as_str(), 16)))),
|
||||
// Rule::octo_pos_int => Ok(Const(Value::Int(parse_int(pair.as_str(), 8)))),
|
||||
// Rule::bin_pos_int => Ok(Const(Value::Int(parse_int(pair.as_str(), 2)))),
|
||||
// Rule::dot_float | Rule::sci_float => Ok(Const(Value::Float(pair.as_str().replace('_', "").parse::<f64>()?))),
|
||||
// Rule::null => Ok(Const(Value::Null)),
|
||||
// Rule::boolean => Ok(Const(Value::Bool(pair.as_str() == "true"))),
|
||||
// Rule::quoted_string | Rule::s_quoted_string | Rule::raw_string => Ok(
|
||||
// Const(Value::Text(Arc::new(Cow::Owned(parse_string(pair)?))))),
|
||||
// Rule::list => {
|
||||
// let mut vals = vec![];
|
||||
// let mut has_apply = false;
|
||||
// for p in pair.into_inner() {
|
||||
// let res = build_expr_primary(p)?;
|
||||
// match res {
|
||||
// v @ Const(_) => { vals.push(v) }
|
||||
// v => {
|
||||
// has_apply = true;
|
||||
// vals.push(v);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if has_apply {
|
||||
// Ok(Expr::List(vals))
|
||||
// } else {
|
||||
// Ok(Const(Value::List(Arc::new(vals.into_iter().map(|v| {
|
||||
// match v {
|
||||
// Apply(_, _) => { unreachable!() }
|
||||
// Expr::List(_) => { unreachable!() }
|
||||
// Expr::Dict(_, _) => { unreachable!() }
|
||||
// Const(v) => { v }
|
||||
// Expr::Ident(_) => unimplemented!()
|
||||
// }
|
||||
// }).collect()))))
|
||||
// }
|
||||
// }
|
||||
// Rule::dict => {
|
||||
// // let mut res = BTreeMap::new();
|
||||
// let mut keys = vec![];
|
||||
// let mut vals = vec![];
|
||||
// let mut has_apply = false;
|
||||
// for p in pair.into_inner() {
|
||||
// match p.as_rule() {
|
||||
// Rule::dict_pair => {
|
||||
// let mut inner = p.into_inner();
|
||||
// let name = parse_string(inner.next().unwrap())?;
|
||||
// keys.push(name);
|
||||
// match build_expr_primary(inner.next().unwrap())? {
|
||||
// v @ Const(_) => {
|
||||
// vals.push(v);
|
||||
// }
|
||||
// v => {
|
||||
// has_apply = true;
|
||||
// vals.push(v);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// _ => todo!()
|
||||
// }
|
||||
// }
|
||||
// if has_apply {
|
||||
// Ok(Expr::Dict(keys, vals))
|
||||
// } else {
|
||||
// Ok(Const(Value::Dict(Arc::new(keys.into_iter().zip(vals.into_iter()).map(|(k, v)| {
|
||||
// match v {
|
||||
// Expr::List(_) => { unreachable!() }
|
||||
// Expr::Dict(_, _) => { unreachable!() }
|
||||
// Apply(_, _) => { unreachable!() }
|
||||
// Const(v) => {
|
||||
// (k.into(), v)
|
||||
// }
|
||||
// Expr::Ident(_) => unimplemented!()
|
||||
// }
|
||||
// }).collect()))))
|
||||
// }
|
||||
// }
|
||||
// Rule::param => {
|
||||
// Ok(Expr::Ident(pair.as_str().to_string()))
|
||||
// }
|
||||
// _ => {
|
||||
// println!("Unhandled rule {:?}", pair.as_rule());
|
||||
// unimplemented!()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// pub fn build_expr(pair: Pair<Rule>) -> Result<Expr> {
|
||||
// PREC_CLIMBER.climb(pair.into_inner(), build_expr_primary, build_expr_infix)
|
||||
// }
|
||||
//
|
||||
// pub fn parse_expr_from_str(inp: &str) -> Result<Expr> {
|
||||
// let expr_tree = Parser::parse(Rule::expr, inp)?.next().unwrap();
|
||||
// build_expr(expr_tree)
|
||||
// }
|
||||
//
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use super::*;
|
||||
//
|
||||
// #[test]
|
||||
// fn raw_string() {
|
||||
// println!("{:#?}", parse_expr_from_str(r#####"r#"x"#"#####))
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn parse_literals() {
|
||||
// assert_eq!(parse_expr_from_str("1").unwrap(), Const(Value::Int(1)));
|
||||
// assert_eq!(parse_expr_from_str("12_3").unwrap(), Const(Value::Int(123)));
|
||||
// assert_eq!(parse_expr_from_str("0xaf").unwrap(), Const(Value::Int(0xaf)));
|
||||
// assert_eq!(parse_expr_from_str("0xafcE_f").unwrap(), Const(Value::Int(0xafcef)));
|
||||
// assert_eq!(parse_expr_from_str("0o1234_567").unwrap(), Const(Value::Int(0o1234567)));
|
||||
// assert_eq!(parse_expr_from_str("0o0001234_567").unwrap(), Const(Value::Int(0o1234567)));
|
||||
// assert_eq!(parse_expr_from_str("0b101010").unwrap(), Const(Value::Int(0b101010)));
|
||||
//
|
||||
// assert_eq!(parse_expr_from_str("0.0").unwrap(), Const(Value::Float(0.)));
|
||||
// assert_eq!(parse_expr_from_str("10.022_3").unwrap(), Const(Value::Float(10.0223)));
|
||||
// assert_eq!(parse_expr_from_str("10.022_3e-100").unwrap(), Const(Value::Float(10.0223e-100)));
|
||||
//
|
||||
// assert_eq!(parse_expr_from_str("null").unwrap(), Const(Value::Null));
|
||||
// assert_eq!(parse_expr_from_str("true").unwrap(), Const(Value::Bool(true)));
|
||||
// assert_eq!(parse_expr_from_str("false").unwrap(), Const(Value::Bool(false)));
|
||||
// assert_eq!(parse_expr_from_str(r#""x \n \ty \"""#).unwrap(), Const(Value::Text(Arc::new(Cow::Borrowed("x \n \ty \"")))));
|
||||
// // assert_eq!(parse_expr_from_str(r#""x'""#).unwrap(), Const(Value::RefString("x'")));
|
||||
// // assert_eq!(parse_expr_from_str(r#"'"x"'"#).unwrap(), Const(Value::RefString(r##""x""##)));
|
||||
// // assert_eq!(parse_expr_from_str(r#####"r###"x"yz"###"#####).unwrap(), Const(Value::RefString(r##"x"yz"##)));
|
||||
// }
|
||||
// }
|
File diff suppressed because it is too large
Load Diff
@ -1,61 +1,61 @@
|
||||
use std::borrow::Cow;
|
||||
use std::collections::BTreeMap;
|
||||
use crate::typing::{Structured};
|
||||
|
||||
pub trait Env<V> where V: Clone {
|
||||
fn define(&mut self, name: String, value: V) -> Option<V>;
|
||||
fn define_new(&mut self, name: String, value: V) -> bool;
|
||||
fn resolve(&self, name: &str) -> Option<Cow<V>>;
|
||||
fn resolve_mut(&mut self, name: &str) -> Option<&mut V>;
|
||||
fn undef(&mut self, name: &str) -> Option<V>;
|
||||
}
|
||||
|
||||
pub trait LayeredEnv<V>: Env<V> where V: Clone {
|
||||
fn root_define(&mut self, name: String, value: V) -> Option<V>;
|
||||
fn root_define_new(&mut self, name: String, value: V) -> bool;
|
||||
fn root_resolve(&self, name: &str) -> Option<Cow<V>>;
|
||||
fn root_undef(&mut self, name: &str) -> Option<V>;
|
||||
}
|
||||
|
||||
|
||||
pub struct Environment {
|
||||
map: BTreeMap<String, Structured>,
|
||||
}
|
||||
|
||||
|
||||
impl Default for Environment {
|
||||
fn default() -> Self {
|
||||
Self { map: BTreeMap::new() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Env<Structured> for Environment {
|
||||
fn define(&mut self, name: String, value: Structured) -> Option<Structured> {
|
||||
let old = self.map.remove(&name);
|
||||
self.map.insert(name, value);
|
||||
old
|
||||
}
|
||||
|
||||
fn define_new(&mut self, name: String, value: Structured) -> bool {
|
||||
if let std::collections::btree_map::Entry::Vacant(e) = self.map.entry(name) {
|
||||
e.insert(value);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve(&self, name: &str) -> Option<Cow<Structured>> {
|
||||
self.map.get(name)
|
||||
.map(|v| Cow::Borrowed(v))
|
||||
}
|
||||
|
||||
fn resolve_mut(&mut self, name: &str) -> Option<&mut Structured> {
|
||||
self.map.get_mut(name)
|
||||
}
|
||||
|
||||
|
||||
fn undef(&mut self, name: &str) -> Option<Structured> {
|
||||
self.map.remove(name)
|
||||
}
|
||||
}
|
||||
// use std::borrow::Cow;
|
||||
// use std::collections::BTreeMap;
|
||||
// use crate::typing::{Structured};
|
||||
//
|
||||
// pub trait Env<V> where V: Clone {
|
||||
// fn define(&mut self, name: String, value: V) -> Option<V>;
|
||||
// fn define_new(&mut self, name: String, value: V) -> bool;
|
||||
// fn resolve(&self, name: &str) -> Option<Cow<V>>;
|
||||
// fn resolve_mut(&mut self, name: &str) -> Option<&mut V>;
|
||||
// fn undef(&mut self, name: &str) -> Option<V>;
|
||||
// }
|
||||
//
|
||||
// pub trait LayeredEnv<V>: Env<V> where V: Clone {
|
||||
// fn root_define(&mut self, name: String, value: V) -> Option<V>;
|
||||
// fn root_define_new(&mut self, name: String, value: V) -> bool;
|
||||
// fn root_resolve(&self, name: &str) -> Option<Cow<V>>;
|
||||
// fn root_undef(&mut self, name: &str) -> Option<V>;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// pub struct Environment {
|
||||
// map: BTreeMap<String, Structured>,
|
||||
// }
|
||||
//
|
||||
//
|
||||
// impl Default for Environment {
|
||||
// fn default() -> Self {
|
||||
// Self { map: BTreeMap::new() }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl Env<Structured> for Environment {
|
||||
// fn define(&mut self, name: String, value: Structured) -> Option<Structured> {
|
||||
// let old = self.map.remove(&name);
|
||||
// self.map.insert(name, value);
|
||||
// old
|
||||
// }
|
||||
//
|
||||
// fn define_new(&mut self, name: String, value: Structured) -> bool {
|
||||
// if let std::collections::btree_map::Entry::Vacant(e) = self.map.entry(name) {
|
||||
// e.insert(value);
|
||||
// true
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fn resolve(&self, name: &str) -> Option<Cow<Structured>> {
|
||||
// self.map.get(name)
|
||||
// .map(|v| Cow::Borrowed(v))
|
||||
// }
|
||||
//
|
||||
// fn resolve_mut(&mut self, name: &str) -> Option<&mut Structured> {
|
||||
// self.map.get_mut(name)
|
||||
// }
|
||||
//
|
||||
//
|
||||
// fn undef(&mut self, name: &str) -> Option<Structured> {
|
||||
// self.map.remove(name)
|
||||
// }
|
||||
// }
|
||||
|
@ -1,65 +1,65 @@
|
||||
use std::result;
|
||||
use thiserror::Error;
|
||||
use crate::parser::Rule;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum CozoError {
|
||||
#[error("Invalid UTF code")]
|
||||
InvalidUtfCode,
|
||||
|
||||
#[error("Invalid escape sequence")]
|
||||
InvalidEscapeSequence,
|
||||
|
||||
#[error("Type mismatch")]
|
||||
TypeError,
|
||||
|
||||
#[error("Reserved identifier")]
|
||||
ReservedIdent,
|
||||
|
||||
#[error("The requested name exists")]
|
||||
NameConflict,
|
||||
|
||||
#[error("Undefined type")]
|
||||
UndefinedType,
|
||||
|
||||
#[error("Undefined table")]
|
||||
UndefinedTable,
|
||||
|
||||
#[error("Undefined parameter")]
|
||||
UndefinedParam,
|
||||
|
||||
#[error("Value required")]
|
||||
ValueRequired,
|
||||
|
||||
#[error("Incompatible value")]
|
||||
IncompatibleValue,
|
||||
|
||||
#[error("Wrong type")]
|
||||
WrongType,
|
||||
|
||||
#[error("Cannot have global edge between local nodes")]
|
||||
IncompatibleEdge,
|
||||
|
||||
#[error("Unexpected index columns found")]
|
||||
UnexpectedIndexColumns,
|
||||
|
||||
#[error("Database already closed")]
|
||||
DatabaseClosed,
|
||||
|
||||
#[error(transparent)]
|
||||
ParseInt(#[from] std::num::ParseIntError),
|
||||
|
||||
#[error(transparent)]
|
||||
ParseFloat(#[from] std::num::ParseFloatError),
|
||||
|
||||
#[error(transparent)]
|
||||
Parse(#[from] pest::error::Error<Rule>),
|
||||
|
||||
#[error(transparent)]
|
||||
Storage(#[from] cozo_rocks::BridgeStatus),
|
||||
|
||||
#[error(transparent)]
|
||||
Io(#[from] std::io::Error),
|
||||
}
|
||||
|
||||
pub type Result<T> = result::Result<T, CozoError>;
|
||||
// use std::result;
|
||||
// use thiserror::Error;
|
||||
// use crate::parser::Rule;
|
||||
//
|
||||
// #[derive(Error, Debug)]
|
||||
// pub enum CozoError {
|
||||
// #[error("Invalid UTF code")]
|
||||
// InvalidUtfCode,
|
||||
//
|
||||
// #[error("Invalid escape sequence")]
|
||||
// InvalidEscapeSequence,
|
||||
//
|
||||
// #[error("Type mismatch")]
|
||||
// TypeError,
|
||||
//
|
||||
// #[error("Reserved identifier")]
|
||||
// ReservedIdent,
|
||||
//
|
||||
// #[error("The requested name exists")]
|
||||
// NameConflict,
|
||||
//
|
||||
// #[error("Undefined type")]
|
||||
// UndefinedType,
|
||||
//
|
||||
// #[error("Undefined table")]
|
||||
// UndefinedTable,
|
||||
//
|
||||
// #[error("Undefined parameter")]
|
||||
// UndefinedParam,
|
||||
//
|
||||
// #[error("Value required")]
|
||||
// ValueRequired,
|
||||
//
|
||||
// #[error("Incompatible value")]
|
||||
// IncompatibleValue,
|
||||
//
|
||||
// #[error("Wrong type")]
|
||||
// WrongType,
|
||||
//
|
||||
// #[error("Cannot have global edge between local nodes")]
|
||||
// IncompatibleEdge,
|
||||
//
|
||||
// #[error("Unexpected index columns found")]
|
||||
// UnexpectedIndexColumns,
|
||||
//
|
||||
// #[error("Database already closed")]
|
||||
// DatabaseClosed,
|
||||
//
|
||||
// #[error(transparent)]
|
||||
// ParseInt(#[from] std::num::ParseIntError),
|
||||
//
|
||||
// #[error(transparent)]
|
||||
// ParseFloat(#[from] std::num::ParseFloatError),
|
||||
//
|
||||
// #[error(transparent)]
|
||||
// Parse(#[from] pest::error::Error<Rule>),
|
||||
//
|
||||
// #[error(transparent)]
|
||||
// Storage(#[from] cozo_rocks::BridgeStatus),
|
||||
//
|
||||
// #[error(transparent)]
|
||||
// Io(#[from] std::io::Error),
|
||||
// }
|
||||
//
|
||||
// pub type Result<T> = result::Result<T, CozoError>;
|
File diff suppressed because it is too large
Load Diff
@ -1,72 +1,72 @@
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use crate::typing::{Typing};
|
||||
use crate::value::{StaticValue, Value};
|
||||
// use lazy_static::lazy_static;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct Function {
|
||||
pub args: Vec<Arg>,
|
||||
pub var_arg: Option<Typing>,
|
||||
pub ret_type: Typing,
|
||||
pub fn_impl: FunctionImpl,
|
||||
}
|
||||
|
||||
pub enum FunctionImpl {
|
||||
Native(&'static str, for<'a> fn(&[Value<'a>]) -> Value<'a>),
|
||||
UserDefined(()),
|
||||
}
|
||||
|
||||
impl Debug for FunctionImpl {
|
||||
fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for FunctionImpl {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(FunctionImpl::Native(a,_), FunctionImpl::Native(b,_)) => a == b,
|
||||
(FunctionImpl::UserDefined(a), FunctionImpl::UserDefined(b)) => a == b,
|
||||
(_, _) => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct Arg {
|
||||
pub typing: Typing,
|
||||
pub default_val: Option<StaticValue>,
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
// lazy_static! {
|
||||
// static ref BUILT_IN_FUNCTIONS : BTreeMap<&'static str, Function> = {
|
||||
// let mut ret = BTreeMap::new();
|
||||
// use std::fmt::{Debug, Formatter};
|
||||
// use crate::typing::{Typing};
|
||||
// use crate::value::{StaticValue, Value};
|
||||
// // use lazy_static::lazy_static;
|
||||
//
|
||||
// fn add_int<'a>(_args: &[Value<'a>]) -> Value<'a> {
|
||||
// todo!()
|
||||
// }
|
||||
// #[derive(PartialEq, Debug)]
|
||||
// pub struct Function {
|
||||
// pub args: Vec<Arg>,
|
||||
// pub var_arg: Option<Typing>,
|
||||
// pub ret_type: Typing,
|
||||
// pub fn_impl: FunctionImpl,
|
||||
// }
|
||||
//
|
||||
// fn add_float<'a>(_args: &[Value<'a>]) -> Value<'a> {
|
||||
// todo!()
|
||||
// }
|
||||
// pub enum FunctionImpl {
|
||||
// Native(&'static str, for<'a> fn(&[Value<'a>]) -> Value<'a>),
|
||||
// UserDefined(()),
|
||||
// }
|
||||
//
|
||||
// ret.insert("_add_int",
|
||||
// Function {
|
||||
// args: vec![],
|
||||
// var_arg: Some(Typing::Base(BaseType::Int)),
|
||||
// ret_type: Typing::Base(BaseType::Int),
|
||||
// fn_impl: FunctionImpl::Native("_add_int", add_int)
|
||||
// });
|
||||
// impl Debug for FunctionImpl {
|
||||
// fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
// todo!()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// ret.insert("_add_float",
|
||||
// Function {
|
||||
// args: vec![],
|
||||
// var_arg: Some(Typing::Base(BaseType::Float)),
|
||||
// ret_type: Typing::Base(BaseType::Float),
|
||||
// fn_impl: FunctionImpl::Native("_add_float", add_float)
|
||||
// });
|
||||
// impl PartialEq for FunctionImpl {
|
||||
// fn eq(&self, other: &Self) -> bool {
|
||||
// match (self, other) {
|
||||
// (FunctionImpl::Native(a,_), FunctionImpl::Native(b,_)) => a == b,
|
||||
// (FunctionImpl::UserDefined(a), FunctionImpl::UserDefined(b)) => a == b,
|
||||
// (_, _) => false
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// ret
|
||||
// };
|
||||
// #[derive(PartialEq, Debug)]
|
||||
// pub struct Arg {
|
||||
// pub typing: Typing,
|
||||
// pub default_val: Option<StaticValue>,
|
||||
// pub name: Option<String>,
|
||||
// }
|
||||
//
|
||||
// // lazy_static! {
|
||||
// // static ref BUILT_IN_FUNCTIONS : BTreeMap<&'static str, Function> = {
|
||||
// // let mut ret = BTreeMap::new();
|
||||
// //
|
||||
// // fn add_int<'a>(_args: &[Value<'a>]) -> Value<'a> {
|
||||
// // todo!()
|
||||
// // }
|
||||
// //
|
||||
// // fn add_float<'a>(_args: &[Value<'a>]) -> Value<'a> {
|
||||
// // todo!()
|
||||
// // }
|
||||
// //
|
||||
// // ret.insert("_add_int",
|
||||
// // Function {
|
||||
// // args: vec![],
|
||||
// // var_arg: Some(Typing::Base(BaseType::Int)),
|
||||
// // ret_type: Typing::Base(BaseType::Int),
|
||||
// // fn_impl: FunctionImpl::Native("_add_int", add_int)
|
||||
// // });
|
||||
// //
|
||||
// // ret.insert("_add_float",
|
||||
// // Function {
|
||||
// // args: vec![],
|
||||
// // var_arg: Some(Typing::Base(BaseType::Float)),
|
||||
// // ret_type: Typing::Base(BaseType::Float),
|
||||
// // fn_impl: FunctionImpl::Native("_add_float", add_float)
|
||||
// // });
|
||||
// //
|
||||
// // ret
|
||||
// // };
|
||||
// // }
|
||||
|
@ -1,97 +1,97 @@
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::BTreeMap;
|
||||
use pest::iterators::Pair;
|
||||
use crate::ast::{build_expr, Expr, ExprVisitor};
|
||||
use crate::definition::build_name_in_def;
|
||||
use crate::env::Env;
|
||||
use crate::error::CozoError::{IncompatibleValue, UndefinedTable, ValueRequired};
|
||||
use crate::eval::Evaluator;
|
||||
use crate::storage::{RocksStorage};
|
||||
use crate::error::Result;
|
||||
use crate::parser::{Parser, Rule};
|
||||
use crate::typing::Structured;
|
||||
use crate::value::Value;
|
||||
|
||||
impl Evaluator<RocksStorage> {
|
||||
pub fn eval_mutation(&mut self, pair: Pair<Rule>) -> Result<()> {
|
||||
let mut pairs = pair.into_inner();
|
||||
let op = pairs.next().unwrap().as_rule();
|
||||
let expr = pairs.next().unwrap();
|
||||
let main_target;
|
||||
// let filters;
|
||||
match pairs.next() {
|
||||
None => {
|
||||
main_target = None;
|
||||
// filters = None;
|
||||
}
|
||||
Some(v) => {
|
||||
match v.as_rule() {
|
||||
Rule::name_in_def => {
|
||||
// let resolved = self.resolve(&build_name_in_def(v, true)?)
|
||||
// .ok_or(UndefinedTable)?.borrow();
|
||||
// main_target = Some(resolved);
|
||||
todo!()
|
||||
}
|
||||
Rule::mutation_filter => {
|
||||
main_target = None;
|
||||
todo!()
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
let expr = build_expr(expr)?;
|
||||
let expr = self.visit_expr(&expr)?;
|
||||
let val = match expr {
|
||||
Expr::Const(v) => v,
|
||||
_ => return Err(ValueRequired)
|
||||
};
|
||||
let val = val.get_list().ok_or(IncompatibleValue)?;
|
||||
println!("{:#?}", val);
|
||||
let coerced_values = self.coerce_table_values(&val, main_target);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn coerce_table_values(&self, values: &[Value], default_table: Option<&Structured>) -> BTreeMap<&Structured, Vec<Value>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::fs;
|
||||
use super::*;
|
||||
use crate::ast::{Expr, ExprVisitor, parse_expr_from_str};
|
||||
use pest::Parser as PestParser;
|
||||
use crate::env::Env;
|
||||
use crate::storage::DummyStorage;
|
||||
use crate::typing::Structured;
|
||||
|
||||
#[test]
|
||||
fn data() -> Result<()> {
|
||||
let ddl = fs::read_to_string("test_data/hr.cozo")?;
|
||||
let parsed = Parser::parse(Rule::file, &ddl).unwrap();
|
||||
let db = RocksStorage::new("_path_hr".to_string())?;
|
||||
let mut eval = Evaluator::new(db).unwrap();
|
||||
eval.build_table(parsed).unwrap();
|
||||
eval.restore_metadata().unwrap();
|
||||
|
||||
let insertion = "insert $data;";
|
||||
let mut insert_stmt = Parser::parse(Rule::mutation, insertion).unwrap();
|
||||
|
||||
let data = fs::read_to_string("test_data/hr.json")?;
|
||||
let parsed = parse_expr_from_str(&data)?;
|
||||
let ev = Evaluator::new(DummyStorage {})?;
|
||||
let evaluated = ev.visit_expr(&parsed)?;
|
||||
let bound_value = match evaluated {
|
||||
Expr::Const(v) => v,
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
eval.define("$data".to_string(), Structured::Value(bound_value.owned_clone()));
|
||||
eval.eval_mutation(insert_stmt.next().unwrap()).unwrap();
|
||||
// println!("{:#?}", evaluated);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
// use std::borrow::Borrow;
|
||||
// use std::collections::BTreeMap;
|
||||
// use pest::iterators::Pair;
|
||||
// use crate::ast::{build_expr, Expr, ExprVisitor};
|
||||
// use crate::definition::build_name_in_def;
|
||||
// use crate::env::Env;
|
||||
// use crate::error::CozoError::{IncompatibleValue, UndefinedTable, ValueRequired};
|
||||
// use crate::eval::Evaluator;
|
||||
// use crate::storage::{RocksStorage};
|
||||
// use crate::error::Result;
|
||||
// use crate::parser::{Parser, Rule};
|
||||
// use crate::typing::Structured;
|
||||
// use crate::value::Value;
|
||||
//
|
||||
// impl Evaluator<RocksStorage> {
|
||||
// pub fn eval_mutation(&mut self, pair: Pair<Rule>) -> Result<()> {
|
||||
// let mut pairs = pair.into_inner();
|
||||
// let op = pairs.next().unwrap().as_rule();
|
||||
// let expr = pairs.next().unwrap();
|
||||
// let main_target;
|
||||
// // let filters;
|
||||
// match pairs.next() {
|
||||
// None => {
|
||||
// main_target = None;
|
||||
// // filters = None;
|
||||
// }
|
||||
// Some(v) => {
|
||||
// match v.as_rule() {
|
||||
// Rule::name_in_def => {
|
||||
// // let resolved = self.resolve(&build_name_in_def(v, true)?)
|
||||
// // .ok_or(UndefinedTable)?.borrow();
|
||||
// // main_target = Some(resolved);
|
||||
// todo!()
|
||||
// }
|
||||
// Rule::mutation_filter => {
|
||||
// main_target = None;
|
||||
// todo!()
|
||||
// }
|
||||
// _ => unreachable!()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// let expr = build_expr(expr)?;
|
||||
// let expr = self.visit_expr(&expr)?;
|
||||
// let val = match expr {
|
||||
// Expr::Const(v) => v,
|
||||
// _ => return Err(ValueRequired)
|
||||
// };
|
||||
// let val = val.get_list().ok_or(IncompatibleValue)?;
|
||||
// println!("{:#?}", val);
|
||||
// let coerced_values = self.coerce_table_values(&val, main_target);
|
||||
// Ok(())
|
||||
// }
|
||||
//
|
||||
// fn coerce_table_values(&self, values: &[Value], default_table: Option<&Structured>) -> BTreeMap<&Structured, Vec<Value>> {
|
||||
// todo!()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use std::fs;
|
||||
// use super::*;
|
||||
// use crate::ast::{Expr, ExprVisitor, parse_expr_from_str};
|
||||
// use pest::Parser as PestParser;
|
||||
// use crate::env::Env;
|
||||
// use crate::storage::DummyStorage;
|
||||
// use crate::typing::Structured;
|
||||
//
|
||||
// #[test]
|
||||
// fn data() -> Result<()> {
|
||||
// let ddl = fs::read_to_string("test_data/hr.cozo")?;
|
||||
// let parsed = Parser::parse(Rule::file, &ddl).unwrap();
|
||||
// let db = RocksStorage::new("_path_hr".to_string())?;
|
||||
// let mut eval = Evaluator::new(db).unwrap();
|
||||
// eval.build_table(parsed).unwrap();
|
||||
// eval.restore_metadata().unwrap();
|
||||
//
|
||||
// let insertion = "insert $data;";
|
||||
// let mut insert_stmt = Parser::parse(Rule::mutation, insertion).unwrap();
|
||||
//
|
||||
// let data = fs::read_to_string("test_data/hr.json")?;
|
||||
// let parsed = parse_expr_from_str(&data)?;
|
||||
// let ev = Evaluator::new(DummyStorage {})?;
|
||||
// let evaluated = ev.visit_expr(&parsed)?;
|
||||
// let bound_value = match evaluated {
|
||||
// Expr::Const(v) => v,
|
||||
// _ => unreachable!()
|
||||
// };
|
||||
//
|
||||
// eval.define("$data".to_string(), Structured::Value(bound_value.owned_clone()));
|
||||
// eval.eval_mutation(insert_stmt.next().unwrap()).unwrap();
|
||||
// // println!("{:#?}", evaluated);
|
||||
// Ok(())
|
||||
// }
|
||||
// }
|
@ -0,0 +1 @@
|
||||
pub mod tuple;
|
@ -0,0 +1,579 @@
|
||||
use std::borrow::{Cow};
|
||||
use std::cell::RefCell;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BTreeMap;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Ord, PartialOrd, Eq, PartialEq)]
|
||||
pub enum Tag {
|
||||
BoolFalse = 0,
|
||||
Null = 2,
|
||||
BoolTrue = 4,
|
||||
FwdEdge = 6,
|
||||
BwdEdge = 8,
|
||||
Int = 11,
|
||||
Float = 13,
|
||||
Text = 15,
|
||||
Uuid = 17,
|
||||
UInt = 21,
|
||||
List = 101,
|
||||
Dict = 103,
|
||||
// Timestamp = 23,
|
||||
// Datetime = 25,
|
||||
// Timezone = 27,
|
||||
// Date = 27,
|
||||
// Time = 29,
|
||||
// Duration = 31,
|
||||
// BigInt = 51,
|
||||
// BigDecimal = 53,
|
||||
// Inet = 55,
|
||||
// Crs = 57,
|
||||
// BitArr = 60,
|
||||
// U8Arr = 61,
|
||||
// I8Arr = 62,
|
||||
// U16Arr = 63,
|
||||
// I16Arr = 64,
|
||||
// U32Arr = 65,
|
||||
// I32Arr = 66,
|
||||
// U64Arr = 67,
|
||||
// I64Arr = 68,
|
||||
// F16Arr = 69,
|
||||
// F32Arr = 70,
|
||||
// F64Arr = 71,
|
||||
// C32Arr = 72,
|
||||
// C64Arr = 73,
|
||||
// C128Arr = 74,
|
||||
}
|
||||
|
||||
impl From<u8> for Tag {
|
||||
fn from(u: u8) -> Self {
|
||||
use self::Tag::*;
|
||||
match u {
|
||||
0 => BoolFalse,
|
||||
2 => Null,
|
||||
4 => BoolTrue,
|
||||
6 => FwdEdge,
|
||||
8 => BwdEdge,
|
||||
11 => Int,
|
||||
13 => Float,
|
||||
15 => Text,
|
||||
17 => Uuid,
|
||||
21 => UInt,
|
||||
101 => List,
|
||||
103 => Dict,
|
||||
_ => panic!("Unexpected value tag {}", u)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum EdgeDir {
|
||||
Fwd,
|
||||
Bwd,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Value<'a> {
|
||||
Null,
|
||||
Bool(bool),
|
||||
EdgeDir(EdgeDir),
|
||||
UInt(u64),
|
||||
Int(i64),
|
||||
Float(f64),
|
||||
Uuid(Uuid),
|
||||
Text(Cow<'a, str>),
|
||||
List(Vec<Value<'a>>),
|
||||
Dict(BTreeMap<Cow<'a, str>, Value<'a>>),
|
||||
}
|
||||
|
||||
impl From<()> for Value<'static> {
|
||||
fn from(_: ()) -> Self {
|
||||
Value::Null
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for Value<'static> {
|
||||
fn from(b: bool) -> Self {
|
||||
Value::Bool(b)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EdgeDir> for Value<'static> {
|
||||
fn from(e: EdgeDir) -> Self {
|
||||
Value::EdgeDir(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for Value<'static> {
|
||||
fn from(u: u64) -> Self {
|
||||
Value::UInt(u)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for Value<'static> {
|
||||
fn from(i: i64) -> Self {
|
||||
Value::Int(i)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for Value<'static> {
|
||||
fn from(f: f64) -> Self {
|
||||
Value::Float(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for Value<'a> {
|
||||
fn from(s: &'a str) -> Self {
|
||||
Value::Text(Cow::Borrowed(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Value<'static> {
|
||||
fn from(s: String) -> Self {
|
||||
Value::Text(Cow::Owned(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Uuid> for Value<'static> {
|
||||
fn from(u: Uuid) -> Self {
|
||||
Value::Uuid(u)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Vec<Value<'a>>> for Value<'a> {
|
||||
fn from(v: Vec<Value<'a>>) -> Self {
|
||||
Value::List(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<BTreeMap<Cow<'a, str>, Value<'a>>> for Value<'a> {
|
||||
fn from(m: BTreeMap<Cow<'a, str>, Value<'a>>) -> Self {
|
||||
Value::Dict(m)
|
||||
}
|
||||
}
|
||||
|
||||
pub type StaticValue = Value<'static>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Tuple<T>
|
||||
where T: AsRef<[u8]>
|
||||
{
|
||||
pub data: T,
|
||||
idx_cache: RefCell<Vec<usize>>,
|
||||
}
|
||||
|
||||
const PREFIX_LEN: usize = 4;
|
||||
|
||||
impl<T: AsRef<[u8]>> Tuple<T> {
|
||||
fn new(data: T) -> Self {
|
||||
Self {
|
||||
data,
|
||||
idx_cache: RefCell::new(vec![]),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn all_cached(&self) -> bool {
|
||||
match self.idx_cache.borrow().last() {
|
||||
None => self.data.as_ref().len() == PREFIX_LEN,
|
||||
Some(l) => *l == self.data.as_ref().len()
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn get_pos(&self, idx: usize) -> Option<usize> {
|
||||
if idx == 0 {
|
||||
if self.data.as_ref().len() > PREFIX_LEN {
|
||||
Some(PREFIX_LEN)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
self.cache_until(idx);
|
||||
self.idx_cache.borrow().get(idx - 1).cloned()
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn cache_until(&self, idx: usize) {
|
||||
while self.idx_cache.borrow().len() < idx && !self.all_cached() {
|
||||
self.skip_and_cache();
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn skip_and_cache(&self) {
|
||||
let data = self.data.as_ref();
|
||||
let tag_start = *self.idx_cache.borrow().last().unwrap_or(&PREFIX_LEN);
|
||||
let start = tag_start + 1;
|
||||
let nxt = match Tag::from(data[tag_start]) {
|
||||
Tag::Null | Tag::BoolTrue | Tag::BoolFalse | Tag::FwdEdge | Tag::BwdEdge => start,
|
||||
Tag::Int | Tag::UInt => start + self.parse_varint(start).1,
|
||||
Tag::Float => start + 8,
|
||||
Tag::Uuid => start + 16,
|
||||
Tag::Text => {
|
||||
let (slen, offset) = self.parse_varint(start);
|
||||
let slen = slen as usize;
|
||||
start + slen + offset
|
||||
}
|
||||
Tag::List => start + u32::from_be_bytes(data[start..start + 4].try_into().unwrap()) as usize,
|
||||
Tag::Dict => start + u32::from_be_bytes(data[start..start + 4].try_into().unwrap()) as usize
|
||||
};
|
||||
self.idx_cache.borrow_mut().push(nxt);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_varint(&self, idx: usize) -> (u64, usize) {
|
||||
let data = self.data.as_ref();
|
||||
let mut cur = idx;
|
||||
let mut u: u64 = 0;
|
||||
let mut shift = 0;
|
||||
loop {
|
||||
let buf = data[cur];
|
||||
cur += 1;
|
||||
u |= ((buf & 0b01111111) as u64) << shift;
|
||||
if buf & 0b10000000 == 0 {
|
||||
break;
|
||||
}
|
||||
shift += 7;
|
||||
}
|
||||
(u, cur - idx)
|
||||
}
|
||||
|
||||
pub fn get(&self, idx: usize) -> Option<Value> {
|
||||
match self.get_pos(idx) {
|
||||
Some(v) => {
|
||||
if v == self.data.as_ref().len() {
|
||||
return None;
|
||||
}
|
||||
let (val, nxt) = self.parse_value_at(v);
|
||||
if idx == self.idx_cache.borrow().len() {
|
||||
self.idx_cache.borrow_mut().push(nxt);
|
||||
}
|
||||
Some(val)
|
||||
}
|
||||
None => None
|
||||
}
|
||||
}
|
||||
pub fn parse_value_at(&self, pos: usize) -> (Value, usize) {
|
||||
let data = self.data.as_ref();
|
||||
let start = pos + 1;
|
||||
let (nxt, val): (usize, Value) = match Tag::from(data[pos]) {
|
||||
Tag::Null => (start, ().into()),
|
||||
Tag::BoolTrue => (start, true.into()),
|
||||
Tag::BoolFalse => (start, false.into()),
|
||||
Tag::FwdEdge => (start, EdgeDir::Fwd.into()),
|
||||
Tag::BwdEdge => (start, EdgeDir::Bwd.into()),
|
||||
Tag::UInt => {
|
||||
let (u, offset) = self.parse_varint(start);
|
||||
(start + offset, u.into())
|
||||
}
|
||||
Tag::Int => {
|
||||
let (u, offset) = self.parse_varint(start);
|
||||
let val = if u & 1 == 0 {
|
||||
(u >> 1) as i64
|
||||
} else {
|
||||
-((u >> 1) as i64) - 1
|
||||
};
|
||||
(start + offset, val.into())
|
||||
}
|
||||
Tag::Float => (start + 8, f64::from_be_bytes(data[start..start + 8].try_into().unwrap()).into()),
|
||||
Tag::Uuid => (start + 16, Uuid::from_slice(&data[start..start + 16]).unwrap().into()),
|
||||
Tag::Text => {
|
||||
let (slen, offset) = self.parse_varint(start);
|
||||
let slen = slen as usize;
|
||||
let s = unsafe {
|
||||
std::str::from_utf8_unchecked(&data[start + offset..start + offset + slen])
|
||||
};
|
||||
|
||||
(start + slen + offset, s.into())
|
||||
}
|
||||
Tag::List => {
|
||||
let end_pos = start + u32::from_be_bytes(data[start..start + 4].try_into().unwrap()) as usize;
|
||||
let mut start_pos = start + 4;
|
||||
let mut collected = vec![];
|
||||
while start_pos < end_pos {
|
||||
let (val, new_pos) = self.parse_value_at(start_pos);
|
||||
collected.push(val);
|
||||
start_pos = new_pos;
|
||||
}
|
||||
(end_pos, collected.into())
|
||||
}
|
||||
Tag::Dict => {
|
||||
let end_pos = start + u32::from_be_bytes(data[start..start + 4].try_into().unwrap()) as usize;
|
||||
let mut start_pos = start + 4;
|
||||
let mut collected: BTreeMap<Cow<str>, Value> = BTreeMap::new();
|
||||
while start_pos < end_pos {
|
||||
let (slen, offset) = self.parse_varint(start_pos);
|
||||
start_pos += offset;
|
||||
let key = unsafe {
|
||||
std::str::from_utf8_unchecked(&data[start_pos..start_pos + slen as usize])
|
||||
};
|
||||
start_pos += slen as usize;
|
||||
let (val, new_pos) = self.parse_value_at(start_pos);
|
||||
collected.insert(key.into(), val);
|
||||
start_pos = new_pos;
|
||||
}
|
||||
(end_pos, collected.into())
|
||||
}
|
||||
};
|
||||
(val, nxt)
|
||||
}
|
||||
}
|
||||
|
||||
impl Tuple<&[u8]> {}
|
||||
|
||||
|
||||
impl Tuple<Vec<u8>> {
|
||||
pub fn with_prefix(prefix: u32) -> Self {
|
||||
let data = Vec::from(prefix.to_be_bytes());
|
||||
Self {
|
||||
data,
|
||||
idx_cache: RefCell::new(vec![]),
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn push_tag(&mut self, tag: Tag) {
|
||||
self.data.push(tag as u8);
|
||||
}
|
||||
#[inline]
|
||||
pub fn push_null(&mut self) {
|
||||
self.push_tag(Tag::Null);
|
||||
self.idx_cache.borrow_mut().push(self.data.len());
|
||||
}
|
||||
#[inline]
|
||||
pub fn push_bool(&mut self, b: bool) {
|
||||
self.push_tag(if b { Tag::BoolTrue } else { Tag::BoolFalse });
|
||||
self.idx_cache.borrow_mut().push(self.data.len());
|
||||
}
|
||||
#[inline]
|
||||
pub fn push_edge_dir(&mut self, d: EdgeDir) {
|
||||
self.push_tag(match d {
|
||||
EdgeDir::Fwd => { Tag::FwdEdge }
|
||||
EdgeDir::Bwd => { Tag::BwdEdge }
|
||||
});
|
||||
self.idx_cache.borrow_mut().push(self.data.len());
|
||||
}
|
||||
#[inline]
|
||||
pub fn push_int(&mut self, i: i64) {
|
||||
self.push_tag(Tag::Int);
|
||||
self.push_zigzag(i);
|
||||
self.idx_cache.borrow_mut().push(self.data.len());
|
||||
}
|
||||
#[inline]
|
||||
pub fn push_float(&mut self, f: f64) {
|
||||
self.push_tag(Tag::Float);
|
||||
self.data.extend(f.to_be_bytes());
|
||||
self.idx_cache.borrow_mut().push(self.data.len());
|
||||
}
|
||||
#[inline]
|
||||
pub fn push_uint(&mut self, u: u64) {
|
||||
self.push_tag(Tag::UInt);
|
||||
self.push_varint(u);
|
||||
self.idx_cache.borrow_mut().push(self.data.len());
|
||||
}
|
||||
#[inline]
|
||||
pub fn push_uuid(&mut self, u: Uuid) {
|
||||
self.push_tag(Tag::Uuid);
|
||||
self.data.extend(u.as_bytes());
|
||||
self.idx_cache.borrow_mut().push(self.data.len());
|
||||
}
|
||||
#[inline]
|
||||
pub fn push_str(&mut self, s: impl AsRef<str>) {
|
||||
let s = s.as_ref();
|
||||
self.push_tag(Tag::Text);
|
||||
self.push_varint(s.len() as u64);
|
||||
self.data.extend_from_slice(s.as_bytes());
|
||||
self.idx_cache.borrow_mut().push(self.data.len());
|
||||
}
|
||||
pub fn push_value(&mut self, v: &Value) {
|
||||
match v {
|
||||
Value::Null => self.push_null(),
|
||||
Value::Bool(b) => self.push_bool(*b),
|
||||
Value::EdgeDir(e) => self.push_edge_dir(*e),
|
||||
Value::UInt(u) => self.push_uint(*u),
|
||||
Value::Int(i) => self.push_int(*i),
|
||||
Value::Float(f) => self.push_float(*f),
|
||||
Value::Uuid(u) => self.push_uuid(*u),
|
||||
Value::Text(t) => self.push_str(t),
|
||||
Value::List(l) => {
|
||||
self.push_tag(Tag::List);
|
||||
let start_pos = self.data.len();
|
||||
let start_len = self.idx_cache.borrow().len();
|
||||
self.data.extend(0u32.to_be_bytes());
|
||||
for val in l {
|
||||
self.push_value(val);
|
||||
}
|
||||
let length = (self.data.len() - start_pos) as u32;
|
||||
let length_bytes = length.to_be_bytes();
|
||||
for i in 0..4 {
|
||||
self.data[start_pos + i] = length_bytes[i]
|
||||
}
|
||||
let mut cache = self.idx_cache.borrow_mut();
|
||||
cache.truncate(start_len);
|
||||
cache.push(self.data.len());
|
||||
}
|
||||
Value::Dict(d) => {
|
||||
self.push_tag(Tag::Dict);
|
||||
let start_pos = self.data.len();
|
||||
let start_len = self.idx_cache.borrow().len();
|
||||
self.data.extend(0u32.to_be_bytes());
|
||||
for (k, v) in d {
|
||||
self.push_varint(k.len() as u64);
|
||||
self.data.extend_from_slice(k.as_bytes());
|
||||
self.push_value(v);
|
||||
}
|
||||
let length = (self.data.len() - start_pos) as u32;
|
||||
let length_bytes = length.to_be_bytes();
|
||||
for i in 0..4 {
|
||||
self.data[start_pos + i] = length_bytes[i]
|
||||
}
|
||||
let mut cache = self.idx_cache.borrow_mut();
|
||||
cache.truncate(start_len);
|
||||
cache.push(self.data.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
fn push_varint(&mut self, u: u64) {
|
||||
let mut u = u;
|
||||
while u > 0b01111111 {
|
||||
self.data.push(0b10000000 | (u as u8 & 0b01111111));
|
||||
u >>= 7;
|
||||
}
|
||||
self.data.push(u as u8);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn push_zigzag(&mut self, i: i64) {
|
||||
let u: u64 = if i >= 0 {
|
||||
(i as u64) << 1
|
||||
} else {
|
||||
// Convoluted, to prevent overflow when calling .abs()
|
||||
(((i + 1).abs() as u64) << 1) + 1
|
||||
};
|
||||
self.push_varint(u);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<T: AsRef<[u8]>> PartialEq for Tuple<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.data.as_ref() == other.data.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<[u8]>> Eq for Tuple<T> {}
|
||||
|
||||
impl<T: AsRef<[u8]>> PartialOrd for Tuple<T> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<[u8]>> Ord for Tuple<T> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::BTreeMap;
|
||||
use crate::relation::tuple::{EdgeDir, Tuple, Value};
|
||||
|
||||
#[test]
|
||||
fn serde() {
|
||||
let mut t = Tuple::with_prefix(0);
|
||||
t.push_null();
|
||||
t.push_bool(true);
|
||||
t.push_bool(false);
|
||||
t.push_edge_dir(EdgeDir::Fwd);
|
||||
t.push_str("abcdef");
|
||||
t.push_edge_dir(EdgeDir::Bwd);
|
||||
t.push_value(&vec![
|
||||
true.into(),
|
||||
1e236.into(),
|
||||
"xxyyzz".into(),
|
||||
].into());
|
||||
t.push_int(-123345);
|
||||
t.push_value(&BTreeMap::from([]).into());
|
||||
t.push_uint(12121212);
|
||||
t.push_value(&BTreeMap::from([("yzyz".into(), "fifo".into())]).into());
|
||||
t.push_float(1e245);
|
||||
t.push_bool(false);
|
||||
assert!(t.all_cached());
|
||||
assert_eq!(t.idx_cache.borrow().len(), 13);
|
||||
let ot = t;
|
||||
let t = Tuple::new(ot.data.as_slice());
|
||||
let t3 = Tuple::new(ot.data.as_slice());
|
||||
assert_eq!(Value::from(()), t.get(0).unwrap());
|
||||
t3.get_pos(1);
|
||||
assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last());
|
||||
assert_eq!(Value::from(true), t.get(1).unwrap());
|
||||
t3.get_pos(2);
|
||||
assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last());
|
||||
assert_eq!(Value::from(false), t.get(2).unwrap());
|
||||
t3.get_pos(3);
|
||||
assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last());
|
||||
assert_eq!(Value::from(EdgeDir::Fwd), t.get(3).unwrap());
|
||||
t3.get_pos(4);
|
||||
assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last());
|
||||
assert_eq!(Value::from("abcdef"), t.get(4).unwrap());
|
||||
t3.get_pos(5);
|
||||
assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last());
|
||||
assert_eq!(Value::from(EdgeDir::Bwd), t.get(5).unwrap());
|
||||
t3.get_pos(6);
|
||||
assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last());
|
||||
assert_eq!(Value::from(Value::from(vec![
|
||||
true.into(),
|
||||
1e236.into(),
|
||||
"xxyyzz".into(),
|
||||
])), t.get(6).unwrap());
|
||||
t3.get_pos(7);
|
||||
assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last());
|
||||
assert_eq!(Value::from(-123345i64), t.get(7).unwrap());
|
||||
t3.get_pos(8);
|
||||
assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last());
|
||||
assert_eq!(Value::from(BTreeMap::new()), t.get(8).unwrap());
|
||||
t3.get_pos(9);
|
||||
assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last());
|
||||
assert_eq!(Value::from(12121212u64), t.get(9).unwrap());
|
||||
t3.get_pos(10);
|
||||
assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last());
|
||||
assert_eq!(Value::from(BTreeMap::from([("yzyz".into(), "fifo".into())])), t.get(10).unwrap());
|
||||
t3.get_pos(11);
|
||||
assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last());
|
||||
assert_eq!(Value::from(1e245), t.get(11).unwrap());
|
||||
t3.get_pos(12);
|
||||
assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last());
|
||||
assert_eq!(Value::from(false), t.get(12).unwrap());
|
||||
t3.get_pos(13);
|
||||
assert_eq!(t.idx_cache.borrow().last(), t3.idx_cache.borrow().last());
|
||||
assert_eq!(None, t.get(13));
|
||||
assert_eq!(None, t.get(13131));
|
||||
let t = Tuple::new(ot.data.as_slice());
|
||||
assert_eq!(Value::from(EdgeDir::Bwd), t.get(5).unwrap());
|
||||
assert_eq!(Value::from(true), t.get(1).unwrap());
|
||||
assert_eq!(Value::from(true), t.get(1).unwrap());
|
||||
assert_eq!(Value::from(1e245), t.get(11).unwrap());
|
||||
assert_eq!(Value::from(false), t.get(12).unwrap());
|
||||
assert_eq!(Value::from(()), t.get(0).unwrap());
|
||||
assert_eq!(Value::from(false), t.get(2).unwrap());
|
||||
assert_eq!(Value::from(12121212u64), t.get(9).unwrap());
|
||||
assert_eq!(Value::from(BTreeMap::new()), t.get(8).unwrap());
|
||||
assert_eq!(Value::from(EdgeDir::Fwd), t.get(3).unwrap());
|
||||
assert_eq!(Value::from("abcdef"), t.get(4).unwrap());
|
||||
assert_eq!(Value::from(Value::from(vec![
|
||||
true.into(),
|
||||
1e236.into(),
|
||||
"xxyyzz".into(),
|
||||
])), t.get(6).unwrap());
|
||||
assert_eq!(None, t.get(13));
|
||||
assert_eq!(Value::from(-123345i64), t.get(7).unwrap());
|
||||
assert_eq!(Value::from(BTreeMap::from([("yzyz".into(), "fifo".into())])), t.get(10).unwrap());
|
||||
assert_eq!(None, t.get(13131));
|
||||
}
|
||||
}
|
@ -1,141 +1,141 @@
|
||||
use std::fs;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::{RwLock};
|
||||
use crate::error::{CozoError, Result};
|
||||
use cozo_rocks::*;
|
||||
use crate::env::Environment;
|
||||
use crate::value::{cozo_comparator_v1};
|
||||
|
||||
|
||||
pub struct RocksStorage {
|
||||
pub db: DB,
|
||||
#[allow(dead_code)]
|
||||
path: String,
|
||||
last_local_id: AtomicUsize,
|
||||
pub root_env: RwLock<Environment>,
|
||||
}
|
||||
|
||||
const DEFAULT_CF: &str = "default";
|
||||
const SCRATCH_CF: &str = "scratch";
|
||||
const COMPARATOR_NAME: &str = "cozo_comparator_v1";
|
||||
|
||||
impl RocksStorage {
|
||||
#[allow(unused_variables)]
|
||||
pub fn new(path: String) -> Result<Self> {
|
||||
let options = Options::default()
|
||||
.increase_parallelism()
|
||||
.optimize_level_style_compaction()
|
||||
.set_create_if_missing(true)
|
||||
.set_comparator(COMPARATOR_NAME, cozo_comparator_v1);
|
||||
|
||||
let db = DB::open(options, path.as_ref())?;
|
||||
(match db.create_column_family(SCRATCH_CF) {
|
||||
Err(s) if s.bridge_code == StatusBridgeCode::EXISTING_ERROR => Ok(()),
|
||||
v => v
|
||||
})?;
|
||||
let mut env = Environment::default();
|
||||
env.define_base_types();
|
||||
Ok(RocksStorage {
|
||||
db,
|
||||
path,
|
||||
last_local_id: AtomicUsize::new(0),
|
||||
root_env: RwLock::new(env),
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
pub fn delete_storage(self) -> Result<()> {
|
||||
let path = self.path.clone();
|
||||
drop(self);
|
||||
fs::remove_dir_all(path)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
pub fn put_global(&self, k: &[u8], v: &[u8]) -> Result<()> {
|
||||
let default_cf = self.db.get_cf_handle(DEFAULT_CF)?;
|
||||
self.db.put(k, v, &default_cf, None)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
#[allow(unused_variables)]
|
||||
pub fn create_table(&self, name: &str, _global: bool) -> Result<()> {
|
||||
match self.db.create_column_family(table_name_to_cf_name(name)) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(s) if s.bridge_code == StatusBridgeCode::EXISTING_ERROR => Ok(()),
|
||||
Err(e) => Err(CozoError::Storage(e))
|
||||
}
|
||||
}
|
||||
#[allow(unused_variables)]
|
||||
pub fn drop_table(&self, name: &str, _global: bool) -> Result<()> {
|
||||
self.db.drop_column_family(table_name_to_cf_name(name))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_next_local_id(&self, global: bool) -> usize {
|
||||
if global {
|
||||
0
|
||||
} else {
|
||||
self.last_local_id.fetch_add(1, Ordering::Relaxed) + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn table_name_to_cf_name(name: &str) -> String {
|
||||
format!("${}", name)
|
||||
}
|
||||
|
||||
pub trait Storage {}
|
||||
|
||||
pub struct DummyStorage;
|
||||
|
||||
impl Storage for DummyStorage {}
|
||||
|
||||
impl Storage for RocksStorage {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::from_utf8;
|
||||
use crate::value::{ByteArrayBuilder, cozo_comparator_v1, Value};
|
||||
|
||||
#[test]
|
||||
fn import() {
|
||||
use cozo_rocks::*;
|
||||
let options = Options::default()
|
||||
.increase_parallelism()
|
||||
.optimize_level_style_compaction()
|
||||
.set_create_if_missing(true)
|
||||
.set_comparator("cozo_comparator_v1", cozo_comparator_v1);
|
||||
|
||||
let db = DB::open(options,
|
||||
"xxyyzz.db".as_ref()).unwrap();
|
||||
|
||||
let mut builder = ByteArrayBuilder::default();
|
||||
builder.build_value(&Value::RefString("A key"));
|
||||
let key = builder;
|
||||
|
||||
let mut builder = ByteArrayBuilder::default();
|
||||
builder.build_value(&Value::RefString("Another key"));
|
||||
let key2 = builder;
|
||||
let cf = db.get_cf_handle("default").unwrap();
|
||||
println!("{:?}", db.all_cf_names());
|
||||
|
||||
let val = db.get(&key, &cf, None).unwrap();
|
||||
println!("before anything {}", val.is_none());
|
||||
|
||||
db.put(&key, "A motherfucking value!!! 👋👋👋", &cf, None).unwrap();
|
||||
let batch = WriteBatch::default();
|
||||
batch.put(&key2, "Another motherfucking value!!! 👋👋👋", &cf).unwrap();
|
||||
db.write(batch, None).unwrap();
|
||||
// db.put("Yes man", "A motherfucking value!!! 👋👋👋", None).unwrap();
|
||||
let val = db.get(&key, &cf, None).unwrap().unwrap();
|
||||
println!("1 {}", from_utf8(val.as_ref()).unwrap());
|
||||
let val = db.get(&key2, &cf, None).unwrap().unwrap();
|
||||
// let val = val.as_bytes();
|
||||
println!("2 {}", from_utf8(val.as_ref()).unwrap());
|
||||
let val = db.get(&key, &cf, None).unwrap().unwrap();
|
||||
println!("3 {}", from_utf8(val.as_ref()).unwrap());
|
||||
println!("4 {}", from_utf8(db.get(&key, &cf, None).unwrap().unwrap().as_ref()).unwrap());
|
||||
}
|
||||
}
|
||||
// use std::fs;
|
||||
// use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
// use std::sync::{RwLock};
|
||||
// use crate::error::{CozoError, Result};
|
||||
// use cozo_rocks::*;
|
||||
// use crate::env::Environment;
|
||||
// use crate::value::{cozo_comparator_v1};
|
||||
//
|
||||
//
|
||||
// pub struct RocksStorage {
|
||||
// pub db: DB,
|
||||
// #[allow(dead_code)]
|
||||
// path: String,
|
||||
// last_local_id: AtomicUsize,
|
||||
// pub root_env: RwLock<Environment>,
|
||||
// }
|
||||
//
|
||||
// const DEFAULT_CF: &str = "default";
|
||||
// const SCRATCH_CF: &str = "scratch";
|
||||
// const COMPARATOR_NAME: &str = "cozo_comparator_v1";
|
||||
//
|
||||
// impl RocksStorage {
|
||||
// #[allow(unused_variables)]
|
||||
// pub fn new(path: String) -> Result<Self> {
|
||||
// let options = Options::default()
|
||||
// .increase_parallelism()
|
||||
// .optimize_level_style_compaction()
|
||||
// .set_create_if_missing(true)
|
||||
// .set_comparator(COMPARATOR_NAME, cozo_comparator_v1);
|
||||
//
|
||||
// let db = DB::open(options, path.as_ref())?;
|
||||
// (match db.create_column_family(SCRATCH_CF) {
|
||||
// Err(s) if s.bridge_code == StatusBridgeCode::EXISTING_ERROR => Ok(()),
|
||||
// v => v
|
||||
// })?;
|
||||
// let mut env = Environment::default();
|
||||
// env.define_base_types();
|
||||
// Ok(RocksStorage {
|
||||
// db,
|
||||
// path,
|
||||
// last_local_id: AtomicUsize::new(0),
|
||||
// root_env: RwLock::new(env),
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// #[allow(unused_variables)]
|
||||
// pub fn delete_storage(self) -> Result<()> {
|
||||
// let path = self.path.clone();
|
||||
// drop(self);
|
||||
// fs::remove_dir_all(path)?;
|
||||
// Ok(())
|
||||
// }
|
||||
//
|
||||
// #[allow(unused_variables)]
|
||||
// pub fn put_global(&self, k: &[u8], v: &[u8]) -> Result<()> {
|
||||
// let default_cf = self.db.get_cf_handle(DEFAULT_CF)?;
|
||||
// self.db.put(k, v, &default_cf, None)?;
|
||||
//
|
||||
// Ok(())
|
||||
// }
|
||||
// #[allow(unused_variables)]
|
||||
// pub fn create_table(&self, name: &str, _global: bool) -> Result<()> {
|
||||
// match self.db.create_column_family(table_name_to_cf_name(name)) {
|
||||
// Ok(_) => Ok(()),
|
||||
// Err(s) if s.bridge_code == StatusBridgeCode::EXISTING_ERROR => Ok(()),
|
||||
// Err(e) => Err(CozoError::Storage(e))
|
||||
// }
|
||||
// }
|
||||
// #[allow(unused_variables)]
|
||||
// pub fn drop_table(&self, name: &str, _global: bool) -> Result<()> {
|
||||
// self.db.drop_column_family(table_name_to_cf_name(name))?;
|
||||
// Ok(())
|
||||
// }
|
||||
//
|
||||
// pub fn get_next_local_id(&self, global: bool) -> usize {
|
||||
// if global {
|
||||
// 0
|
||||
// } else {
|
||||
// self.last_local_id.fetch_add(1, Ordering::Relaxed) + 1
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #[inline]
|
||||
// fn table_name_to_cf_name(name: &str) -> String {
|
||||
// format!("${}", name)
|
||||
// }
|
||||
//
|
||||
// pub trait Storage {}
|
||||
//
|
||||
// pub struct DummyStorage;
|
||||
//
|
||||
// impl Storage for DummyStorage {}
|
||||
//
|
||||
// impl Storage for RocksStorage {}
|
||||
//
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use std::str::from_utf8;
|
||||
// use crate::value::{ByteArrayBuilder, cozo_comparator_v1, Value};
|
||||
//
|
||||
// // #[test]
|
||||
// // fn import() {
|
||||
// // use cozo_rocks::*;
|
||||
// // let options = Options::default()
|
||||
// // .increase_parallelism()
|
||||
// // .optimize_level_style_compaction()
|
||||
// // .set_create_if_missing(true)
|
||||
// // .set_comparator("cozo_comparator_v1", cozo_comparator_v1);
|
||||
// //
|
||||
// // let db = DB::open(options,
|
||||
// // "xxyyzz.db".as_ref()).unwrap();
|
||||
// //
|
||||
// // let mut builder = ByteArrayBuilder::default();
|
||||
// // builder.build_value(&Value::RefString("A key"));
|
||||
// // let key = builder;
|
||||
// //
|
||||
// // let mut builder = ByteArrayBuilder::default();
|
||||
// // builder.build_value(&Value::RefString("Another key"));
|
||||
// // let key2 = builder;
|
||||
// // let cf = db.get_cf_handle("default").unwrap();
|
||||
// // println!("{:?}", db.all_cf_names());
|
||||
// //
|
||||
// // let val = db.get(&key, &cf, None).unwrap();
|
||||
// // println!("before anything {}", val.is_none());
|
||||
// //
|
||||
// // db.put(&key, "A motherfucking value!!! 👋👋👋", &cf, None).unwrap();
|
||||
// // let batch = WriteBatch::default();
|
||||
// // batch.put(&key2, "Another motherfucking value!!! 👋👋👋", &cf).unwrap();
|
||||
// // db.write(batch, None).unwrap();
|
||||
// // // db.put("Yes man", "A motherfucking value!!! 👋👋👋", None).unwrap();
|
||||
// // let val = db.get(&key, &cf, None).unwrap().unwrap();
|
||||
// // println!("1 {}", from_utf8(val.as_ref()).unwrap());
|
||||
// // let val = db.get(&key2, &cf, None).unwrap().unwrap();
|
||||
// // // let val = val.as_bytes();
|
||||
// // println!("2 {}", from_utf8(val.as_ref()).unwrap());
|
||||
// // let val = db.get(&key, &cf, None).unwrap().unwrap();
|
||||
// // println!("3 {}", from_utf8(val.as_ref()).unwrap());
|
||||
// // println!("4 {}", from_utf8(db.get(&key, &cf, None).unwrap().unwrap().as_ref()).unwrap());
|
||||
// // }
|
||||
// }
|
@ -1,256 +1,256 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt::{Debug, Display, Formatter, Write};
|
||||
use crate::env::{Env, Environment};
|
||||
use crate::value::{StaticValue, Value};
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub enum BaseType {
|
||||
Bool,
|
||||
Int,
|
||||
UInt,
|
||||
Float,
|
||||
String,
|
||||
BitArr,
|
||||
U8Arr,
|
||||
I8Arr,
|
||||
I16Arr,
|
||||
U16Arr,
|
||||
I32Arr,
|
||||
U32Arr,
|
||||
I64Arr,
|
||||
U64Arr,
|
||||
F16Arr,
|
||||
F32Arr,
|
||||
F64Arr,
|
||||
C32Arr,
|
||||
C64Arr,
|
||||
C128Arr,
|
||||
Uuid,
|
||||
Timestamp,
|
||||
Datetime,
|
||||
Timezone,
|
||||
Date,
|
||||
Time,
|
||||
Duration,
|
||||
BigInt,
|
||||
BigDecimal,
|
||||
Inet,
|
||||
Crs,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Col {
|
||||
pub name: String,
|
||||
pub typ: Typing,
|
||||
pub default: StaticValue,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Clone)]
|
||||
pub enum StorageStatus {
|
||||
Planned,
|
||||
Verified,
|
||||
Stored,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Ord, PartialOrd, Clone)]
|
||||
pub struct TableId {
|
||||
pub name: String,
|
||||
pub local_id: usize,
|
||||
}
|
||||
|
||||
impl TableId {
|
||||
pub fn is_global(&self) -> bool {
|
||||
self.local_id == 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Debug for TableId {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(&self.name)?;
|
||||
if self.local_id > 0 {
|
||||
f.write_str(&format!("({})", self.local_id))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Ord, PartialOrd, Eq, PartialEq, Clone)]
|
||||
pub struct ColumnId {
|
||||
table_id: TableId,
|
||||
is_key: bool,
|
||||
col_order: usize,
|
||||
}
|
||||
|
||||
impl Debug for ColumnId {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(&format!("{:?}", self.table_id))?;
|
||||
if self.is_key {
|
||||
f.write_char('*')?;
|
||||
} else {
|
||||
f.write_char('-')?;
|
||||
}
|
||||
f.write_str(&format!("{}", self.col_order))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Node {
|
||||
pub status: StorageStatus,
|
||||
pub id: TableId,
|
||||
pub keys: Vec<Col>,
|
||||
pub cols: Vec<Col>,
|
||||
pub out_e: Vec<TableId>,
|
||||
pub in_e: Vec<TableId>,
|
||||
pub attached: Vec<TableId>,
|
||||
pub col_map: BTreeMap<String, ColumnId>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Edge {
|
||||
pub status: StorageStatus,
|
||||
pub src: TableId,
|
||||
pub dst: TableId,
|
||||
pub id: TableId,
|
||||
pub keys: Vec<Col>,
|
||||
pub cols: Vec<Col>,
|
||||
pub col_map: BTreeMap<String, ColumnId>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Columns {
|
||||
pub status: StorageStatus,
|
||||
pub attached: TableId,
|
||||
pub id: TableId,
|
||||
pub cols: Vec<Col>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Index {
|
||||
pub status: StorageStatus,
|
||||
pub id: TableId,
|
||||
pub attached: TableId,
|
||||
pub cols: Vec<String>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Eq, PartialEq, Clone)]
|
||||
pub enum Typing {
|
||||
Any,
|
||||
Base(BaseType),
|
||||
HList(Box<Typing>),
|
||||
Nullable(Box<Typing>),
|
||||
Tuple(Vec<Typing>),
|
||||
NamedTuple(BTreeMap<String, Typing>),
|
||||
}
|
||||
|
||||
impl Display for Typing {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Typing::Any => f.write_str("Any")?,
|
||||
Typing::Base(b) => {
|
||||
match b {
|
||||
BaseType::Bool => f.write_str("Bool")?,
|
||||
BaseType::Int => f.write_str("Int")?,
|
||||
BaseType::UInt => f.write_str("UInt")?,
|
||||
BaseType::Float => f.write_str("Float")?,
|
||||
BaseType::String => f.write_str("String")?,
|
||||
BaseType::BitArr => f.write_str("BitArr")?,
|
||||
BaseType::U8Arr => f.write_str("U8Arr")?,
|
||||
BaseType::I8Arr => f.write_str("I8Arr")?,
|
||||
BaseType::I16Arr => f.write_str("I16Arr")?,
|
||||
BaseType::U16Arr => f.write_str("U16Arr")?,
|
||||
BaseType::I32Arr => f.write_str("I32Arr")?,
|
||||
BaseType::U32Arr => f.write_str("U32Arr")?,
|
||||
BaseType::I64Arr => f.write_str("I64Arr")?,
|
||||
BaseType::U64Arr => f.write_str("U64Arr")?,
|
||||
BaseType::F16Arr => f.write_str("F16Arr")?,
|
||||
BaseType::F32Arr => f.write_str("F32Arr")?,
|
||||
BaseType::F64Arr => f.write_str("F64Arr")?,
|
||||
BaseType::C32Arr => f.write_str("C32Arr")?,
|
||||
BaseType::C64Arr => f.write_str("C64Arr")?,
|
||||
BaseType::C128Arr => f.write_str("C128Arr")?,
|
||||
BaseType::Uuid => f.write_str("Uuid")?,
|
||||
BaseType::Timestamp => f.write_str("Timestamp")?,
|
||||
BaseType::Datetime => f.write_str("Datetime")?,
|
||||
BaseType::Timezone => f.write_str("Timezone")?,
|
||||
BaseType::Date => f.write_str("Date")?,
|
||||
BaseType::Time => f.write_str("Time")?,
|
||||
BaseType::Duration => f.write_str("Duration")?,
|
||||
BaseType::BigInt => f.write_str("BigInt")?,
|
||||
BaseType::BigDecimal => f.write_str("BigDecimal")?,
|
||||
BaseType::Inet => f.write_str("Inet")?,
|
||||
BaseType::Crs => f.write_str("Crs")?
|
||||
}
|
||||
}
|
||||
Typing::HList(l) => {
|
||||
f.write_char('[')?;
|
||||
Display::fmt(l, f)?;
|
||||
f.write_char(']')?;
|
||||
}
|
||||
Typing::Nullable(d) => {
|
||||
f.write_char('?')?;
|
||||
Display::fmt(d, f)?;
|
||||
}
|
||||
Typing::Tuple(_) => todo!(),
|
||||
Typing::NamedTuple(_) => todo!()
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Typing {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Structured {
|
||||
Typing(Typing),
|
||||
Node(Node),
|
||||
Edge(Edge),
|
||||
Columns(Columns),
|
||||
Index(Index),
|
||||
Value(StaticValue),
|
||||
}
|
||||
|
||||
impl Structured {
|
||||
pub fn storage_id(&self) -> Option<TableId> {
|
||||
match self {
|
||||
Structured::Typing(_) => None,
|
||||
Structured::Node(n) => Some(n.id.clone()),
|
||||
Structured::Edge(e) => Some(e.id.clone()),
|
||||
Structured::Columns(c) => Some(c.id.clone()),
|
||||
Structured::Index(i) => Some(i.id.clone()),
|
||||
Structured::Value(_) => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Environment {
|
||||
pub fn define_base_types(&mut self) {
|
||||
self.define("Any".to_string(), Structured::Typing(Typing::Any));
|
||||
self.define("Bool".to_string(), Structured::Typing(Typing::Base(BaseType::Bool)));
|
||||
self.define("Int".to_string(), Structured::Typing(Typing::Base(BaseType::Int)));
|
||||
self.define("UInt".to_string(), Structured::Typing(Typing::Base(BaseType::UInt)));
|
||||
self.define("Float".to_string(), Structured::Typing(Typing::Base(BaseType::Float)));
|
||||
self.define("String".to_string(), Structured::Typing(Typing::Base(BaseType::String)));
|
||||
self.define("Bytes".to_string(), Structured::Typing(Typing::Base(BaseType::U8Arr)));
|
||||
self.define("U8Arr".to_string(), Structured::Typing(Typing::Base(BaseType::U8Arr)));
|
||||
self.define("Uuid".to_string(), Structured::Typing(Typing::Base(BaseType::Uuid)));
|
||||
self.define("Timestamp".to_string(), Structured::Typing(Typing::Base(BaseType::Timestamp)));
|
||||
self.define("Datetime".to_string(), Structured::Typing(Typing::Base(BaseType::Datetime)));
|
||||
self.define("Timezone".to_string(), Structured::Typing(Typing::Base(BaseType::Timezone)));
|
||||
self.define("Date".to_string(), Structured::Typing(Typing::Base(BaseType::Date)));
|
||||
self.define("Time".to_string(), Structured::Typing(Typing::Base(BaseType::Time)));
|
||||
self.define("Duration".to_string(), Structured::Typing(Typing::Base(BaseType::Duration)));
|
||||
self.define("BigInt".to_string(), Structured::Typing(Typing::Base(BaseType::BigInt)));
|
||||
self.define("BigDecimal".to_string(), Structured::Typing(Typing::Base(BaseType::BigDecimal)));
|
||||
self.define("Int".to_string(), Structured::Typing(Typing::Base(BaseType::Int)));
|
||||
self.define("Crs".to_string(), Structured::Typing(Typing::Base(BaseType::Crs)));
|
||||
}
|
||||
}
|
||||
// use std::collections::BTreeMap;
|
||||
// use std::fmt::{Debug, Display, Formatter, Write};
|
||||
// use crate::env::{Env, Environment};
|
||||
// use crate::value::{StaticValue, Value};
|
||||
//
|
||||
// #[derive(Debug, Eq, PartialEq, Clone)]
|
||||
// pub enum BaseType {
|
||||
// Bool,
|
||||
// Int,
|
||||
// UInt,
|
||||
// Float,
|
||||
// String,
|
||||
// BitArr,
|
||||
// U8Arr,
|
||||
// I8Arr,
|
||||
// I16Arr,
|
||||
// U16Arr,
|
||||
// I32Arr,
|
||||
// U32Arr,
|
||||
// I64Arr,
|
||||
// U64Arr,
|
||||
// F16Arr,
|
||||
// F32Arr,
|
||||
// F64Arr,
|
||||
// C32Arr,
|
||||
// C64Arr,
|
||||
// C128Arr,
|
||||
// Uuid,
|
||||
// Timestamp,
|
||||
// Datetime,
|
||||
// Timezone,
|
||||
// Date,
|
||||
// Time,
|
||||
// Duration,
|
||||
// BigInt,
|
||||
// BigDecimal,
|
||||
// Inet,
|
||||
// Crs,
|
||||
// }
|
||||
//
|
||||
//
|
||||
// #[derive(Debug, PartialEq, Clone)]
|
||||
// pub struct Col {
|
||||
// pub name: String,
|
||||
// pub typ: Typing,
|
||||
// pub default: StaticValue,
|
||||
// }
|
||||
//
|
||||
//
|
||||
// #[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Clone)]
|
||||
// pub enum StorageStatus {
|
||||
// Planned,
|
||||
// Verified,
|
||||
// Stored,
|
||||
// }
|
||||
//
|
||||
// #[derive(PartialEq, Eq, Ord, PartialOrd, Clone)]
|
||||
// pub struct TableId {
|
||||
// pub name: String,
|
||||
// pub local_id: usize,
|
||||
// }
|
||||
//
|
||||
// impl TableId {
|
||||
// pub fn is_global(&self) -> bool {
|
||||
// self.local_id == 0
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// impl Debug for TableId {
|
||||
// fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
// f.write_str(&self.name)?;
|
||||
// if self.local_id > 0 {
|
||||
// f.write_str(&format!("({})", self.local_id))?;
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #[derive(Ord, PartialOrd, Eq, PartialEq, Clone)]
|
||||
// pub struct ColumnId {
|
||||
// table_id: TableId,
|
||||
// is_key: bool,
|
||||
// col_order: usize,
|
||||
// }
|
||||
//
|
||||
// impl Debug for ColumnId {
|
||||
// fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
// f.write_str(&format!("{:?}", self.table_id))?;
|
||||
// if self.is_key {
|
||||
// f.write_char('*')?;
|
||||
// } else {
|
||||
// f.write_char('-')?;
|
||||
// }
|
||||
// f.write_str(&format!("{}", self.col_order))?;
|
||||
// Ok(())
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #[derive(Debug, PartialEq, Clone)]
|
||||
// pub struct Node {
|
||||
// pub status: StorageStatus,
|
||||
// pub id: TableId,
|
||||
// pub keys: Vec<Col>,
|
||||
// pub cols: Vec<Col>,
|
||||
// pub out_e: Vec<TableId>,
|
||||
// pub in_e: Vec<TableId>,
|
||||
// pub attached: Vec<TableId>,
|
||||
// pub col_map: BTreeMap<String, ColumnId>,
|
||||
// }
|
||||
//
|
||||
// #[derive(Debug, PartialEq, Clone)]
|
||||
// pub struct Edge {
|
||||
// pub status: StorageStatus,
|
||||
// pub src: TableId,
|
||||
// pub dst: TableId,
|
||||
// pub id: TableId,
|
||||
// pub keys: Vec<Col>,
|
||||
// pub cols: Vec<Col>,
|
||||
// pub col_map: BTreeMap<String, ColumnId>,
|
||||
// }
|
||||
//
|
||||
// #[derive(Debug, PartialEq, Clone)]
|
||||
// pub struct Columns {
|
||||
// pub status: StorageStatus,
|
||||
// pub attached: TableId,
|
||||
// pub id: TableId,
|
||||
// pub cols: Vec<Col>,
|
||||
// }
|
||||
//
|
||||
// #[derive(Debug, PartialEq, Clone)]
|
||||
// pub struct Index {
|
||||
// pub status: StorageStatus,
|
||||
// pub id: TableId,
|
||||
// pub attached: TableId,
|
||||
// pub cols: Vec<String>,
|
||||
// }
|
||||
//
|
||||
//
|
||||
// #[derive(Eq, PartialEq, Clone)]
|
||||
// pub enum Typing {
|
||||
// Any,
|
||||
// Base(BaseType),
|
||||
// HList(Box<Typing>),
|
||||
// Nullable(Box<Typing>),
|
||||
// Tuple(Vec<Typing>),
|
||||
// NamedTuple(BTreeMap<String, Typing>),
|
||||
// }
|
||||
//
|
||||
// impl Display for Typing {
|
||||
// fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
// match self {
|
||||
// Typing::Any => f.write_str("Any")?,
|
||||
// Typing::Base(b) => {
|
||||
// match b {
|
||||
// BaseType::Bool => f.write_str("Bool")?,
|
||||
// BaseType::Int => f.write_str("Int")?,
|
||||
// BaseType::UInt => f.write_str("UInt")?,
|
||||
// BaseType::Float => f.write_str("Float")?,
|
||||
// BaseType::String => f.write_str("String")?,
|
||||
// BaseType::BitArr => f.write_str("BitArr")?,
|
||||
// BaseType::U8Arr => f.write_str("U8Arr")?,
|
||||
// BaseType::I8Arr => f.write_str("I8Arr")?,
|
||||
// BaseType::I16Arr => f.write_str("I16Arr")?,
|
||||
// BaseType::U16Arr => f.write_str("U16Arr")?,
|
||||
// BaseType::I32Arr => f.write_str("I32Arr")?,
|
||||
// BaseType::U32Arr => f.write_str("U32Arr")?,
|
||||
// BaseType::I64Arr => f.write_str("I64Arr")?,
|
||||
// BaseType::U64Arr => f.write_str("U64Arr")?,
|
||||
// BaseType::F16Arr => f.write_str("F16Arr")?,
|
||||
// BaseType::F32Arr => f.write_str("F32Arr")?,
|
||||
// BaseType::F64Arr => f.write_str("F64Arr")?,
|
||||
// BaseType::C32Arr => f.write_str("C32Arr")?,
|
||||
// BaseType::C64Arr => f.write_str("C64Arr")?,
|
||||
// BaseType::C128Arr => f.write_str("C128Arr")?,
|
||||
// BaseType::Uuid => f.write_str("Uuid")?,
|
||||
// BaseType::Timestamp => f.write_str("Timestamp")?,
|
||||
// BaseType::Datetime => f.write_str("Datetime")?,
|
||||
// BaseType::Timezone => f.write_str("Timezone")?,
|
||||
// BaseType::Date => f.write_str("Date")?,
|
||||
// BaseType::Time => f.write_str("Time")?,
|
||||
// BaseType::Duration => f.write_str("Duration")?,
|
||||
// BaseType::BigInt => f.write_str("BigInt")?,
|
||||
// BaseType::BigDecimal => f.write_str("BigDecimal")?,
|
||||
// BaseType::Inet => f.write_str("Inet")?,
|
||||
// BaseType::Crs => f.write_str("Crs")?
|
||||
// }
|
||||
// }
|
||||
// Typing::HList(l) => {
|
||||
// f.write_char('[')?;
|
||||
// Display::fmt(l, f)?;
|
||||
// f.write_char(']')?;
|
||||
// }
|
||||
// Typing::Nullable(d) => {
|
||||
// f.write_char('?')?;
|
||||
// Display::fmt(d, f)?;
|
||||
// }
|
||||
// Typing::Tuple(_) => todo!(),
|
||||
// Typing::NamedTuple(_) => todo!()
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl Debug for Typing {
|
||||
// fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
// Display::fmt(self, f)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #[derive(Debug, PartialEq, Clone)]
|
||||
// pub enum Structured {
|
||||
// Typing(Typing),
|
||||
// Node(Node),
|
||||
// Edge(Edge),
|
||||
// Columns(Columns),
|
||||
// Index(Index),
|
||||
// Value(StaticValue),
|
||||
// }
|
||||
//
|
||||
// impl Structured {
|
||||
// pub fn storage_id(&self) -> Option<TableId> {
|
||||
// match self {
|
||||
// Structured::Typing(_) => None,
|
||||
// Structured::Node(n) => Some(n.id.clone()),
|
||||
// Structured::Edge(e) => Some(e.id.clone()),
|
||||
// Structured::Columns(c) => Some(c.id.clone()),
|
||||
// Structured::Index(i) => Some(i.id.clone()),
|
||||
// Structured::Value(_) => None
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl Environment {
|
||||
// pub fn define_base_types(&mut self) {
|
||||
// self.define("Any".to_string(), Structured::Typing(Typing::Any));
|
||||
// self.define("Bool".to_string(), Structured::Typing(Typing::Base(BaseType::Bool)));
|
||||
// self.define("Int".to_string(), Structured::Typing(Typing::Base(BaseType::Int)));
|
||||
// self.define("UInt".to_string(), Structured::Typing(Typing::Base(BaseType::UInt)));
|
||||
// self.define("Float".to_string(), Structured::Typing(Typing::Base(BaseType::Float)));
|
||||
// self.define("String".to_string(), Structured::Typing(Typing::Base(BaseType::String)));
|
||||
// self.define("Bytes".to_string(), Structured::Typing(Typing::Base(BaseType::U8Arr)));
|
||||
// self.define("U8Arr".to_string(), Structured::Typing(Typing::Base(BaseType::U8Arr)));
|
||||
// self.define("Uuid".to_string(), Structured::Typing(Typing::Base(BaseType::Uuid)));
|
||||
// self.define("Timestamp".to_string(), Structured::Typing(Typing::Base(BaseType::Timestamp)));
|
||||
// self.define("Datetime".to_string(), Structured::Typing(Typing::Base(BaseType::Datetime)));
|
||||
// self.define("Timezone".to_string(), Structured::Typing(Typing::Base(BaseType::Timezone)));
|
||||
// self.define("Date".to_string(), Structured::Typing(Typing::Base(BaseType::Date)));
|
||||
// self.define("Time".to_string(), Structured::Typing(Typing::Base(BaseType::Time)));
|
||||
// self.define("Duration".to_string(), Structured::Typing(Typing::Base(BaseType::Duration)));
|
||||
// self.define("BigInt".to_string(), Structured::Typing(Typing::Base(BaseType::BigInt)));
|
||||
// self.define("BigDecimal".to_string(), Structured::Typing(Typing::Base(BaseType::BigDecimal)));
|
||||
// self.define("Int".to_string(), Structured::Typing(Typing::Base(BaseType::Int)));
|
||||
// self.define("Crs".to_string(), Structured::Typing(Typing::Base(BaseType::Crs)));
|
||||
// }
|
||||
// }
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue