new tuple type

main
Ziyang Hu 2 years ago
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,3 +1,5 @@
extern crate core;
pub mod value;
pub mod typing;
pub mod env;
@ -9,4 +11,5 @@ pub mod error;
pub mod definition;
pub mod storage;
pub mod mutation;
pub mod plan;
pub mod plan;
pub mod relation;

@ -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…
Cancel
Save