From 193b8c8cacc83bf20e6e8e8159ee77776ccdb576 Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Thu, 18 Jan 2024 19:32:49 +0100
Subject: [PATCH] implement MorphismBase,  remove `data` from NestedNode

---
 examples/tty-02-node/src/main.rs            | 189 ++++++-------
 lib-nested-core/src/edit_tree/node.rs       |  68 +----
 lib-nested-core/src/editors/integer/ctx.rs  |   5 +-
 lib-nested-core/src/editors/list/editor.rs  |   3 +-
 lib-nested-core/src/editors/typeterm/ctx.rs |   4 +-
 lib-nested-core/src/repr_tree/context.rs    | 287 +-------------------
 lib-nested-core/src/repr_tree/mod.rs        | 113 +-------
 lib-nested-core/src/repr_tree/morphism.rs   | 105 +++++++
 lib-nested-tty/src/editors/mod.rs           |  81 ++++++
 9 files changed, 309 insertions(+), 546 deletions(-)
 create mode 100644 lib-nested-core/src/repr_tree/morphism.rs

diff --git a/examples/tty-02-node/src/main.rs b/examples/tty-02-node/src/main.rs
index d6199a8..2fe3791 100644
--- a/examples/tty-02-node/src/main.rs
+++ b/examples/tty-02-node/src/main.rs
@@ -7,87 +7,36 @@ extern crate termion;
 use {
     cgmath::Vector2,
     nested::{
-        edit_tree::{NestedNode, TreeCursor, TreeNav},
-        repr_tree::{Context, ReprTree},
-        editors::ObjCommander
+        editors::ObjCommander,
+        repr_tree::{Context},
     },
     nested_tty::{
-        terminal::TermOutWriter, DisplaySegment, Terminal, TerminalAtom, TerminalCompositor,
-        TerminalEvent, TerminalStyle, TerminalView,
-        TTYApplication
+        DisplaySegment, TTYApplication,
+        TerminalCompositor, TerminalStyle, TerminalView,
     },
     r3vi::{
         buffer::singleton::*,
-        view::{port::UpdateTask, singleton::*, sequence::*, ViewPort},
-        projection::decorate_sequence::*
     },
-    std::sync::{Arc, Mutex, RwLock},
-    termion::event::{Event, Key},
+    std::sync::{Arc, RwLock},
 };
 
-fn node_make_char_view(
-    node: NestedNode
-) -> NestedNode {
-    node.disp.view
-        .write().unwrap()
-        .insert_branch(ReprTree::new_leaf(
-            Context::parse(&node.ctx, "TerminalView"),
-            node.data
-                .read()
-                .unwrap()
-                .get_port::<dyn SingletonView<Item = char>>()
-                .expect("unable to get Char-view")
-                .map(move |c| TerminalAtom::from(if c == '\0' { ' ' } else { c }))
-                .to_grid()
-                .into(),
-        ));
-
-    node
-}
-
-fn node_make_seq_view(
-    mut node: NestedNode
-) -> NestedNode {
-    node.disp.view
-        .write().unwrap()
-        .insert_branch(ReprTree::new_leaf(
-            Context::parse(&node.ctx, "TerminalView"),
-            node.data
-                .read()
-                .unwrap()
-                .get_port::< dyn SequenceView<Item = NestedNode> >()
-                .expect("unable to get Seq-view")
-                .map(move |char_node| node_make_view(char_node.clone()).display_view() )
-                .wrap(nested_tty::make_label("("), nested_tty::make_label(")"))
-                .to_grid_horizontal()
-                .flatten()
-                .into()
-        ));
-    node
-}
-
-fn node_make_list_edit(
-    mut node: NestedNode
-) -> NestedNode {
-    nested_tty::editors::list::PTYListStyle::for_node( &mut node, ("(", ",", ")") );
-    nested_tty::editors::list::PTYListController::for_node( &mut node, None, None );
-
-    node
-}
-
-fn node_make_view(
-    node: NestedNode
-) -> NestedNode {
-    if node.data.read().unwrap().get_type() == &Context::parse(&node.ctx, "Char") {
-        node_make_char_view( node )
-    } else if node.data.read().unwrap().get_type() == &Context::parse(&node.ctx, "<Seq Char>") {
-        node_make_seq_view( node )
-    } else if node.data.read().unwrap().get_type() == &Context::parse(&node.ctx, "<List Char>") {
-        node_make_list_edit( node )
-    } else {
-        eprintln!("couldnt add view");
-        node
+struct ParseDigit { radix: u32 };
+impl Morphism for ParseDigit {
+    fn new(
+        ctx: &Arc<RwLock<Context>>
+    ) -> Self {
+        
     }
+
+    fn setup_projection(&self, repr_tree: Arc<RwLock<ReprTree>>) {
+        if let Some( char_view ) = repr_tree.get_out(Context::parse(&ctx, "Char~")) {
+            
+        }
+    }
+}
+
+get_morphism( ) -> Morphism {
+    
 }
 
 #[async_std::main]
@@ -96,19 +45,36 @@ async fn main() {
      */
     let ctx = Arc::new(RwLock::new(Context::default()));
 
-
     /* Create a Char-Node with editor & view
      */
-    let mut node1 = Context::make_node(
+    let mut char_obj = ReprTree::make_leaf(
+        Context::parse(&ctx, "Char"),
+        SingletonBuffer::new('X').get_port().into()
+    );
+
+    char_obj.insert_branch(
+        Context::parse(&ctx, "EditTree"),
+        SingletonBuffer::new(
+            
+        )
+    );
+
+    let mut vec_obj = ReprTree::make_leaf(
+        Context::parse(&ctx, "<Vec Char>"),
+        VecBuffer::new(vec!['a', 'b', 'c']).get_port().into()
+    );
+
+    let mut char_edit = Context::new_edit_tree(
         &ctx,
         // node type
         Context::parse(&ctx, "Char"),
         // depth
         SingletonBuffer::new(0).get_port(),
-    ).unwrap();
+    )
+    .unwrap();
 
     // add a display view to the node
-    node1 = node_make_view( node1 );
+    node1 = nested_tty::editors::node_make_tty_view(node1);
 
     /* Create a <List Char>-Node with editor & view
      */
@@ -118,10 +84,25 @@ async fn main() {
         Context::parse(&ctx, "<List Char>"),
         // depth
         SingletonBuffer::new(0).get_port(),
-    ).unwrap();
+    )
+    .unwrap();
 
     // add a display view to the node
-    node2 = node_make_view( node2 );
+    node2 = nested_tty::editors::node_make_tty_view(node2);
+
+    /* Create a <List Char>-Node with editor & view
+     */
+    let mut node3 = Context::make_node(
+        &ctx,
+        // node type
+        Context::parse(&ctx, "<List <List Char>>"),
+        // depth
+        SingletonBuffer::new(0).get_port(),
+    )
+    .unwrap();
+
+    // add a display view to the node
+    node3 = nested_tty::editors::node_make_tty_view(node3);
 
     /* setup terminal
      */
@@ -130,13 +111,16 @@ async fn main() {
          */
 
         let ctx = ctx.clone();
-        let mut node1 = node1.clone();
-        let mut node2 = node2.clone();
-        move |ev| {           
+        let node1 = node1.clone();
+        let node2 = node2.clone();
+        let node3 = node3.clone();
+        move |ev| {
             let mut node1 = node1.clone();
             let mut node2 = node2.clone();
-            node1.send_cmd_obj( ev.to_repr_tree(&ctx) );
-            node2.send_cmd_obj( ev.to_repr_tree(&ctx) );
+            let mut node3 = node3.clone();
+            node1.send_cmd_obj(ev.to_repr_tree(&ctx));
+            node2.send_cmd_obj(ev.to_repr_tree(&ctx));
+            node3.send_cmd_obj(ev.to_repr_tree(&ctx));
         }
     });
 
@@ -144,7 +128,7 @@ async fn main() {
      */
     let compositor = TerminalCompositor::new(app.port.inner());
 
-    // add some views to the display compositor 
+    // add some views to the display compositor
     compositor.write().unwrap().push(
         nested_tty::make_label("Hello World")
             .map_item(|p, a| {
@@ -153,21 +137,40 @@ async fn main() {
             .offset(Vector2::new(5, 0)),
     );
 
-    let label = ctx.read().unwrap().type_term_to_str( &node1.get_type() );
-    compositor.write().unwrap()
-        .push(nested_tty::make_label( &label ).offset(Vector2::new(0, 2)));
+    let label = ctx.read().unwrap().type_term_to_str(&node1.get_type());
+    compositor
+        .write()
+        .unwrap()
+        .push(nested_tty::make_label(&label).offset(Vector2::new(0, 2)));
 
-    compositor.write().unwrap()
+    compositor
+        .write()
+        .unwrap()
         .push(node1.display_view().offset(Vector2::new(15, 2)));
 
+    let label2 = ctx.read().unwrap().type_term_to_str(&node2.get_type());
+    compositor
+        .write()
+        .unwrap()
+        .push(nested_tty::make_label(&label2).offset(Vector2::new(0, 3)));
 
-    let label2 = ctx.read().unwrap().type_term_to_str( &node2.get_type() );
-    compositor.write().unwrap()
-        .push(nested_tty::make_label( &label2 ).offset(Vector2::new(0, 3)));
-
-    compositor.write().unwrap()
+    compositor
+        .write()
+        .unwrap()
         .push(node2.display_view().offset(Vector2::new(15, 3)));
 
+
+    let label3 = ctx.read().unwrap().type_term_to_str(&node3.get_type());
+    compositor
+        .write()
+        .unwrap()
+        .push(nested_tty::make_label(&label3).offset(Vector2::new(0, 4)));
+
+    compositor
+        .write()
+        .unwrap()
+        .push(node3.display_view().offset(Vector2::new(25, 4)));
+
     /* write the changes in the view of `term_port` to the terminal
      */
     app.show().await.expect("output error!");
diff --git a/lib-nested-core/src/edit_tree/node.rs b/lib-nested-core/src/edit_tree/node.rs
index 84d0412..b60326a 100644
--- a/lib-nested-core/src/edit_tree/node.rs
+++ b/lib-nested-core/src/edit_tree/node.rs
@@ -52,9 +52,6 @@ pub struct NestedNode {
     /// context
     pub ctx: Arc<RwLock<Context>>,
 
-    /// abstract data view
-    pub data: Arc<RwLock<ReprTree>>,
-
     /// viewports for terminal display
     pub disp: NestedNodeDisplay,
 
@@ -63,7 +60,7 @@ pub struct NestedNode {
 }
 
 impl NestedNode {
-    pub fn new(ctx: Arc<RwLock<Context>>, data: Arc<RwLock<ReprTree>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> Self {
+    pub fn new(ctx: Arc<RwLock<Context>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> Self {
         NestedNode {
             disp: NestedNodeDisplay {
                 view: ReprTree::new_arc(Context::parse(&ctx, "Display")),
@@ -74,43 +71,13 @@ impl NestedNode {
                 editor: SingletonBuffer::new(None),
                 spillbuf: Arc::new(RwLock::new(Vec::new())),
                 cmd: SingletonBuffer::new(None),
-                close_char: SingletonBuffer::new(None),                
+                close_char: SingletonBuffer::new(None),            
                 tree_nav: SingletonBuffer::new(None),
             },
-            data,
             ctx
         }
     }
-
-    /* TODO: move into separate file/module
-    */
-    pub fn from_char(ctx: Arc<RwLock<Context>>, c: char) -> NestedNode {
-        let buf = r3vi::buffer::singleton::SingletonBuffer::<char>::new(c);
-
-        NestedNode::new(
-            ctx.clone(),
-            ReprTree::new_leaf(
-                Context::parse(&ctx, "Char"),
-                buf.get_port().into()
-            ),
-            SingletonBuffer::new(0).get_port()
-      )
-//            .set_editor(Arc::new(RwLock::new(buf)))
-    }
-
-    
-    //\\//\\
-
-    pub fn morph(self, ty: TypeTerm) -> NestedNode {
-        Context::morph_node(self, ty)
-    }
-
-    pub fn get_type(&self) -> TypeTerm {
-        self.data.read().unwrap().get_type().clone()
-    }
-
-    //\\//\\
-    
+   
     pub fn set_editor(mut self, editor: Arc<dyn Any + Send + Sync>) -> Self {
         self.edit.editor.set(Some(editor));
         self
@@ -137,33 +104,6 @@ impl NestedNode {
         self.disp.diag.clone().unwrap_or(ViewPort::new().into_outer())
     }
 
-    pub fn get_data_port<'a, V: View + ?Sized + 'static>(&'a self, type_str: impl Iterator<Item = &'a str>) -> Option<OuterViewPort<V>>
-    where V::Msg: Clone {
-        let ctx = self.ctx.clone();
-        let type_ladder = type_str.map(|s| Context::parse(&ctx, s));
-
-        let repr_tree = ReprTree::descend_ladder(&self.data, type_ladder)?;
-        repr_tree.clone().read().unwrap()
-            .get_port::<V>().clone()
-    }
-
-    pub fn get_data_view<'a, V: View + ?Sized + 'static>(&'a self, type_str: impl Iterator<Item = &'a str>) -> Option<Arc<V>>
-    where V::Msg: Clone {
-        self.get_data_port::<V>(type_str)?.get_view()
-    }
-
-    /* TODO
-    pub fn get_seq_view<'a, T: Clone>(&self, type_str: impl Iterator<Item = &'a str>) -> Option<OuterViewPort<dyn SingletonView<Item = T>>> {
-        self.get_data_view::<dyn SequenceView<Item = NestedNode>>(type_str)
-            .unwrap()
-            .map({
-                move |node| {
-                    node.get_data_view::<dyn SingletonView<Item = T>>().get()
-                }
-            })
-    }
-     */
-    
     pub fn get_edit<T: Send + Sync + 'static>(&self) -> Option<Arc<RwLock<T>>> {
         if let Some(edit) = self.edit.editor.get() {
             if let Ok(edit) = edit.downcast::<RwLock<T>>() {
@@ -187,7 +127,7 @@ impl TreeType for NestedNode {
         }
     }
 }
- */
+*/
 
 impl TreeNav for NestedNode {
     fn get_cursor(&self) -> TreeCursor {
diff --git a/lib-nested-core/src/editors/integer/ctx.rs b/lib-nested-core/src/editors/integer/ctx.rs
index 214ef8c..86875d0 100644
--- a/lib-nested-core/src/editors/integer/ctx.rs
+++ b/lib-nested-core/src/editors/integer/ctx.rs
@@ -6,7 +6,7 @@ use {
     laddertypes::{TypeTerm},
     crate::{
         repr_tree::{Context},
-        repr_tree::{MorphismTypePattern},
+        repr_tree::{MorphismType},
         editors::{
             list::*,
             integer::*
@@ -16,6 +16,7 @@ use {
 };
 
 pub fn init_ctx(ctx: &mut Context) {
+    /*
     ctx.add_typename("MachineInt".into());
     ctx.add_typename("u32".into());
     ctx.add_typename("u64".into());
@@ -126,7 +127,7 @@ pub fn init_ctx(ctx: &mut Context) {
             }
         )
     );
-    
+*/    
     ctx.add_typename("Date".into());
     ctx.add_typename("ISO-8601".into());
     ctx.add_typename("TimeSince".into());
diff --git a/lib-nested-core/src/editors/list/editor.rs b/lib-nested-core/src/editors/list/editor.rs
index 087861b..8619012 100644
--- a/lib-nested-core/src/editors/list/editor.rs
+++ b/lib-nested-core/src/editors/list/editor.rs
@@ -109,7 +109,7 @@ impl ListEditor {
 
         let e = editor.read().unwrap();
 
-        let mut node = NestedNode::new(ctx, data, depth)
+        let mut node = NestedNode::new(ctx, depth)
             .set_editor(editor.clone())
             .set_nav(editor.clone())
             .set_cmd(editor.clone())
@@ -307,6 +307,7 @@ impl ListEditor {
                 self.nexd();
 
                 let mut b = item.edit.spillbuf.write().unwrap();
+
                 let mut tail_node = Context::make_node(&self.ctx, self.typ.clone(), self.depth.map(|d| d+1)).unwrap();
                 tail_node.goto(TreeCursor::home());
 
diff --git a/lib-nested-core/src/editors/typeterm/ctx.rs b/lib-nested-core/src/editors/typeterm/ctx.rs
index 0039c8f..984bb19 100644
--- a/lib-nested-core/src/editors/typeterm/ctx.rs
+++ b/lib-nested-core/src/editors/typeterm/ctx.rs
@@ -4,7 +4,7 @@ use {
     },
     laddertypes::{TypeTerm},
     crate::{
-        repr_tree::{Context, MorphismTypePattern},
+        repr_tree::{Context, MorphismType},
         editors::{
             list::{ListEditor, ListSegmentSequence},
             typeterm::{State, TypeTermEditor}
@@ -26,7 +26,7 @@ pub fn init_ctx(ctx: &mut Context) {
     ctx.add_list_typename("Type::Ladder".into()); // = T1~T2~...
 
     ctx.add_morphism(
-        MorphismTypePattern { src_tyid: ctx.get_typeid("List"), dst_tyid: ctx.get_typeid("Type").unwrap() },
+        MorphismType { src_tyid: Context::parse(&ctx, "<List T>"), dst_tyid: Context::parse(&ctx, "Type") },
         Arc::new(move |node, _dst_type:_| {
             let ctx : Arc<RwLock<Context>> = Arc::new(RwLock::new(Context::with_parent(Some(node.ctx.clone()))));
             ctx.write().unwrap().meta_chars.push('~');
diff --git a/lib-nested-core/src/repr_tree/context.rs b/lib-nested-core/src/repr_tree/context.rs
index 56d331d..264e3cc 100644
--- a/lib-nested-core/src/repr_tree/context.rs
+++ b/lib-nested-core/src/repr_tree/context.rs
@@ -1,8 +1,8 @@
- use {
+use {
     r3vi::{view::{OuterViewPort, singleton::*}, buffer::{singleton::*}},
     laddertypes::{TypeDict, TypeTerm, TypeID},
     crate::{
-        repr_tree::{ReprTree},
+        repr_tree::{ReprTree, MorphismType, GenericReprTreeMorphism, MorphismBase},
         edit_tree::NestedNode
     },
     std::{
@@ -13,129 +13,26 @@
 
 //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
 
-#[derive(Clone, Copy, Hash, PartialEq, Eq)]
-pub enum MorphismMode {
-    /// Isomorphism
-    /// e.g. `( PositionalInteger 10 BigEndian ) <~> ( PositionalInteger 16 LittleEndian )`
-    Iso,
-
-    /// Monomorphism, i.e. injective functions,
-    /// upcast-view, downcast-control, semantic gain
-    /// e.g. `( Sequence ( Digit 16 ) ) ~> ( PositionalInteger 16 LittleEndian )`
-    Mono,
-
-    /// Epimorphsim, i.e. surjective functions,
-    /// upcast-control, downcast-view, possible loss of entropy
-    /// e.g. `( Ascii ) ~> ( Digit 16 )`
-    Epi,
-
-    /// Any other function
-    Any,
-}
-
-#[derive(Clone, Hash, PartialEq, Eq, Debug)]
-pub struct MorphismType {
-//    pub mode: MorphismMode,
-    pub src_type: Option<TypeTerm>,
-    pub dst_type: TypeTerm,
-}
-
-#[derive(Clone, Hash, Eq, PartialEq)]
-pub struct MorphismTypePattern {
-    pub src_tyid: Option<TypeID>,
-    pub dst_tyid: TypeID
-}
-
-impl MorphismType {
-    pub fn to_str(&self, ctx: &Context) -> String {
-        format!("{:?} -> {:?}",
-                if let Some(t) = self.src_type.as_ref() {
-                    ctx.type_term_to_str(t)
-                } else {
-                    "None".into()
-                },
-                ctx.type_term_to_str(&self.dst_type))
-    }
-}
-
-impl MorphismTypePattern {
-    pub fn to_str(&self, ctx: &Context) -> String {
-        format!("{:?} -> {:?}",
-                if let Some(t) = self.src_tyid.as_ref() {
-                    ctx.type_term_to_str(&TypeTerm::TypeID(t.clone()))
-                } else {
-                    "None".into()
-                },
-                ctx.type_term_to_str(&TypeTerm::TypeID(self.dst_tyid.clone())))
-    }
-}
-
-impl From<MorphismType> for MorphismTypePattern {    
-    fn from(value: MorphismType) -> MorphismTypePattern {
-        fn strip( x: &TypeTerm ) -> TypeID {
-            match x {
-                TypeTerm::TypeID(id) => id.clone(),
-                TypeTerm::App(args) => strip(&args[0]),
-                TypeTerm::Ladder(args) => strip(&args[0]),
-                    _ => unreachable!()
-            }
-        }
-
-        MorphismTypePattern {
-            src_tyid: value.src_type.map(|x| strip(&x)),
-            dst_tyid: strip(&value.dst_type)
-        }
-    }
-}
-
-//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
-
 #[derive(Clone)]
 pub struct Context {
     /// assigns a name to every type
     pub type_dict: Arc<RwLock<TypeDict>>,
 
+    pub morphisms: MorphismBase,
+
     /// named vertices of the graph
-    nodes: HashMap< String, NestedNode >,
+    nodes: HashMap< String, Arc<RwLock<ReprTree>> >,
 
     /// todo: beautify
     /// types that can be edited as lists
+    /// do we really need this?
     pub list_types: Vec< TypeID >,
     pub meta_chars: Vec< char >,
 
-    /// graph constructors
-    /// TODO: move into separate struct MorphismMap or something
-    morphisms: HashMap<
-                   MorphismTypePattern,
-                   Arc<
-                           dyn Fn( NestedNode, TypeTerm ) -> Option<NestedNode>
-                           + Send + Sync
-                   >
-               >,
-
     /// recursion
     parent: Option<Arc<RwLock<Context>>>,
 }
 
-impl Default for Context {
-    fn default() -> Context {
-        let mut ctx = Context::new();
-
-        ctx.add_list_typename("Sequence");
-        ctx.add_synonym("Seq", "Sequence");
-        ctx.add_list_typename("SepSeq");
-        ctx.add_typename("NestedNode");
-        ctx.add_typename("TerminalEvent");
-        
-        crate::editors::list::init_ctx( &mut ctx );
-        crate::editors::char::init_ctx( &mut ctx );
-        crate::editors::integer::init_ctx( &mut ctx );
-        crate::editors::typeterm::init_ctx( &mut ctx );
-
-        ctx
-    }
-}
-
 impl Context {
     pub fn with_parent(parent: Option<Arc<RwLock<Context>>>) -> Self {
         Context {
@@ -143,7 +40,7 @@ impl Context {
                 Some(p) => p.read().unwrap().type_dict.clone(),
                 None => Arc::new(RwLock::new(TypeDict::new()))
             },
-            morphisms: HashMap::new(),
+            morphisms: MorphismBase::new(),
             nodes: HashMap::new(),
             list_types: match parent.as_ref() {
                 Some(p) => p.read().unwrap().list_types.clone(),
@@ -240,105 +137,20 @@ impl Context {
     pub fn type_term_to_str(&self, t: &TypeTerm) -> String {
         self.type_dict.read().unwrap().unparse(&t)
     }
-
-    pub fn add_node_ctor(&mut self, tn: &str, mk_editor: Arc<dyn Fn(Arc<RwLock<Self>>, TypeTerm, OuterViewPort<dyn SingletonView<Item = usize>>) -> Option<NestedNode> + Send + Sync>) {
-        let dict = self.type_dict.clone();
-        let mut dict = dict.write().unwrap();
-
-        let tyid =
-            if let Some(tyid) = dict.get_typeid(&tn.into()) {
-                tyid
-            } else {
-                dict.add_typename(tn.into())
-            };
-
-        let morphism_pattern = MorphismTypePattern {
-            src_tyid: None,
-            dst_tyid: tyid
-        };
-
-        drop(dict);
-
-        self.add_morphism(morphism_pattern, Arc::new(move |node, dst_type| {
-            mk_editor(node.ctx.clone(), dst_type, node.disp.depth)
-        }));
-    }
-
-    pub fn add_morphism(
-        &mut self,
-        morph_type_pattern: MorphismTypePattern,
-        morph_fn: Arc<
-                     dyn Fn( NestedNode, TypeTerm ) -> Option<NestedNode>
-                     + Send + Sync
-                  >
-    ) {
-        self.morphisms.insert(morph_type_pattern, morph_fn);
-    }
-
-    pub fn get_morphism(&self, ty: MorphismType) -> Option<Arc<dyn Fn(NestedNode, TypeTerm) -> Option<NestedNode> + Send + Sync>> {
-        let pattern = MorphismTypePattern::from(ty.clone());
-
-        if let Some(morphism) = self.morphisms.get( &pattern ) {
-            Some(morphism.clone())
-        } else {
-            self.parent.as_ref()?
-                .read().unwrap()
-                .get_morphism(ty)
-        }
-    }
-
-    pub fn make_node(ctx: &Arc<RwLock<Self>>, type_term: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> Option<NestedNode> {
-        let mk_node = ctx.read().unwrap().get_morphism(MorphismType {
-            src_type: None,
-            dst_type: type_term.clone()
-        }).expect(&format!("morphism {}", ctx.read().unwrap().type_term_to_str(&type_term)));
-
-        /* create new context per node ?? too heavy.. whats the reason? TODO */
-
-        let new_ctx = Arc::new(RwLock::new(Context::with_parent(Some(ctx.clone()))));
-
-        mk_node(
-            NestedNode::new(new_ctx, ReprTree::new_arc(type_term.clone()), depth),
-            type_term
-        )
-    }
-
-    pub fn morph_node(mut node: NestedNode, dst_type: TypeTerm) -> NestedNode {
-        let src_type = node.data.read().unwrap().get_type().clone();
-        let pattern = MorphismType { src_type: Some(src_type), dst_type: dst_type.clone() };
-
-        /* it is not univesally true to always use ascend.
-         */
-        node.data =
-            ReprTree::ascend(
-                &node.data,
-                dst_type.clone()
-            );
-
-        let m = node.ctx.read().unwrap().get_morphism(pattern.clone());
-        if let Some(transform) = m {
-            if let Some(new_node) = transform(node.clone(), dst_type) {
-                new_node
-            } else {
-                node.clone()
-            }
-        } else {
-            node
-        }
-    }
-
     /// adds an object without any representations
     pub fn add_obj(ctx: Arc<RwLock<Context>>, name: String, typename: &str) {
         let type_tag = ctx.read().unwrap()
             .type_dict.write().unwrap()
             .parse(typename).unwrap();
 
+/*
         if let Some(node) = Context::make_node(&ctx, type_tag, SingletonBuffer::new(0).get_port()) {
             ctx.write().unwrap().nodes.insert(name, node);
         }
+*/
     }
 
-    pub fn get_obj(&self, name: &String) -> Option<NestedNode> {
+    pub fn get_obj(&self, name: &String) -> Option< Arc<RwLock<ReprTree>> > {
         if let Some(obj) = self.nodes.get(name) {
             Some(obj.clone())
         } else if let Some(parent) = self.parent.as_ref() {
@@ -347,85 +159,6 @@ impl Context {
             None
         }
     }
-
-/*
-    pub fn get_obj_port<'a, V: View + ?Sized + 'static>(
-        &self,
-        name: &str,
-        type_ladder: impl Iterator<Item = &'a str>,
-    ) -> Option<OuterViewPort<V>>
-    where
-        V::Msg: Clone,
-    {
-        self.get_obj(&name.into())?
-            .downcast_ladder(type_ladder.map(|tn| self.type_dict.type_term_from_str(tn).unwrap()))?
-            .get_port()
-    }
-
-    pub fn insert_repr<'a>(
-        &mut self,
-        name: &str,
-        type_ladder: impl Iterator<Item = &'a str>,
-        port: AnyOuterViewPort,
-    ) {
-        self.get_obj(&name.to_string())
-            .unwrap()
-            .repr
-            .write()
-            .unwrap()
-            .insert_leaf(
-                type_ladder.map(|tn| self.type_dict.type_term_from_str(tn).unwrap()),
-                port,
-            );
-    }
-
-    pub fn epi_cast(&mut self, name: &str, typename: &str) {
-        let dst_type = self.type_dict.type_term_from_str(typename).unwrap();
-        let old_obj = self.objects.get(&name.to_string()).unwrap().clone();
-        let new_obj = if let Some(ctor) = self.morphism_constructors.get(&MorphismType {
-            mode: MorphismMode::Epi,
-            src_type: old_obj.type_tag.clone(),
-            dst_type: dst_type.clone(),
-        }) {
-            ctor(old_obj.clone())
-        } else {
-            Arc::new(RwLock::new(ReprTree::new(dst_type)))
-        };
-
-        new_obj
-            .repr
-            .write()
-            .unwrap()
-            .insert_branch(old_obj.type_tag, old_obj.repr);
-
-        self.objects.insert(name.to_string(), new_obj);
-    }
-
-    pub fn mono_view<'a, V: View + ?Sized + 'static>(
-        &mut self,
-        name: &str,
-        type_ladder: impl Iterator<Item = &'a str>,
-    ) -> Option<OuterViewPort<V>>
-    where
-        V::Msg: Clone,
-    {
-        if let Some(p) = self.get_obj_port(name, type_ladder) {
-            Some(p)
-        } else {
-            // todo : add repr with morphism constructor (if one exists)
-            /*
-            if let Some(ctor) = self.morphism_constructors.get(
-                &MorphismType {
-                    mode: MorphismMode::Mono,
-                    src_type: old_obj.type_tag.clone(),
-                    dst_type:
-                }
-            )
-            */
-            None
-        }
-}
-    */
 }
 
 //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
diff --git a/lib-nested-core/src/repr_tree/mod.rs b/lib-nested-core/src/repr_tree/mod.rs
index 758fea3..dc6e7d9 100644
--- a/lib-nested-core/src/repr_tree/mod.rs
+++ b/lib-nested-core/src/repr_tree/mod.rs
@@ -1,7 +1,9 @@
 pub mod context;
+pub mod morphism;
 
 pub use {
-    context::{Context, MorphismMode, MorphismType, MorphismTypePattern},
+    context::{Context},
+    morphism::{MorphismType, GenericReprTreeMorphism, MorphismBase}
 };
 
 use {
@@ -16,7 +18,7 @@ use {
 //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
 
 #[derive(Clone)]
-pub struct ReprTree {
+pub struct ReprTree {    
     type_tag: TypeTerm,
     port: Option<AnyOuterViewPort>,
     branches: HashMap<TypeTerm, Arc<RwLock<ReprTree>>>,
@@ -97,6 +99,8 @@ impl ReprTree {
 
     //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
 
+    
+
     pub fn get_port<V: View + ?Sized + 'static>(&self) -> Option<OuterViewPort<V>>
     where
         V::Msg: Clone,
@@ -137,110 +141,5 @@ impl ReprTree {
         n.insert_branch(rt.clone());
         Arc::new(RwLock::new(n))
     }
-
-/*
-    pub fn add_iso_repr(
-        &self,
-        type_ladder: impl Iterator<Item = TypeTerm>,
-        morphism_constructors: &HashMap<MorphismType, Box<dyn Fn(Object) -> Object>>,
-    ) {
-        let mut cur_repr = self.repr.clone();
-
-        for dst_type in type_ladder {
-            if let Some(next_repr) = self.repr.read().unwrap().branches.get(&dst_type) {
-                // go deeper
-                cur_repr = next_repr.clone();
-            } else {
-                // search for morphism constructor and insert new repr
-                let mut obj = None;
-
-                for src_type in cur_repr.read().unwrap().branches.keys() {
-                    if let Some(ctor) = morphism_constructors.get(&MorphismType {
-                        mode: MorphismMode::Iso,
-                        src_type: src_type.clone(),
-                        dst_type: dst_type.clone(),
-                    }) {
-                        let new_obj = ctor(Object {
-                            type_tag: src_type.clone(),
-                            repr: cur_repr
-                                .read()
-                                .unwrap()
-                                .branches
-                                .get(&src_type)
-                                .unwrap()
-                                .clone(),
-                        });
-
-                        assert!(new_obj.type_tag == dst_type);
-
-                        obj = Some(new_obj);
-                        break;
-                    }
-                }
-
-                if let Some(obj) = obj {
-                    cur_repr
-                        .write()
-                        .unwrap()
-                        .insert_branch(obj.type_tag, obj.repr);
-                } else {
-                    panic!("could not find matching isomorphism!");
-                }
-            }
-        }
-    }
-
-    pub fn add_mono_repr<'a>(
-        &self,
-        type_ladder: impl Iterator<Item = TypeTerm>,
-        morphism_constructors: &HashMap<MorphismType, Box<dyn Fn(Object) -> Object>>,
-    ) {
-        let mut cur_type = self.type_tag.clone();
-        let mut cur_repr = self.repr.clone();   
-
-        for dst_type in type_ladder {
-            if let Some(next_repr) = self.repr.read().unwrap().branches.get(&dst_type) {
-                // go deeper
-                cur_type = dst_type;
-                cur_repr = next_repr.clone();
-            } else {
-                if let Some(constructor) = morphism_constructors.get(&MorphismType {
-                    mode: MorphismMode::Mono,
-                    src_type: cur_type.clone(),
-                    dst_type: dst_type.clone(),
-                }) {
-                    let new_obj = constructor(Object {
-                        type_tag: cur_type.clone(),
-                        repr: cur_repr
-                            .read()
-                            .unwrap()
-                            .branches
-                            .get(&cur_type)
-                            .unwrap()
-                            .clone(),
-                    });
-
-                    assert!(new_obj.type_tag == dst_type);
-                    cur_repr
-                        .write()
-                        .unwrap()
-                        .insert_branch(new_obj.type_tag.clone(), new_obj.repr.clone());
-
-                    cur_type = new_obj.type_tag;
-                    cur_repr = new_obj.repr;
-                }
-            }
-        }
-    }
-
-    // replace with higher-level type in which self is a repr branch
-    pub fn epi_cast<'a>(
-        &self,
-        _type_ladder: impl Iterator<Item = TypeTerm>,
-        _morphism_constructors: &HashMap<MorphismType, Box<dyn Fn(Object) -> Object>>,
-    ) {
-        // todo        
-}
-    */
 }
 
diff --git a/lib-nested-core/src/repr_tree/morphism.rs b/lib-nested-core/src/repr_tree/morphism.rs
new file mode 100644
index 0000000..cc08e05
--- /dev/null
+++ b/lib-nested-core/src/repr_tree/morphism.rs
@@ -0,0 +1,105 @@
+use {
+    laddertypes::{TypeTerm, TypeID},
+    crate::{
+        repr_tree::{ReprTree},
+    },
+    std::{
+        sync::{Arc, RwLock},
+        collections::HashMap
+    }
+};
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
+
+#[derive(Clone, Hash, PartialEq, Eq, Debug)]
+pub struct MorphismType {
+    pub src_type: TypeTerm,
+    pub dst_type: TypeTerm,
+}
+
+#[derive(Clone)]
+pub struct GenericReprTreeMorphism {
+    morph_type: MorphismType,
+    repr_tree_op: Arc<
+        dyn Fn( Arc<RwLock<ReprTree>>, &HashMap<TypeID, TypeTerm> )
+        + Send + Sync
+    >
+}
+
+#[derive(Clone)]
+pub struct MorphismBase {
+    morphisms: Vec< GenericReprTreeMorphism >
+}
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
+
+impl MorphismBase {
+    pub fn new() -> Self {
+        MorphismBase {
+            morphisms: Vec::new()
+        }
+    }
+
+    pub fn add_morphism(
+        &mut self,
+        morph_type: MorphismType,
+        repr_tree_op: impl Fn( Arc<RwLock<ReprTree>>, &HashMap<TypeID, TypeTerm> ) + Send + Sync
+    ) {
+        self.morphisms.push(
+            GenericReprTreeMorphism {
+                morph_type,
+                repr_tree_op: Arc::new(repr_tree_op)
+            }
+        );
+    }
+
+    pub fn find_morphism(
+        &self,
+        src_type: &TypeTerm,
+        dst_type: &TypeTerm
+    ) -> Option<(&GenericReprTreeMorphism, HashMap<TypeID, TypeTerm>)> {
+        for m in self.morphisms.iter() {
+
+            let unification_problem = laddertypes::UnificationProblem::new(
+                vec![
+                    ( src_type.clone(), m.morph_type.src_type.clone() ),
+                    ( dst_type.clone(), m.morph_type.dst_type.clone() )
+                ]
+            );
+
+            if let Ok(σ) = unification_problem.solve() {
+                eprintln!("found matching morphism");
+                return Some((m, σ));
+            }
+        }
+
+        None
+    }
+
+    pub fn morph(
+        &self,
+        repr_tree: Arc<RwLock<ReprTree>>,
+        target_type: &TypeTerm
+    ) {
+        if let Some((m, σ)) = self.find_morphism( repr_tree.read().unwrap().get_type(), target_type ) {
+            (m.repr_tree_op)( repr_tree, &σ );
+        } else {
+            eprintln!("could not find morphism");
+        }
+    }
+}
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
+/*
+impl MorphismType {
+    pub fn to_str(&self, ctx: &Context) -> String {
+        format!("{:?} -> {:?}",
+                if let Some(t) = self.src_type.as_ref() {
+                    ctx.type_dict.read().unwrap().unparse(t)
+                } else {
+                    "None".into()
+                },
+                ctx.type_dict.read().unwrap().unparse(&self.dst_type))
+    }
+}
+*/
diff --git a/lib-nested-tty/src/editors/mod.rs b/lib-nested-tty/src/editors/mod.rs
index dbaef38..dfc07ee 100644
--- a/lib-nested-tty/src/editors/mod.rs
+++ b/lib-nested-tty/src/editors/mod.rs
@@ -1,3 +1,84 @@
 
 pub mod list;
 
+use {
+    nested::{
+        edit_tree::{NestedNode},
+        repr_tree::{ReprTree, Context}
+    },
+    r3vi::{
+        view::{singleton::*, sequence::*},
+        projection::decorate_sequence::*
+    },
+    crate::{
+        make_label,
+        DisplaySegment,
+        atom::TerminalAtom
+    }
+};
+
+pub fn node_make_char_view(
+    node: NestedNode
+) -> NestedNode {
+    node.disp.view
+        .write().unwrap()
+        .insert_branch(ReprTree::new_leaf(
+            Context::parse(&node.ctx, "TerminalView"),
+            node.data
+                .read()
+                .unwrap()
+                .get_port::<dyn SingletonView<Item = char>>()
+                .expect("unable to get Char-view")
+                .map(move |c| TerminalAtom::from(if c == '\0' { ' ' } else { c }))
+                .to_grid()
+                .into(),
+        ));
+
+    node
+}
+
+pub fn node_make_seq_view(
+    mut node: NestedNode
+) -> NestedNode {
+    node.disp.view
+        .write().unwrap()
+        .insert_branch(ReprTree::new_leaf(
+            Context::parse(&node.ctx, "TerminalView"),
+            node.data
+                .read()
+                .unwrap()
+                .get_port::<dyn SequenceView<Item = NestedNode>>()
+                .expect("unable to get Seq-view")
+                .map(move |char_node| node_make_tty_view(char_node.clone()).display_view() )
+                .wrap(make_label("("), make_label(")"))
+                .to_grid_horizontal()
+                .flatten()
+                .into()
+        ));
+    node
+}
+
+pub fn node_make_list_edit(
+    mut node: NestedNode
+) -> NestedNode {
+    list::PTYListStyle::for_node( &mut node, ("(", "", ")") );
+    list::PTYListController::for_node( &mut node, None, None );
+
+    node
+}
+
+pub fn node_make_tty_view(
+    node: NestedNode
+) -> NestedNode {
+    if node.data.read().unwrap().get_type() == &Context::parse(&node.ctx, "Char") {
+        node_make_char_view( node )
+    } else if node.data.read().unwrap().get_type() == &Context::parse(&node.ctx, "<Seq Char>") {
+        node_make_seq_view( node )
+    } else if node.data.read().unwrap().get_type() == &Context::parse(&node.ctx, "<List Char>") {
+        node_make_list_edit( node )
+    } else {
+        eprintln!("couldnt add view");
+        node
+    }
+}
+