unevaluated value; lisp

main
Ziyang Hu 2 years ago
parent 05f06ea427
commit b576d0e867

@ -1,241 +0,0 @@
// 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]))
// }
//
//
// 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"##)));
// }
// }

@ -63,12 +63,12 @@ pub enum CozoError {
//
// #[error("Database already closed")]
// DatabaseClosed,
//
// #[error(transparent)]
// ParseInt(#[from] std::num::ParseIntError),
//
// #[error(transparent)]
// ParseFloat(#[from] std::num::ParseFloatError),
#[error(transparent)]
ParseInt(#[from] std::num::ParseIntError),
#[error(transparent)]
ParseFloat(#[from] std::num::ParseFloatError),
#[error(transparent)]
Parse(#[from] pest::error::Error<Rule>),

@ -82,14 +82,15 @@ impl<T: AsRef<[u8]>> Tuple<T> {
Tag::Int | Tag::UInt => start + self.parse_varint(start).1,
Tag::Float => start + 8,
Tag::Uuid => start + 16,
Tag::Text => {
Tag::Text | Tag::Variable => {
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::Apply => 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,
Tag::MaxTag => panic!()
Tag::MaxTag => panic!(),
};
self.idx_cache.borrow_mut().push(nxt);
}
@ -164,6 +165,15 @@ impl<T: AsRef<[u8]>> Tuple<T> {
(start + slen + offset, s.into())
}
Tag::Variable => {
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, Value::Variable(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;
@ -175,6 +185,23 @@ impl<T: AsRef<[u8]>> Tuple<T> {
}
(end_pos, collected.into())
}
Tag::Apply => {
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![];
let (val, new_pos) = self.parse_value_at(start_pos);
start_pos = new_pos;
let op = match val {
Value::Variable(s) => s,
_ => panic!("Corrupt data when parsing Apply")
};
while start_pos < end_pos {
let (val, new_pos) = self.parse_value_at(start_pos);
collected.push(val);
start_pos = new_pos;
}
(end_pos, Value::Apply(op, collected))
}
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;
@ -192,7 +219,7 @@ impl<T: AsRef<[u8]>> Tuple<T> {
}
(end_pos, collected.into())
}
Tag::MaxTag => (start, Value::End_Sentinel)
Tag::MaxTag => (start, Value::EndSentinel),
};
(val, nxt)
}
@ -317,6 +344,14 @@ impl OwnTuple {
self.idx_cache.borrow_mut().push(self.data.len());
}
#[inline]
pub fn push_variable(&mut self, s: impl AsRef<str>) {
let s = s.as_ref();
self.push_tag(Tag::Variable);
self.push_varint(s.len() as u64);
self.data.extend_from_slice(s.as_bytes());
self.idx_cache.borrow_mut().push(self.data.len());
}
#[inline]
pub fn push_value(&mut self, v: &Value) {
match v {
Value::Null => self.push_null(),
@ -326,6 +361,7 @@ impl OwnTuple {
Value::Float(f) => self.push_float(f.into_inner()),
Value::Uuid(u) => self.push_uuid(*u),
Value::Text(t) => self.push_str(t),
Value::Variable(s) => self.push_variable(s),
Value::List(l) => {
self.push_tag(Tag::List);
let start_pos = self.data.len();
@ -341,6 +377,22 @@ impl OwnTuple {
cache.truncate(start_len);
cache.push(self.data.len());
}
Value::Apply(op, args) => {
self.push_tag(Tag::Apply);
let start_pos = self.data.len();
let start_len = self.idx_cache.borrow().len();
self.data.extend(0u32.to_be_bytes());
self.push_variable(op);
for val in args {
self.push_value(val);
}
let length = (self.data.len() - start_pos) as u32;
let length_bytes = length.to_be_bytes();
self.data[start_pos..(4 + start_pos)].clone_from_slice(&length_bytes[..4]);
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();
@ -358,7 +410,7 @@ impl OwnTuple {
cache.truncate(start_len);
cache.push(self.data.len());
}
Value::End_Sentinel => panic!("Cannot push sentinel value")
Value::EndSentinel => panic!("Cannot push sentinel value"),
}
}

@ -1,8 +1,16 @@
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::fmt::{Display, Formatter, Write};
use lazy_static::lazy_static;
use pest::prec_climber::{Assoc, PrecClimber, Operator};
use ordered_float::OrderedFloat;
use pest::iterators::Pair;
use uuid::Uuid;
use crate::parser::Rule;
use crate::error::Result;
use crate::parser::number::parse_int;
use crate::parser::text_identifier::parse_string;
#[repr(u8)]
#[derive(Ord, PartialOrd, Eq, PartialEq)]
@ -42,7 +50,9 @@ pub enum Tag {
// C32Arr = 72,
// C64Arr = 73,
// C128Arr = 74,
MaxTag = u8::MAX
Variable = u8::MAX - 2,
Apply = u8::MAX - 1,
MaxTag = u8::MAX,
}
impl TryFrom<u8> for Tag {
@ -78,7 +88,9 @@ pub enum Value<'a> {
Text(Cow<'a, str>),
List(Vec<Value<'a>>),
Dict(BTreeMap<Cow<'a, str>, Value<'a>>),
End_Sentinel
Variable(Cow<'a, str>),
Apply(Cow<'a, str>, Vec<Value<'a>>),
EndSentinel,
}
pub type StaticValue = Value<'static>;
@ -94,13 +106,39 @@ impl<'a> Value<'a> {
Value::Float(f) => Value::from(f),
Value::Uuid(u) => Value::from(u),
Value::Text(t) => Value::from(t.into_owned()),
Value::Variable(s) => Value::Variable(Cow::Owned(s.into_owned())),
Value::List(l) => l.into_iter().map(|v| v.to_static()).collect::<Vec<StaticValue>>().into(),
Value::Apply(op, args) => {
Value::Apply(Cow::Owned(op.into_owned()),
args.into_iter().map(|v| v.to_static()).collect::<Vec<StaticValue>>())
}
Value::Dict(d) => d.into_iter()
.map(|(k, v)| (Cow::Owned(k.into_owned()), v.to_static()))
.collect::<BTreeMap<Cow<'static, str>, StaticValue>>().into(),
Value::End_Sentinel => panic!("Cannot process sentinel value")
Value::EndSentinel => panic!("Cannot process sentinel value"),
}
}
#[inline]
pub fn is_evaluated(&self) -> bool {
match self {
Value::Null |
Value::Bool(_) |
Value::UInt(_) |
Value::Int(_) |
Value::Float(_) |
Value::Uuid(_) |
Value::Text(_) |
Value::EndSentinel => true,
Value::List(l) => l.iter().all(|v| v.is_evaluated()),
Value::Dict(d) => d.values().all(|v| v.is_evaluated()),
Value::Variable(_) => false,
Value::Apply(_, _) => false
}
}
#[inline]
pub fn from_pair(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self> {
PREC_CLIMBER.climb(pair.into_inner(), build_expr_primary, build_expr_infix)
}
}
impl From<()> for StaticValue {
@ -253,10 +291,164 @@ impl<'a> Display for Value<'a> {
}
f.write_char('}')?;
}
Value::End_Sentinel => {
Value::Variable(s) => {
write!(f, "`{}`", s)?
}
Value::EndSentinel => {
write!(f, "Sentinel")?
}
Value::Apply(op, args) => {
write!(f, "({} {})", op,
args.iter().map(|v| v.to_string()).collect::<Vec<_>>().join(" "))?;
}
}
Ok(())
}
}
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)
])
};
}
fn build_expr_infix<'a>(lhs: Result<Value<'a>>, op: Pair<Rule>, rhs: Result<Value<'a>>) -> Result<Value<'a>> {
let lhs = lhs?;
let rhs = rhs?;
let op = match op.as_rule() {
Rule::op_add => "+",
Rule::op_sub => "-",
Rule::op_mul => "*",
Rule::op_div => "/",
Rule::op_eq => "==",
Rule::op_ne => "!=",
Rule::op_or => "||",
Rule::op_and => "&&",
Rule::op_mod => "%",
Rule::op_gt => ">",
Rule::op_ge => ">=",
Rule::op_lt => "<",
Rule::op_le => "<=",
Rule::op_pow => "**",
Rule::op_coalesce => "~~",
_ => unreachable!()
};
Ok(Value::Apply(op.into(), vec![lhs, rhs]))
}
fn build_expr_primary(pair: Pair<Rule>) -> Result<Value> {
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 => Value::from_pair(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())?;
let op = match op {
Rule::negate => "!",
Rule::minus => "--",
_ => unreachable!()
};
Ok(Value::Apply(op.into(), vec![term]))
}
Rule::pos_int => Ok(Value::Int(pair.as_str().replace('_', "").parse::<i64>()?)),
Rule::hex_pos_int => Ok(Value::Int(parse_int(pair.as_str(), 16))),
Rule::octo_pos_int => Ok(Value::Int(parse_int(pair.as_str(), 8))),
Rule::bin_pos_int => Ok(Value::Int(parse_int(pair.as_str(), 2))),
Rule::dot_float | Rule::sci_float => Ok(Value::Float(pair.as_str().replace('_', "").parse::<f64>()?.into())),
Rule::null => Ok(Value::Null),
Rule::boolean => Ok(Value::Bool(pair.as_str() == "true")),
Rule::quoted_string | Rule::s_quoted_string | Rule::raw_string => Ok(
Value::Text(Cow::Owned(parse_string(pair)?))),
Rule::list => Ok(pair.into_inner().map(|v| build_expr_primary(v)).collect::<Result<Vec<Value>>>()?.into()),
Rule::dict => {
Ok(pair.into_inner().map(|p| {
match p.as_rule() {
Rule::dict_pair => {
let mut inner = p.into_inner();
let name = parse_string(inner.next().unwrap())?;
let val = build_expr_primary(inner.next().unwrap())?;
Ok((name.into(), val))
}
_ => todo!()
}
}).collect::<Result<BTreeMap<Cow<str>, Value>>>()?.into())
}
Rule::param => {
Ok(Value::Variable(pair.as_str().into()))
}
Rule::ident => {
Ok(Value::Variable(pair.as_str().into()))
}
_ => {
println!("Unhandled rule {:?}", pair.as_rule());
unimplemented!()
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::parser::Parser;
use pest::Parser as PestParser;
fn parse_expr_from_str<S: AsRef<str>>(s: S) -> Result<StaticValue> {
let pair = Parser::parse(Rule::expr, s.as_ref()).unwrap().next().unwrap();
Value::from_pair(pair).map(|v| v.to_static())
}
#[test]
fn raw_string() {
println!("{:#?}", parse_expr_from_str(r#####"r#"x"#"#####))
}
#[test]
fn unevaluated() {
let val = parse_expr_from_str("a+b*c+d").unwrap();
println!("{}", val);
assert!(!val.is_evaluated());
}
#[test]
fn parse_literals() {
assert_eq!(parse_expr_from_str("1").unwrap(), Value::Int(1));
assert_eq!(parse_expr_from_str("12_3").unwrap(), Value::Int(123));
assert_eq!(parse_expr_from_str("0xaf").unwrap(), Value::Int(0xaf));
assert_eq!(parse_expr_from_str("0xafcE_f").unwrap(), Value::Int(0xafcef));
assert_eq!(parse_expr_from_str("0o1234_567").unwrap(), Value::Int(0o1234567));
assert_eq!(parse_expr_from_str("0o0001234_567").unwrap(), Value::Int(0o1234567));
assert_eq!(parse_expr_from_str("0b101010").unwrap(), Value::Int(0b101010));
assert_eq!(parse_expr_from_str("0.0").unwrap(), Value::Float((0.).into()));
assert_eq!(parse_expr_from_str("10.022_3").unwrap(), Value::Float(10.0223.into()));
assert_eq!(parse_expr_from_str("10.022_3e-100").unwrap(), Value::Float(10.0223e-100.into()));
assert_eq!(parse_expr_from_str("null").unwrap(), Value::Null);
assert_eq!(parse_expr_from_str("true").unwrap(), Value::Bool(true));
assert_eq!(parse_expr_from_str("false").unwrap(), Value::Bool(false));
assert_eq!(parse_expr_from_str(r#""x \n \ty \"""#).unwrap(), Value::Text(Cow::Borrowed("x \n \ty \"")));
assert_eq!(parse_expr_from_str(r#""x'""#).unwrap(), Value::Text("x'".into()));
assert_eq!(parse_expr_from_str(r#"'"x"'"#).unwrap(), Value::Text(r##""x""##.into()));
assert_eq!(parse_expr_from_str(r#####"r###"x"yz"###"#####).unwrap(), (Value::Text(r##"x"yz"##.into())));
}
}
Loading…
Cancel
Save