From 28e52242e01181a9ac6e56e97a928b2d635920d7 Mon Sep 17 00:00:00 2001 From: Ziyang Hu Date: Sun, 10 Apr 2022 23:07:19 +0800 Subject: [PATCH] defining nodes and edges --- src/ast.rs | 160 ++----------------------- src/definition.rs | 241 ++++++++++++++++++++++++++++++++++++++ src/env.rs | 14 ++- src/error.rs | 12 ++ src/eval.rs | 19 ++- src/grammar.pest | 2 +- src/lib.rs | 3 +- src/typing.rs | 292 ++++++++++++++++++++++++++++++++++++++++++---- 8 files changed, 566 insertions(+), 177 deletions(-) create mode 100644 src/definition.rs diff --git a/src/ast.rs b/src/ast.rs index e1b9494f..b29755a6 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -7,7 +7,6 @@ use lazy_static::lazy_static; use crate::ast::Expr::{Apply, Const}; use crate::error::CozoError; use crate::error::CozoError::ReservedIdent; -use crate::typing::{BaseType, Typing}; use crate::value::Value; @@ -55,43 +54,6 @@ lazy_static! { }; } -#[derive(Debug, PartialEq)] -pub struct Col { - pub name: String, - pub typ: Typing, - pub default: Option>, -} - -#[derive(Debug, PartialEq)] -pub enum TableDef { - Node { - is_local: bool, - name: String, - keys: Vec, - cols: Vec, - }, - Edge { - is_local: bool, - src: String, - dst: String, - name: String, - keys: Vec, - cols: Vec, - }, - Columns { - is_local: bool, - attached: String, - name: String, - cols: Vec, - }, - Index { - is_local: bool, - name: String, - attached: String, - cols: Vec, - }, -} - #[derive(PartialEq, Debug)] pub enum Expr<'a> { @@ -193,6 +155,16 @@ fn parse_s_quoted_string(pair: Pair) -> Result { Ok(ret) } +#[inline] +pub fn parse_string(pair: Pair) -> Result { + 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)?), + _ => unreachable!() + } +} + fn build_expr_primary(pair: Pair) -> Result { match pair.as_rule() { Rule::expr => build_expr_primary(pair.into_inner().next().unwrap()), @@ -217,9 +189,8 @@ fn build_expr_primary(pair: Pair) -> Result { Rule::dot_float | Rule::sci_float => Ok(Const(Value::Float(pair.as_str().replace('_', "").parse::()?))), Rule::null => Ok(Const(Value::Null)), Rule::boolean => Ok(Const(Value::Bool(pair.as_str() == "true"))), - Rule::quoted_string => Ok(Const(Value::OwnString(Box::new(parse_quoted_string(pair)?)))), - Rule::s_quoted_string => Ok(Const(Value::OwnString(Box::new(parse_s_quoted_string(pair)?)))), - Rule::raw_string => Ok(Const(Value::OwnString(Box::new(parse_raw_string(pair)?)))), + Rule::quoted_string | Rule::s_quoted_string | Rule::s_quoted_string => Ok( + Const(Value::OwnString(Box::new(parse_string(pair)?)))), _ => { println!("{:#?}", pair); unimplemented!() @@ -236,102 +207,6 @@ pub fn parse_expr_from_str(inp: &str) -> Result { build_expr(expr_tree) } -fn parse_ident(pair: Pair) -> String { - pair.as_str().to_string() -} - -fn build_name_in_def(pair: Pair, forbid_underscore: bool) -> Result { - let inner = pair.into_inner().next().unwrap(); - let name = match inner.as_rule() { - Rule::ident => parse_ident(inner), - Rule::raw_string => parse_raw_string(inner)?, - Rule::s_quoted_string => parse_s_quoted_string(inner)?, - Rule::quoted_string => parse_quoted_string(inner)?, - _ => unreachable!() - }; - if forbid_underscore && name.starts_with('_') { - Err(ReservedIdent) - } else { - Ok(name) - } -} - -fn parse_col_name(pair: Pair) -> Result<(String, bool), CozoError> { - let mut pairs = pair.into_inner(); - let mut is_key = false; - let mut nxt_pair = pairs.next().unwrap(); - if nxt_pair.as_rule() == Rule::key_marker { - is_key = true; - nxt_pair = pairs.next().unwrap(); - } - - Ok((build_name_in_def(nxt_pair, true)?, is_key)) -} - -fn build_col_entry(pair: Pair) -> Result<(Col, bool), CozoError> { - let mut pairs = pair.into_inner(); - let (name, is_key) = parse_col_name(pairs.next().unwrap())?; - Ok((Col { - name, - typ: Typing::Base(BaseType::Int), - default: None, - }, is_key)) -} - -fn build_col_defs(pair: Pair) -> Result<(Vec, Vec), CozoError> { - let mut keys = vec![]; - let mut cols = vec![]; - for pair in pair.into_inner() { - let (col, is_key) = build_col_entry(pair)?; - if is_key { - keys.push(col) - } else { - cols.push(col) - } - } - - Ok((keys, cols)) -} - -fn build_node_def(pair: Pair, is_local: bool) -> Result { - let mut inner = pair.into_inner(); - let name = build_name_in_def(inner.next().unwrap(), true)?; - let (keys, cols) = build_col_defs(inner.next().unwrap())?; - Ok(TableDef::Node { - is_local, - name, - keys, - cols, - }) -} - -pub fn build_statements(pairs: Pairs) -> Result, CozoError> { - let mut ret = vec![]; - for pair in pairs { - match pair.as_rule() { - r @ (Rule::global_def | Rule::local_def) => { - let inner = pair.into_inner().next().unwrap(); - let is_local = r == Rule::local_def; - // println!("{:?} {:?}", r, inner.as_rule()); - match inner.as_rule() { - Rule::node_def => { - ret.push(build_node_def(inner, is_local)?); - } - _ => todo!() - } - } - Rule::EOI => {} - _ => unreachable!() - } - } - Ok(ret) -} - -pub fn build_statements_from_str(inp: &str) -> Result, CozoError> { - let expr_tree = Parser::parse(Rule::file, inp)?; - build_statements(expr_tree) -} - #[cfg(test)] mod tests { use super::*; @@ -364,15 +239,4 @@ mod tests { assert_eq!(parse_expr_from_str(r#####"r###"x"yz"###"#####).unwrap(), Const(Value::RefString(r##"x"yz"##))); } - #[test] - fn definitions() { - println!("{:#?}", build_statements_from_str(r#" - local node "Person" { - *id: Int, - name: String, - email: ?String, - habits: [String] - } - "#).unwrap()); - } } \ No newline at end of file diff --git a/src/definition.rs b/src/definition.rs new file mode 100644 index 00000000..d140526f --- /dev/null +++ b/src/definition.rs @@ -0,0 +1,241 @@ +use pest::Parser as PestParser; +use pest::iterators::{Pair, Pairs}; +use crate::ast::parse_string; +use crate::env::Env; +use crate::error::CozoError; +use crate::error::CozoError::*; +use crate::parser::{Parser, Rule}; +use crate::typing::{BaseType, Col, Edge, Node, Structured, StructuredEnv, StructuredEnvItem, TableId, Typing}; +use crate::typing::Persistence::{Global, Local}; +use crate::typing::StorageStatus::Planned; +use crate::value::Value; + +fn parse_ident(pair: Pair) -> String { + pair.as_str().to_string() +} + +fn build_name_in_def(pair: Pair, forbid_underscore: bool) -> Result { + let inner = pair.into_inner().next().unwrap(); + let name = match inner.as_rule() { + Rule::ident => parse_ident(inner), + Rule::raw_string | Rule::s_quoted_string | Rule::quoted_string => parse_string(inner)?, + _ => unreachable!() + }; + if forbid_underscore && name.starts_with('_') { + Err(ReservedIdent) + } else { + Ok(name) + } +} + +fn parse_col_name(pair: Pair) -> Result<(String, bool), CozoError> { + let mut pairs = pair.into_inner(); + let mut is_key = false; + let mut nxt_pair = pairs.next().unwrap(); + if nxt_pair.as_rule() == Rule::key_marker { + is_key = true; + nxt_pair = pairs.next().unwrap(); + } + + Ok((build_name_in_def(nxt_pair, true)?, is_key)) +} + + +impl StructuredEnvItem { + pub fn build_edge_def(&mut self, pair: Pair, table_id: TableId) -> Result<(), CozoError> { + let mut inner = pair.into_inner(); + let src_name = build_name_in_def(inner.next().unwrap(), true)?; + let src = self.resolve(&src_name).ok_or(UndefinedType)?; + let src_id = if let Structured::Node(n, _) = src { + n.id + } else { + return Err(WrongType); + }; + let name = build_name_in_def(inner.next().unwrap(), true)?; + let dst_name = build_name_in_def(inner.next().unwrap(), true)?; + let dst = self.resolve(&dst_name).ok_or(UndefinedType)?; + let dst_id = if let Structured::Node(n, _) = dst { + n.id + } else { + return Err(WrongType); + }; + if table_id.0 == Global && (src_id.0 == Local || dst_id.0 == Local) { + return Err(IncompatibleEdge); + } + let (keys, cols) = if let Some(p) = inner.next() { + self.build_col_defs(p)? + } else { + (vec![], vec![]) + }; + let edge = Edge { + src: src_id, + dst: dst_id, + id: table_id, + keys, + cols, + }; + if self.define_new(name.to_string(), Structured::Edge(edge, Planned)) { + if let Some(Structured::Node(src, _)) = self.resolve_mut(&src_name) { + src.out_e.push(table_id); + } else { + unreachable!() + } + + if let Some(Structured::Node(dst, _)) = self.resolve_mut(&dst_name) { + dst.in_e.push(table_id); + } else { + unreachable!() + } + Ok(()) + } else { + Err(NameConflict) + } + } + pub fn build_node_def(&mut self, pair: Pair, table_id: TableId) -> Result<(), CozoError> { + let mut inner = pair.into_inner(); + let name = build_name_in_def(inner.next().unwrap(), true)?; + let (keys, cols) = self.build_col_defs(inner.next().unwrap())?; + let node = Node { + id: table_id, + keys, + cols, + out_e: vec![], + in_e: vec![], + attached: vec![], + }; + if self.define_new(name.to_string(), Structured::Node(node, Planned)) { + Ok(()) + } else { + Err(NameConflict) + } + } + + fn build_type(&self, pair: Pair) -> Result { + let mut pairs = pair.into_inner(); + let mut inner = pairs.next().unwrap(); + let nullable = if Rule::nullable_marker == inner.as_rule() { + inner = pairs.next().unwrap(); + true + } else { + false + }; + let t = match inner.as_rule() { + Rule::simple_type => { + let name = parse_ident(inner.into_inner().next().unwrap()); + if let Some(Structured::Typing(t)) = self.resolve(&name) { + t.clone() + } else { + return Err(UndefinedType); + } + } + Rule::list_type => { + let inner_t = self.build_type(inner.into_inner().next().unwrap())?; + Typing::HList(Box::new(inner_t)) + } + // Rule::tuple_type => {}, + _ => unreachable!() + }; + Ok(if nullable { + Typing::Nullable(Box::new(t)) + } else { + t + }) + } + + fn build_default_value(&self, _pair: Pair) -> Result, CozoError> { + // TODO: _pair is an expression, parse it and evaluate it to a constant value + Ok(Value::Null) + } + + fn build_col_entry(&self, pair: Pair) -> Result<(Col, bool), CozoError> { + let mut pairs = pair.into_inner(); + let (name, is_key) = parse_col_name(pairs.next().unwrap())?; + let typ = self.build_type(pairs.next().unwrap())?; + let default = if let Some(p) = pairs.next() { + // TODO: check value is suitable for the type + Some(self.build_default_value(p)?) + } else { + None + }; + Ok((Col { + name, + typ, + default, + }, is_key)) + } + + fn build_col_defs(&self, pair: Pair) -> Result<(Vec, Vec), CozoError> { + let mut keys = vec![]; + let mut cols = vec![]; + for pair in pair.into_inner() { + let (col, is_key) = self.build_col_entry(pair)?; + if is_key { + keys.push(col) + } else { + cols.push(col) + } + } + + Ok((keys, cols)) + } +} + +impl StructuredEnv { + pub fn build_table(&mut self, pairs: Pairs) -> Result<(), CozoError> { + for pair in pairs { + match pair.as_rule() { + r @ (Rule::global_def | Rule::local_def) => { + let inner = pair.into_inner().next().unwrap(); + let is_local = r == Rule::local_def; + let next_id = self.get_next_table_id(is_local); + let env_to_build = if is_local { + self.root_mut() + } else { + self.cur_mut() + }; + + // println!("{:?} {:?}", r, inner.as_rule()); + match inner.as_rule() { + Rule::node_def => { + env_to_build.build_node_def(inner, next_id)?; + } + Rule::edge_def => { + env_to_build.build_edge_def(inner, next_id)?; + } + _ => todo!() + } + } + Rule::EOI => {} + _ => unreachable!() + } + } + Ok(()) + } +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn definitions() { + let s = r#" + local node "Person" { + *id: Int, + name: String, + email: ?String, + habits: ?[?String] + } + + local edge (Person)-[Friend]->(Person) { + relation: ?String + } + "#; + let parsed = Parser::parse(Rule::file, s).unwrap(); + let mut env = StructuredEnv::new(); + env.build_table(parsed).unwrap(); + println!("{:#?}", env.resolve("Person")); + println!("{:#?}", env.resolve("Friend")); + } +} \ No newline at end of file diff --git a/src/env.rs b/src/env.rs index 16d93a1e..46bcbf93 100644 --- a/src/env.rs +++ b/src/env.rs @@ -1,5 +1,15 @@ pub trait Env { - fn define(&mut self, name: &str, value: V) -> Option; - fn resolve(&self, name: &str) -> Option; + fn define(&mut self, name: String, value: V) -> Option; + fn define_new(&mut self, name: String, value: V) -> bool; + fn resolve(&self, name: &str) -> Option<&V>; + fn resolve_mut(&mut self, name: &str) -> Option<&mut V>; fn undef(&mut self, name: &str) -> Option; } + +pub trait LayeredEnv : Env { + fn root_define(&mut self, name: String, value: V) -> Option; + fn root_define_new(&mut self, name: String, value: V) -> bool; + fn root_resolve(&self, name: &str) -> Option<&V>; + fn root_resolve_mut(&mut self, name: &str) -> Option<&mut V>; + fn root_undef(&mut self, name: &str) -> Option; +} \ No newline at end of file diff --git a/src/error.rs b/src/error.rs index ce8c302e..6bef80ee 100644 --- a/src/error.rs +++ b/src/error.rs @@ -15,6 +15,18 @@ pub enum CozoError { #[error("Reserved identifier")] ReservedIdent, + #[error("The requested name exists")] + NameConflict, + + #[error("Undefined type")] + UndefinedType, + + #[error("Wrong type")] + WrongType, + + #[error("Cannot have global edge between local nodes")] + IncompatibleEdge, + #[error(transparent)] ParseInt(#[from] std::num::ParseIntError), diff --git a/src/eval.rs b/src/eval.rs index e357d227..0816ad2d 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -4,8 +4,23 @@ use crate::error::CozoError; use crate::error::CozoError::*; use crate::value::Value::*; use crate::ast::*; +use crate::typing::StructuredEnv; -struct Evaluator; +pub struct Evaluator { + pub s_envs: StructuredEnv, +} + +impl Evaluator { + pub fn new() -> Self { + Self { s_envs: StructuredEnv::new() } + } +} + +impl Default for Evaluator { + fn default() -> Self { + Evaluator::new() + } +} impl<'a> ExprVisitor<'a, Result, CozoError>> for Evaluator { fn visit_expr(&mut self, ex: &Expr<'a>) -> Result, CozoError> { @@ -491,7 +506,7 @@ mod tests { #[test] fn operators() { - let mut ev = Evaluator {}; + let mut ev = Evaluator::new(); println!("{:#?}", ev.visit_expr(&parse_expr_from_str("1/10+(-2+3)*4^5").unwrap()).unwrap()); println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true && false").unwrap()).unwrap()); diff --git a/src/grammar.pest b/src/grammar.pest index a7c2f1c3..24152354 100644 --- a/src/grammar.pest +++ b/src/grammar.pest @@ -146,7 +146,7 @@ col_list = {"(" ~ name_in_def ~ ("," ~ name_in_def)* ~ ","? ~ ")"} node_def = { "node" ~ name_in_def ~ cols_def } columns_def = { "columns" ~ name_in_def ~ ":" ~ name_in_def ~ cols_def } edge_def = { "edge" ~ - "[" ~ name_in_def ~ "]" ~ "-" ~ "(" ~ name_in_def ~ ")" ~ "->" ~ "[" ~ name_in_def ~ "]" + "(" ~ name_in_def ~ ")" ~ "-" ~ "[" ~ name_in_def ~ "]" ~ "->" ~ "(" ~ name_in_def ~ ")" ~ cols_def? } index_def = { "index" ~ (name_in_def ~ ":")? ~ name_in_def ~ col_list } struct_def = { "struct" ~ name_in_def ~ cols_def } diff --git a/src/lib.rs b/src/lib.rs index 890b5b1e..9707614d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,4 +5,5 @@ pub mod ast; pub mod parser; pub mod eval; pub mod function; -pub mod error; \ No newline at end of file +pub mod error; +pub mod definition; \ No newline at end of file diff --git a/src/typing.rs b/src/typing.rs index 26673ea2..38c7a7fd 100644 --- a/src/typing.rs +++ b/src/typing.rs @@ -1,7 +1,9 @@ use std::collections::BTreeMap; -use crate::env::Env; +use crate::ast::Op; +use crate::env::{Env, LayeredEnv}; +use crate::value::Value; -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug, Eq, PartialEq, Clone)] pub enum BaseType { Bool, Int, @@ -36,7 +38,231 @@ pub enum BaseType { Crs, } -#[derive(Debug, Eq, PartialEq)] +pub struct StructuredEnvItem { + map: BTreeMap, +} + + +pub struct StructuredEnv { + stack: Vec, +} + + +impl StructuredEnv { + pub fn new() -> Self { + let mut root = StructuredEnvItem { map: BTreeMap::new() }; + define_base_types(&mut root); + Self { stack: vec![root] } + } + + pub fn root(&self) -> &StructuredEnvItem { + &self.stack[0] + } + + pub fn root_mut(&mut self) -> &mut StructuredEnvItem { + &mut self.stack[0] + } + + pub fn cur(&self) -> &StructuredEnvItem { + self.stack.last().unwrap() + } + + pub fn cur_mut(&mut self) -> &mut StructuredEnvItem { + self.stack.last_mut().unwrap() + } + + pub fn push(&mut self) { + self.stack.push(StructuredEnvItem { map: BTreeMap::new() }) + } + pub fn pop(&mut self) -> bool { + if self.stack.len() <= 1 { + false + } else { + self.stack.pop(); + true + } + } + + pub fn get_next_table_id(&self, local: bool) -> TableId { + let mut id = 0; + let persistence = if local { Persistence::Local } else { Persistence::Global }; + for env in &self.stack { + for item in env.map.values() { + if let Some(TableId(p, eid)) = item.storage_id() { + if p == persistence { + id = id.max(eid); + } + } + } + } + TableId(persistence, id + 1) + } +} + +impl LayeredEnv for StructuredEnv { + fn root_define(&mut self, name: String, value: Structured) -> Option { + self.root_mut().define(name, value) + } + + fn root_define_new(&mut self, name: String, value: Structured) -> bool { + self.root_mut().define_new(name, value) + } + + fn root_resolve(&self, name: &str) -> Option<&Structured> { + self.root().resolve(name) + } + + fn root_resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { + self.root_mut().resolve_mut(name) + } + + fn root_undef(&mut self, name: &str) -> Option { + self.root_mut().undef(name) + } +} + +impl Env for StructuredEnv { + fn define(&mut self, name: String, value: Structured) -> Option { + self.stack.last_mut().unwrap().define(name, value) + } + + fn define_new(&mut self, name: String, value: Structured) -> bool { + self.stack.last_mut().unwrap().define_new(name, value) + } + + fn resolve(&self, name: &str) -> Option<&Structured> { + let mut res = None; + for item in self.stack.iter().rev() { + res = item.resolve(name); + if res.is_some() { + return res; + } + } + res + } + + fn resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { + let mut res = None; + for item in self.stack.iter_mut().rev() { + res = item.resolve_mut(name); + if res.is_some() { + return res; + } + } + res + } + + fn undef(&mut self, name: &str) -> Option { + let mut res = None; + for item in self.stack.iter_mut().rev() { + res = item.undef(name); + if res.is_some() { + return res; + } + } + res + } +} + +impl Env for StructuredEnvItem { + fn define(&mut self, name: String, value: Structured) -> Option { + 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<&Structured> { + self.map.get(name) + } + + fn resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { + self.map.get_mut(name) + } + + + fn undef(&mut self, name: &str) -> Option { + self.map.remove(name) + } +} + + +impl Default for StructuredEnv { + fn default() -> Self { + StructuredEnv::new() + } +} + + +#[derive(Debug, PartialEq, Clone)] +pub struct Col { + pub name: String, + pub typ: Typing, + pub default: Option>, +} + +#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Clone, Copy)] +pub enum Persistence { + Global, + Local, +} + +#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Clone)] +pub enum StorageStatus { + Planned, + Verified, + Stored, +} + +#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Clone, Copy)] +pub struct TableId(pub Persistence, pub usize); + +#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)] +pub struct ColumnId(TableId, usize); + +#[derive(Debug, PartialEq, Clone)] +pub struct Node { + pub id: TableId, + pub keys: Vec, + pub cols: Vec, + pub out_e: Vec, + pub in_e: Vec, + pub attached: Vec, +} + +#[derive(Debug, PartialEq, Clone)] +pub struct Edge { + pub src: TableId, + pub dst: TableId, + pub id: TableId, + pub keys: Vec, + pub cols: Vec, +} + +#[derive(Debug, PartialEq, Clone)] +pub struct Columns { + pub attached: TableId, + pub id: TableId, + pub cols: Vec, +} + +#[derive(Debug, PartialEq, Clone)] +pub struct Index { + pub id: TableId, + pub attached: TableId, + pub cols: Vec, +} + + +#[derive(Debug, Eq, PartialEq, Clone)] pub enum Typing { Any, Base(BaseType), @@ -46,25 +272,45 @@ pub enum Typing { NamedTuple(BTreeMap), } +#[derive(Debug, PartialEq, Clone)] +pub enum Structured { + Typing(Typing), + Node(Node, StorageStatus), + Edge(Edge, StorageStatus), + Columns(Columns, StorageStatus), + Index(Index, StorageStatus), +} + +impl Structured { + fn storage_id(&self) -> Option { + match self { + Structured::Typing(_) => None, + Structured::Node(n, _) => Some(n.id), + Structured::Edge(e, _) => Some(e.id), + Structured::Columns(c, _) => Some(c.id), + Structured::Index(i, _) => Some(i.id) + } + } +} -pub fn define_types>(env: &mut T) { - env.define("Any", Typing::Any); - env.define("Bool", Typing::Base(BaseType::Bool)); - env.define("Int", Typing::Base(BaseType::Int)); - env.define("UInt", Typing::Base(BaseType::UInt)); - env.define("Float", Typing::Base(BaseType::Float)); - env.define("String", Typing::Base(BaseType::String)); - env.define("Bytes", Typing::Base(BaseType::U8Arr)); - env.define("U8Arr", Typing::Base(BaseType::U8Arr)); - env.define("Uuid", Typing::Base(BaseType::Uuid)); - env.define("Timestamp", Typing::Base(BaseType::Timestamp)); - env.define("Datetime", Typing::Base(BaseType::Datetime)); - env.define("Timezone", Typing::Base(BaseType::Timezone)); - env.define("Date", Typing::Base(BaseType::Date)); - env.define("Time", Typing::Base(BaseType::Time)); - env.define("Duration", Typing::Base(BaseType::Duration)); - env.define("BigInt", Typing::Base(BaseType::BigInt)); - env.define("BigDecimal", Typing::Base(BaseType::BigDecimal)); - env.define("Int", Typing::Base(BaseType::Int)); - env.define("Crs", Typing::Base(BaseType::Crs)); +pub fn define_base_types>(env: &mut T) { + env.define("Any".to_string(), Structured::Typing(Typing::Any)); + env.define("Bool".to_string(), Structured::Typing(Typing::Base(BaseType::Bool))); + env.define("Int".to_string(), Structured::Typing(Typing::Base(BaseType::Int))); + env.define("UInt".to_string(), Structured::Typing(Typing::Base(BaseType::UInt))); + env.define("Float".to_string(), Structured::Typing(Typing::Base(BaseType::Float))); + env.define("String".to_string(), Structured::Typing(Typing::Base(BaseType::String))); + env.define("Bytes".to_string(), Structured::Typing(Typing::Base(BaseType::U8Arr))); + env.define("U8Arr".to_string(), Structured::Typing(Typing::Base(BaseType::U8Arr))); + env.define("Uuid".to_string(), Structured::Typing(Typing::Base(BaseType::Uuid))); + env.define("Timestamp".to_string(), Structured::Typing(Typing::Base(BaseType::Timestamp))); + env.define("Datetime".to_string(), Structured::Typing(Typing::Base(BaseType::Datetime))); + env.define("Timezone".to_string(), Structured::Typing(Typing::Base(BaseType::Timezone))); + env.define("Date".to_string(), Structured::Typing(Typing::Base(BaseType::Date))); + env.define("Time".to_string(), Structured::Typing(Typing::Base(BaseType::Time))); + env.define("Duration".to_string(), Structured::Typing(Typing::Base(BaseType::Duration))); + env.define("BigInt".to_string(), Structured::Typing(Typing::Base(BaseType::BigInt))); + env.define("BigDecimal".to_string(), Structured::Typing(Typing::Base(BaseType::BigDecimal))); + env.define("Int".to_string(), Structured::Typing(Typing::Base(BaseType::Int))); + env.define("Crs".to_string(), Structured::Typing(Typing::Base(BaseType::Crs))); } \ No newline at end of file