From 51dcf19eb6f8d2127f3dedfc1d7d5326d7a8017b Mon Sep 17 00:00:00 2001 From: Greg Brown Date: Tue, 27 Apr 2021 13:07:27 +0100 Subject: Start rewrite using query system. --- src/chomp/intern.rs | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 src/chomp/intern.rs (limited to 'src/chomp/intern.rs') diff --git a/src/chomp/intern.rs b/src/chomp/intern.rs new file mode 100644 index 0000000..b224e53 --- /dev/null +++ b/src/chomp/intern.rs @@ -0,0 +1,151 @@ +use std::{cell::RefCell, collections::HashMap, hash::Hash, rc::Rc}; + +use super::{ + ast::Tree, + typed::{GroundType, Type}, +}; + +#[derive(Debug)] +pub struct Intern(Rc); + +impl PartialEq for Intern { + fn eq(&self, other: &Self) -> bool { + Rc::ptr_eq(&self.0, &other.0) + } +} + +impl Eq for Intern {} + +impl Hash for Intern { + fn hash(&self, state: &mut H) { + Rc::as_ptr(&self.0).hash(state) + } +} + +impl From> for Intern { + fn from(inner: Rc) -> Self { + Self(inner) + } +} + +#[derive(Debug)] +pub struct TreeInterner { + epsilon: Option>, + bottom: Option>, + identity: Option>, + literal: HashMap>, + cat: HashMap<(Intern, Intern), Rc>, + alt: HashMap<(Intern, Intern), Rc>, + fix: HashMap, Rc>, + call: HashMap<(Intern, Intern), Rc>, +} + +impl TreeInterner { + pub fn epsilon(&mut self) -> Rc { + self.epsilon + .get_or_insert_with(|| Rc::new(Tree::Epsilon)) + .clone() + } + + pub fn bottom(&mut self) -> Rc { + self.bottom + .get_or_insert_with(|| Rc::new(Tree::Bottom)) + .clone() + } + + pub fn identity(&mut self) -> Rc { + self.identity + .get_or_insert_with(|| Rc::new(Tree::Identity)) + .clone() + } + + pub fn literal(&mut self, lit: String) -> Rc { + self.literal + .entry(lit) + .or_insert_with_key(|lit| Rc::new(Tree::Literal(lit.clone()))) + .clone() + } + + pub fn cat(&mut self, front: Rc, back: Rc) -> Rc { + self.cat + .entry((Intern(front), Intern(back))) + .or_insert_with_key(|(front, back)| Rc::new(Tree::Cat(front.0.clone(), back.0.clone()))) + .clone() + } + + pub fn alt(&mut self, left: Rc, right: Rc) -> Rc { + self.alt + .entry((Intern(left), Intern(right))) + .or_insert_with_key(|(left, right)| Rc::new(Tree::Alt(left.0.clone(), right.0.clone()))) + .clone() + } + + pub fn fix(&mut self, inner: Rc) -> Rc { + self.fix + .entry(Intern(inner)) + .or_insert_with_key(|inner| Rc::new(Tree::Fix(inner.0.clone()))) + .clone() + } + + pub fn call(&mut self, fun: Rc, arg: Rc) -> Rc { + self.call + .entry((Intern(fun), Intern(arg))) + .or_insert_with_key(|(fun, arg)| Rc::new(Tree::Call(fun.0.clone(), arg.0.clone()))) + .clone() + } +} + +#[derive(Debug)] +pub struct TypeInterner { + epsilon: Option>, + bottom: Option>, + character: HashMap>, + cat: HashMap<(Intern, Intern), Rc>, + alt: HashMap<(Intern, Intern), Rc>, + fix: HashMap, Rc>, +} + +impl TypeInterner { + pub fn epsilon(&mut self) -> Rc { + self.epsilon + .get_or_insert_with(|| Rc::new(GroundType::Epsilon.into())) + .clone() + } + + pub fn bottom(&mut self) -> Rc { + self.bottom + .get_or_insert_with(|| Rc::new(GroundType::Bottom.into())) + .clone() + } + + pub fn character(&mut self, c: char) -> Rc { + self.character + .entry(c) + .or_insert_with(|| Rc::new(GroundType::Character(c).into())) + .clone() + } + + pub fn cat(&mut self, front: Rc, back: Rc) -> Rc { + self.cat + .entry((Intern(front), Intern(back))) + .or_insert_with_key(|(front, back)| { + Rc::new( + GroundType::Cat(RefCell::new(front.0.clone()), RefCell::new(back.0.clone())) + .into(), + ) + }) + .clone() + } + + pub fn alt(&mut self, left: Rc, right: Rc) -> Rc { + self.alt + .entry((Intern(left), Intern(right))) + .or_insert_with_key(|(left, right)| { + Rc::new( + GroundType::Alt(RefCell::new(left.0.clone()), RefCell::new(right.0.clone())) + .into(), + ) + }) + .clone() + } +} -- cgit v1.2.3