From 2f26dcc936663def70c06ca653bb0fa4ead96477 Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Sun, 1 Oct 2023 17:03:47 +0200
Subject: [PATCH] add term, dict & bimap

---
 src/bimap.rs | 25 +++++++++++++++++++
 src/dict.rs  | 60 ++++++++++++++++++++++++++++++++++++++++++++++
 src/lib.rs   | 11 +++++----
 src/term.rs  | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 159 insertions(+), 5 deletions(-)
 create mode 100644 src/bimap.rs
 create mode 100644 src/dict.rs
 create mode 100644 src/term.rs

diff --git a/src/bimap.rs b/src/bimap.rs
new file mode 100644
index 0000000..177c041
--- /dev/null
+++ b/src/bimap.rs
@@ -0,0 +1,25 @@
+use std::{collections::HashMap, hash::Hash};
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
+
+pub struct Bimap<V: Eq + Hash, Λ: Eq + Hash> {
+    pub mλ: HashMap<V, Λ>,
+    pub my: HashMap<Λ, V>,
+}
+
+impl<V: Eq + Hash + Clone, Λ: Eq + Hash + Clone> Bimap<V, Λ> {
+    pub fn new() -> Self {
+        Bimap {
+            mλ: HashMap::new(),
+            my: HashMap::new(),
+        }
+    }
+
+    pub fn insert(&mut self, y: V, λ: Λ) {
+        self.mλ.insert(y.clone(), λ.clone());
+        self.my.insert(λ, y);
+    }
+}
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
+
diff --git a/src/dict.rs b/src/dict.rs
new file mode 100644
index 0000000..45620c5
--- /dev/null
+++ b/src/dict.rs
@@ -0,0 +1,60 @@
+use crate::bimap::Bimap;
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
+
+#[derive(Eq, PartialEq, Hash, Clone, Debug)]
+pub enum TypeID {
+    Fun(u64),
+    Var(u64)
+}
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
+
+pub struct TypeDict {
+    typenames: Bimap<String, TypeID>,
+    type_lit_counter: u64,
+    type_var_counter: u64,
+}
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
+
+impl TypeDict {
+    pub fn new() -> Self {
+        TypeDict {
+            typenames: Bimap::new(),
+            type_lit_counter: 0,
+            type_var_counter: 0,
+        }
+    }
+
+    pub fn add_varname(&mut self, tn: String) -> TypeID {
+        let tyid = TypeID::Var(self.type_var_counter);
+        self.type_var_counter += 1;
+        self.typenames.insert(tn, tyid.clone());
+        tyid
+    }
+
+    pub fn add_typename(&mut self, tn: String) -> TypeID {
+        let tyid = TypeID::Fun(self.type_lit_counter);
+        self.type_lit_counter += 1;
+        self.typenames.insert(tn, tyid.clone());
+        tyid
+    }
+
+    pub fn add_synonym(&mut self, new: String, old: String) {
+        if let Some(tyid) = self.get_typeid(&old) {
+            self.typenames.insert(new, tyid);
+        }
+    }
+
+    pub fn get_typename(&self, tid: &TypeID) -> Option<String> {
+        self.typenames.my.get(tid).cloned()
+    }
+
+    pub fn get_typeid(&self, tn: &String) -> Option<TypeID> {
+        self.typenames.mλ.get(tn).cloned()
+    }
+}
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
+
diff --git a/src/lib.rs b/src/lib.rs
index bae0eed..08b487a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,12 +1,13 @@
 
+
 pub mod lexer;
-//pub mod bimap;
-//pub mod dict;
-//pub mod term;
+pub mod bimap;
+pub mod dict;
+pub mod term;
 
 pub use {
-//    dict::*,
-//    term::*,
+    dict::*,
+    term::*,
 };
 
 #[cfg(test)]
diff --git a/src/term.rs b/src/term.rs
new file mode 100644
index 0000000..b01a76c
--- /dev/null
+++ b/src/term.rs
@@ -0,0 +1,68 @@
+use {
+    crate::TypeID,
+    std::collections::HashMap
+};
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
+
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub enum TypeTerm {
+
+    /* Atomic Terms */
+
+    // Base types from dictionary
+    TypeID(TypeID),
+
+    // Literals
+    Num(i64),
+    Char(char),
+
+    
+
+    /* Complex Terms */
+
+    // Type Parameters
+    // avoid currying to save space & indirection
+    App(Vec< TypeTerm >),
+
+    // Type Ladders
+    Ladder(Vec< TypeTerm >),
+}
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
+
+impl TypeTerm {
+    pub fn unit() -> Self {
+        TypeTerm::Ladder(vec![])
+    }
+
+    pub fn new(id: TypeID) -> Self {
+        TypeTerm::TypeID(id)
+    }
+
+    pub fn arg(&mut self, t: impl Into<TypeTerm>) -> &mut Self {
+        match self {
+            TypeTerm::App(args) => {
+                args.push(t.into());                
+            }
+
+            _ => {
+                *self = TypeTerm::App(vec![
+                    self.clone(),
+                    t.into()
+                ])                
+            }
+        }
+
+        self
+    }
+
+    pub fn num_arg(&mut self, v: i64) -> &mut Self {
+        self.arg(TypeTerm::Num(v))
+    }
+
+    pub fn char_arg(&mut self, c: char) -> &mut Self {
+        self.arg(TypeTerm::Char(c))
+    }
+}
+