From b386fee6eb77352a35ea2775973360f598416a42 Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Fri, 25 Aug 2023 04:00:38 +0200
Subject: [PATCH] wip typterm edit; list editor: split using spill buf

---
 nested/src/editors/list/cmd.rs     |  10 +-
 nested/src/editors/list/editor.rs  | 130 ++++++++--------
 nested/src/editors/typeterm/mod.rs | 234 ++++++++++++++++++++++++-----
 nested/src/tree/node.rs            |  13 +-
 4 files changed, 268 insertions(+), 119 deletions(-)

diff --git a/nested/src/editors/list/cmd.rs b/nested/src/editors/list/cmd.rs
index e5fcb39..f74c753 100644
--- a/nested/src/editors/list/cmd.rs
+++ b/nested/src/editors/list/cmd.rs
@@ -35,7 +35,7 @@ impl ListCmd {
 impl ObjCommander for ListEditor {
     fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
         let cmd_repr = cmd_obj.read().unwrap();
-        
+
         if let Some(view) = cmd_repr.get_view::<dyn SingletonView<Item = NestedNode>>() {
             let node = view.get();
             let cur = self.cursor.get();
@@ -144,12 +144,8 @@ impl ObjCommander for ListEditor {
                                 TreeNavResult::Continue
                             }
                             ListCmd::Split => {
-/*
-                                self.split(self.spill_node);
-                                */
-                                self.listlist_split();
-
-                                TreeNavResult::Continue
+                                self.split();
+                                TreeNavResult::Exit
                             }
                             ListCmd::Clear => {
                                 self.clear();
diff --git a/nested/src/editors/list/editor.rs b/nested/src/editors/list/editor.rs
index 007955e..95c9287 100644
--- a/nested/src/editors/list/editor.rs
+++ b/nested/src/editors/list/editor.rs
@@ -1,23 +1,29 @@
 use {
     r3vi::{
-        view::{port::UpdateTask, OuterViewPort, singleton::*, sequence::*},
+        view::{ChannelSender, ChannelReceiver, port::UpdateTask, OuterViewPort, singleton::*, sequence::*},
         buffer::{singleton::*, vec::*}
     },
     crate::{
         type_system::{Context, TypeTerm, ReprTree},
-        editors::list::{ListCursor, ListCursorMode},
+        editors::list::{ListCursor, ListCursorMode, ListCmd},
         tree::{NestedNode, TreeNav, TreeCursor},
-        diagnostics::Diagnostics
+        diagnostics::Diagnostics,
+        commander::ObjCommander
     },
-    std::sync::{Arc, RwLock}
+    std::sync::{Arc, RwLock, Mutex},
+    std::ops::Deref
 };
 
 //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
 
 pub struct ListEditor {
     pub(super) cursor: SingletonBuffer<ListCursor>,
+
+    // todo: (?) remove RwLock<..> around NestedNode ??
     pub data: VecBuffer< Arc<RwLock<NestedNode>> >,
 
+    pub spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>,
+    
     pub(super) addr_port: OuterViewPort<dyn SequenceView<Item = isize>>,
     pub(super) mode_port: OuterViewPort<dyn SingletonView<Item = ListCursorMode>>,
 
@@ -33,7 +39,7 @@ impl ListEditor {
         typ: TypeTerm,
     ) -> Self {
         let cursor = SingletonBuffer::new(ListCursor::default());
-        let data = VecBuffer::<Arc<RwLock<NestedNode>>>::new();
+        let data : VecBuffer<Arc<RwLock<NestedNode>>> = VecBuffer::new();
 
         ListEditor {
             mode_port: cursor
@@ -83,8 +89,9 @@ impl ListEditor {
                 .flatten(),
             cursor,
             data,
+            spillbuf: Arc::new(RwLock::new(Vec::new())),
             ctx,
-            typ,
+            typ
         }
     }
 
@@ -95,7 +102,7 @@ impl ListEditor {
 
         let e = editor.read().unwrap();
 
-        NestedNode::new(ctx, data, depth)
+        let mut node = NestedNode::new(ctx, data, depth)
             .set_editor(editor.clone())
             .set_nav(editor.clone())
             .set_cmd(editor.clone())
@@ -117,7 +124,10 @@ impl ListEditor {
                           }
                       )
                       .flatten()
-            )
+            );
+
+        node.spillbuf = e.spillbuf.clone();
+        node
     }
 
     pub fn get_item_type(&self) -> TypeTerm {
@@ -235,26 +245,18 @@ impl ListEditor {
     }
 
     /// split the list off at the current cursor position and return the second half
-    pub fn split(&mut self, le_node: &mut NestedNode) {
+    pub fn split(&mut self) {        
         let cur = self.cursor.get();
         if let Some(idx) = cur.idx {
             let idx = idx as usize;
-            le_node.goto(TreeCursor::home());
             for _ in idx .. self.data.len() {
-
-                eprintln!("send items to new tail");
-                le_node.cmd.get().unwrap().write().unwrap().send_cmd_obj(
-                    self.data.get(idx).read().unwrap().data.clone()
-/*
-                    ReprTree::new_leaf(
-                        self.ctx.read().unwrap().type_term_from_str("( NestedNode )").unwrap(),
-                        SingletonBuffer::<NestedNode>::new( self.data.get(idx).clone().read().unwrap().clone() ).get_port().into()
-                    )
-*/
+                self.spillbuf.write().unwrap().push(
+                    self.data.get(idx)
                 );
                 self.data.remove(idx);
             }
-            le_node.goto(TreeCursor::none());
+
+            /* TODO
 
             if self.is_listlist() {
                 if idx > 0 && idx < self.data.len()+1 {
@@ -276,7 +278,8 @@ impl ListEditor {
                         }
                     }
                 }
-            }
+        }
+            */
         }
     }
 
@@ -317,53 +320,44 @@ impl ListEditor {
     pub fn listlist_split(&mut self) {
         let cur = self.get_cursor();
 
-        if let Some(item) = self.get_item() {
-//            let item = item.read().unwrap();
-            let _depth = item.depth;
-            
-            if let Some(head_editor) = item.editor.get() {
-                eprintln!("listlistsplit:editor = {:?}", Arc::into_raw(head_editor.clone()));
+        if let Some(mut item) = self.get_item().clone() {
+            item.send_cmd_obj(ListCmd::Split.into_repr_tree(&self.ctx));
 
-                let head = head_editor.downcast::<RwLock<ListEditor>>().unwrap();
-                let mut head = head.write().unwrap();
+            let mut tail_node = Context::make_node(&self.ctx, self.typ.clone(), 0).unwrap();
+            tail_node.goto(TreeCursor::home());
 
-                let mut tail_node = Context::make_node(&self.ctx, self.typ.clone(), 0).unwrap();
-
-                if head.data.len() > 0 {
-                    if cur.tree_addr.len() > 2 {
-                        eprintln!("call child head listlist split");
-                        head.listlist_split();
-                        eprintln!("return");
-                    }
-
-                    /*
-                    TODO: replace this by: (does not require  ListEditor downcast)
-                    head.send_cmd_obj(ListCmd::Split.into_repr());
-                    tail_node = head.spill_buf.clone();
-                     */
-
-                    head.split( &mut tail_node );
-                }
-
-                head.goto(TreeCursor::none());
-                drop(head);
-
-                tail_node.goto(
-                    TreeCursor {
-                        tree_addr: vec![0],
-                        leaf_mode: if cur.tree_addr.len() > 2 {
-                            ListCursorMode::Select
-                        } else {
-                            ListCursorMode::Insert
-                        }
-                    }
-                );
-                self.insert(
-                    Arc::new(RwLock::new(tail_node))
-                );
-
-                eprintln!("made insert");
+            let mut b = item.spillbuf.write().unwrap();
+            for node in b.iter() {
+                tail_node
+                    .send_cmd_obj(
+                        ReprTree::new_leaf(
+                            (&self.ctx, "( NestedNode )"),
+                            SingletonBuffer::<NestedNode>::new(
+                                node.read().unwrap().clone()
+                            ).get_port().into()
+                        )
+                    );
             }
+            b.clear();
+            drop(b);
+
+            item.goto(TreeCursor::none());
+            drop(item);
+
+            tail_node.goto(
+                TreeCursor {
+                    tree_addr: vec![0],
+                    leaf_mode: if cur.tree_addr.len() > 2 {
+                        ListCursorMode::Select
+                    } else {
+                        ListCursorMode::Insert
+                    }
+                }
+            );
+
+            self.insert(
+                Arc::new(RwLock::new(tail_node))
+            );
         }
     }
 
@@ -412,6 +406,7 @@ impl ListEditor {
         self.data.remove(next_idx);
     }
 }
+
 /*
 use crate::{
     type_system::TypeLadder,
@@ -432,4 +427,5 @@ impl TreeType for ListEditor {
         }
     }
 }
-*/
+ */
+
diff --git a/nested/src/editors/typeterm/mod.rs b/nested/src/editors/typeterm/mod.rs
index 9fb84fc..9a646f5 100644
--- a/nested/src/editors/typeterm/mod.rs
+++ b/nested/src/editors/typeterm/mod.rs
@@ -4,7 +4,7 @@ pub use ctx::init_ctx;
 
 use {
     r3vi::{
-        buffer::singleton::*,
+        buffer::{singleton::*, vec::*},
         view::{singleton::*, sequence::*, OuterViewPort}
     },
     crate::{
@@ -13,7 +13,7 @@ use {
         tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor},
         commander::ObjCommander
     },
-    std::{sync::{Arc, RwLock}, any::Any},
+    std::{sync::{Arc, RwLock, Mutex}, any::Any},
     cgmath::{Vector2}
 };
 
@@ -33,13 +33,9 @@ pub struct TypeTermEditor {
     ctx: Arc<RwLock<Context>>,
     data: Arc<RwLock<ReprTree>>,
 
-    // forward the editor to the node that references TypeTermEditor
-    // will be removed once the node includes a spill buffer using which joins can be implemented
-    editor: SingletonBuffer<
-                Option< Arc<dyn Any + Send + Sync> >
-            >,
-
+    // references to Node pointing to TypeTermEditor
     close_char: SingletonBuffer<Option<char>>,
+    spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>,
 
     state: State,
     cur_node: SingletonBuffer< NestedNode >
@@ -110,8 +106,6 @@ impl TypeTermEditor {
 
                 let int_edit = crate::editors::integer::PosIntEditor::from_u64(parent_ctx, 10, *n as u64);
                 let node = int_edit.into_node();
-
-                editor.write().unwrap().editor.set(node.editor.get());
                 editor.write().unwrap().cur_node.set(node);
                 editor.write().unwrap().state = State::Num;
             }
@@ -131,6 +125,8 @@ impl TypeTermEditor {
     }
     
     fn set_state(&mut self, new_state: State) {
+        eprintln!("TypeEdit: set state to {:?}", new_state);
+        
         let old_node = self.cur_node.get();
 
         let mut node = match new_state {
@@ -171,15 +167,15 @@ impl TypeTermEditor {
         node.goto(TreeCursor::home());
 
         let editor = node.editor.get();
-
-        self.editor.set(editor);
         self.close_char.set(node.close_char.get());
-
         self.cur_node.set(node);
         self.state = new_state;
     }
 
-    pub fn new_node(ctx: Arc<RwLock<Context>>, depth: usize) -> NestedNode {        
+    pub fn new_node(ctx: Arc<RwLock<Context>>, depth: usize) -> NestedNode {
+        let ctx : Arc<RwLock<Context>> = Arc::new(RwLock::new(Context::with_parent(Some(ctx))));
+        ctx.write().unwrap().meta_chars.push('~');
+
         let mut symb_node = Context::make_node( &ctx, (&ctx, "( List Char )").into(), 0 ).unwrap();
         symb_node = symb_node.morph( (&ctx, "( Type::Sym )").into() );
 
@@ -203,8 +199,9 @@ impl TypeTermEditor {
             state,
             data: data.clone(),
             cur_node: SingletonBuffer::new(node),
-            editor: SingletonBuffer::new(None),
-            close_char: SingletonBuffer::new(None)
+            //editor: SingletonBuffer::new(None),
+            close_char: SingletonBuffer::new(None),
+            spillbuf: Arc::new(RwLock::new(Vec::new()))
         };
 
         let view = editor.cur_node
@@ -224,11 +221,28 @@ impl TypeTermEditor {
             .set_editor(editor.clone());
 
         editor.write().unwrap().close_char = node.close_char.clone();
-        editor.write().unwrap().editor = node.editor.clone();
+        node.spillbuf = editor.read().unwrap().spillbuf.clone();
         
         node
     }
 
+    fn forward_spill(&mut self) {
+        eprintln!("forward spill");
+        let node = self.cur_node.get();
+        let mut buf = node.spillbuf.write().unwrap();
+        for n in buf.iter() {
+            self.spillbuf.write().unwrap().push(n.clone());
+        }
+        buf.clear();
+    }
+
+    fn send_child_cmd(&mut self, cmd: Arc<RwLock<ReprTree>>) -> TreeNavResult {
+        eprintln!("typterm forward cmd");
+        let res = self.cur_node.get_mut().send_cmd_obj( cmd );
+        self.forward_spill();
+        res
+    }
+    
     fn get_typeterm(&self) -> Option<TypeTerm> {
         match self.state {
             State::Any => None,
@@ -316,7 +330,7 @@ impl ObjCommander for TypeTermEditor {
                             }
                             '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' => {
                                 self.set_state( State::Num );
-                                self.cur_node.get_mut().send_cmd_obj( co );
+                                self.send_child_cmd( co );
                                 TreeNavResult::Continue
                             }
                             '\'' => {
@@ -329,11 +343,10 @@ impl ObjCommander for TypeTermEditor {
                             _ => {
                                 self.set_state( State::AnySymbol );
                                 self.cur_node.get_mut().goto(TreeCursor::home());
-                                self.cur_node.get_mut().send_cmd_obj( co )
+                                self.send_child_cmd( co )
                             }
                         }
                     }
-
                     State::Char => {
                         match c {
                             '\'' => {
@@ -341,37 +354,181 @@ impl ObjCommander for TypeTermEditor {
                                 TreeNavResult::Exit
                             }
                             _ => {
-                                self.cur_node.get_mut().send_cmd_obj( co )
+                                self.send_child_cmd( co )
                             }
                         }
                     }
 
-                    _ => {
-                        match self.cur_node.get_mut().send_cmd_obj( co ) {
+                    State::Ladder => {
+                        eprintln!("have LADDER, send cmd tochild");
+                        let res = self.send_child_cmd( co );
+                        let cur = self.get_cursor();
+                        
+                        match res {
+                            TreeNavResult::Continue => {
+                                if cur.tree_addr.len() == 3 {
+                                    match c {
+                                        '~' => {
+                                            let mut ladder_node = self.cur_node.get().clone();
+                                            let mut ladder_edit = ladder_node.get_edit::<ListEditor>().unwrap();
+
+                                            let item = ladder_edit.write().unwrap().get_item().clone();
+
+                                            if let Some(mut it_node) = item {
+                                                if it_node.get_type() == (&self.ctx, "( Type )").into() {
+                                                    let other_tt = it_node.get_edit::<TypeTermEditor>().unwrap();
+                                                    let other = other_tt.read().unwrap().cur_node.get().get_edit::<ListEditor>().unwrap();
+                                                    let buf = other.read().unwrap().data.clone();
+
+                                                    ladder_edit.write().unwrap().up();
+                                                    ladder_edit.write().unwrap().up();
+
+                                                    ladder_node.send_cmd_obj(
+                                                        ListCmd::DeleteNexd.into_repr_tree( &self.ctx )
+                                                    );
+                                                    //ladder_edit.write().unwrap().delete_nexd();
+
+                                                    let l = buf.len();
+                                                    for i in 0..l {
+                                                        ladder_edit.write().unwrap().insert( buf.get(i) );
+                                                    }
+                                                    ladder_node.dn();
+
+                                                    TreeNavResult::Continue
+                                                } else {
+                                                    TreeNavResult::Continue
+                                                }
+                                            } else {
+                                                TreeNavResult::Continue
+                                            }
+                                        }
+                                        _=> res
+                                    }
+                                } else {
+                                    TreeNavResult::Continue
+                                }
+                            }
+                            res => res,
+                        }
+                    }
+
+                    State::App => {
+                        let res = self.send_child_cmd( co );
+
+                        match res {
                             TreeNavResult::Exit => {
                                 match c {
                                     '~' => {
-                                        // todo:
-                                        
-                                        // in case previous item is not ladder
-                                        // create new intermediary ladder-node
-                                        // with the previous item as one step
+                                        // if item at cursor is Ladder
+                                        let app_edit = self.cur_node.get().get_edit::<ListEditor>().expect("editor");
+                                        let mut app_edit = app_edit.write().unwrap();
+                                        app_edit.delete_nexd();
+                                        app_edit.pxev();
 
-                                        // in case previous item is ladder
-                                        // goto end
+                                        if let Some(item_node) = app_edit.get_item() {
 
-                                        eprintln!("TypeEdit: child exit ~");
-                                    }
-                                    _ => {}
+                                            let item_typterm = item_node.get_edit::<TypeTermEditor>().expect("typetermedit");
+                                            let mut item_typterm = item_typterm.write().unwrap();
+                                            match item_typterm.state {
+                                                State::Ladder => {
+                                                    drop(item_typterm);
+
+                                                    app_edit.dn();
+                                                    app_edit.qnexd();
+                                                }
+                                                _ => {
+                                                    eprintln!("create new ladder");
+                                                    
+                                                    // else create enw ladder
+                                                    let mut new_node = Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), 0 ).unwrap();
+                                                    new_node = new_node.morph( (&self.ctx, "( Type::Ladder )").into() );
+                                                    // insert old node and split
+                                                    new_node.goto(TreeCursor::home());
+
+                                                    new_node.send_cmd_obj(
+                                                        ReprTree::new_leaf(
+                                                            (&self.ctx, "( NestedNode )"),
+                                                            SingletonBuffer::<NestedNode>::new( item_node ).get_port().into()
+                                                        )
+                                                    );
+
+                                                    drop(item_typterm);
+                                                    *app_edit.get_item_mut().unwrap().write().unwrap() = new_node;
+                                                    app_edit.dn();
+                                                }
+                                            }
+                                        }
+
+                                        TreeNavResult::Continue
+                                    },
+                                    _ => {TreeNavResult::Exit}
                                 }
+                            },
+                            res => res
+                        }
+                }
 
-                                TreeNavResult::Exit
+                    State::AnySymbol | State::FunSymbol | State::VarSymbol | State::App => {
+                        let res = self.send_child_cmd( co );
+                        match res {
+                            TreeNavResult::Exit => {
+                                match c {
+                                    '~' => {
+                                        eprintln!("typeterm: ~ ");
+
+                                        let old_node = self.cur_node.get().clone();
+
+                                        // create a new NestedNode with TerminaltypeEditor,
+                                        // that has same data as current node.
+                                        let mut old_edit_node = TypeTermEditor::new_node( self.ctx.clone(), 0 );
+                                        let mut old_edit_clone = old_edit_node.get_edit::<TypeTermEditor>().unwrap();
+                                        old_edit_clone.write().unwrap().set_state( self.state );
+                                        old_edit_clone.write().unwrap().close_char.set( old_node.close_char.get() );
+                                        old_edit_clone.write().unwrap().cur_node.set( old_node );
+
+                                        // create new list-edit node for the ladder
+                                        let mut new_node = Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), 0 ).unwrap();
+                                        new_node = new_node.morph( (&self.ctx, "( Type::Ladder )").into() );
+
+                                        eprintln!("insert old node into new node");
+                                        
+                                        // insert old node and split
+                                        new_node.goto(TreeCursor::home());
+                                        new_node.send_cmd_obj(
+                                            ReprTree::new_leaf(
+                                                (&self.ctx, "( NestedNode )"),
+                                                SingletonBuffer::new( old_edit_node ).get_port().into()
+                                            )
+                                        );
+
+                                        new_node.set_addr(0);
+                                        new_node.dn();
+
+                                        let res = new_node.send_cmd_obj(
+                                            ListCmd::Split.into_repr_tree( &self.ctx )
+                                        );
+
+                                        // reconfigure current node to display new_node
+                                        self.close_char.set(new_node.close_char.get());
+                                        self.cur_node.set(new_node);
+                                        self.state = State::Ladder;
+
+                                        TreeNavResult::Continue
+                                    }
+                                    _ => {
+                                        TreeNavResult::Exit
+                                    }
+                                }
                             }
                             TreeNavResult::Continue => {
                                 TreeNavResult::Continue
                             }
                         }
                     }
+
+                    _ => {
+                        self.send_child_cmd( co )
+                    }
                 }
             } else {
                 TreeNavResult::Exit
@@ -379,17 +536,14 @@ impl ObjCommander for TypeTermEditor {
         } else {
             match &self.state {
                 State::Any => {
-                    eprintln!("undefined comd object set to ladder");
-                    self.set_state( State::Ladder );
+                    self.set_state( State::AnySymbol );
                     self.cur_node.get_mut().goto(TreeCursor::home());
-                    let res = self.cur_node.get().cmd.get().unwrap().write().unwrap().send_cmd_obj( co );
-                    self.cur_node.get_mut().goto(TreeCursor::none());
-                    res
                 }
                 _ => {
-                    self.cur_node.get().cmd.get().unwrap().write().unwrap().send_cmd_obj( co )
                 }
             }
+
+            self.send_child_cmd( co )
         }
     }
 }
diff --git a/nested/src/tree/node.rs b/nested/src/tree/node.rs
index f4b3ca3..348b204 100644
--- a/nested/src/tree/node.rs
+++ b/nested/src/tree/node.rs
@@ -1,9 +1,9 @@
 use {
-    std::{sync::{Arc, RwLock}, any::Any},
+    std::{sync::{Arc, RwLock, Mutex}, any::Any},
     cgmath::{Vector2, Point2},
     r3vi::{
-        view::{View, ViewPort, OuterViewPort, AnyOuterViewPort, singleton::*, sequence::*},
-        buffer::{singleton::*}
+        view::{ChannelReceiver, View, ViewPort, OuterViewPort, AnyOuterViewPort, singleton::*, sequence::*},
+        buffer::{singleton::*, vec::*}
     },
     crate::{
         type_system::{ReprTree, Context, TypeTerm},
@@ -34,7 +34,8 @@ struct NestedNodeEdit {
                     Option< Arc<dyn Any + Send + Sync> >
 >,
 
-    pub spill_buf: VecBuffer< NestedNode >,
+    pub input_buf:: VecBuffer< NestedNode >,
+    pub output_buf: VecBuffer< NestedNode >,
 
     /// commander & navigation
     pub cmd: SingletonBuffer<
@@ -91,7 +92,8 @@ pub struct NestedNode {
     /* TODO:
      * - spill buffer (contains overflowing elements as well as 'split-off' parts)
      */
-    
+    pub spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>,
+
     /// commander & navigation
     pub cmd: SingletonBuffer<
                  Option< Arc<RwLock<dyn ObjCommander + Send + Sync>> >
@@ -113,6 +115,7 @@ impl NestedNode {
             diag: None,
             depth: SingletonBuffer::new(depth),
             editor: SingletonBuffer::new(None),
+            spillbuf: Arc::new(RwLock::new(Vec::new())),
             cmd: SingletonBuffer::new(None),
             close_char: SingletonBuffer::new(None),
             tree_nav: SingletonBuffer::new(None)