From a569fb46a8ea93acc04eb545a27aa7d4adfb511a Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Thu, 7 Sep 2023 18:04:34 +0200 Subject: [PATCH 01/10] char editor: display space when uninitialized --- nested/src/editors/char/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nested/src/editors/char/mod.rs b/nested/src/editors/char/mod.rs index 91dc3f4..6e5eb49 100644 --- a/nested/src/editors/char/mod.rs +++ b/nested/src/editors/char/mod.rs @@ -84,7 +84,7 @@ impl CharEditor { ) .set_view(data .get_port() - .map(move |c| TerminalAtom::from(c)) + .map(move |c| TerminalAtom::from(if c == '\0' { ' ' } else { c })) .to_grid() ) .set_cmd( editor.clone() ) From d8d282f9e993c0036e83f13908170541b7dc6f3e Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Thu, 7 Sep 2023 18:06:52 +0200 Subject: [PATCH 02/10] TypeTerm: add unit(), return index of first / last match in is_syntactic_subtype --- nested/src/type_system/term.rs | 78 +++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/nested/src/type_system/term.rs b/nested/src/type_system/term.rs index cb0cce4..12c1c15 100644 --- a/nested/src/type_system/term.rs +++ b/nested/src/type_system/term.rs @@ -33,6 +33,10 @@ pub enum TypeTerm { //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> impl TypeTerm { + pub fn unit() -> Self { + TypeTerm::Ladder(vec![]) + } + pub fn new(id: TypeID) -> Self { TypeTerm::TypeID(id) } @@ -130,6 +134,17 @@ impl TypeTerm { } } + pub fn get_lnf_vec(self) -> Vec<TypeTerm> { + match self.normalize() { + TypeTerm::Ladder( v ) => { + v + }, + _ => { + unreachable!(); + } + } + } + /// transmute self into Ladder-Normal-Form /// /// Example: @@ -194,48 +209,43 @@ impl TypeTerm { TypeTerm::Ladder( new_ladder ) } - /* - pub fn is_supertype_of(&self, t: &TypeTerm) -> bool { + pub fn is_semantic_supertype_of(&self, t: &TypeTerm) -> Option<( usize, TypeTerm )> { t.is_semantic_subtype_of(self) } - */ + + // returns ladder-step of first match and provided representation-type + pub fn is_semantic_subtype_of(&self, expected_type: &TypeTerm) -> Option<( usize, TypeTerm )> { + let provided_lnf = self.clone().get_lnf_vec(); + let expected_lnf = expected_type.clone().get_lnf_vec(); - // returns provided syntax-type, - pub fn is_semantic_subtype_of(&self, expected_type: &TypeTerm) -> Option< TypeTerm > { - let provided_lnf = self.clone(); - let expected_lnf = expected_type.clone(); - - match - (provided_lnf.normalize(), - expected_lnf.normalize()) - { - ( TypeTerm::Ladder( provided_ladder ), - TypeTerm::Ladder( expected_ladder ) - ) => { - - for i in 0..provided_ladder.len() { - if provided_ladder[i] == expected_ladder[0] { - return Some(TypeTerm::Ladder( - provided_ladder[i..].into_iter().cloned().collect() - )) - } - } - - None - }, - - _ => { - // both are in LNF! - unreachable!() + for i in 0..provided_lnf.len() { + if provided_lnf[i] == expected_lnf[0] { + return Some((i, TypeTerm::Ladder( + provided_lnf[i..].into_iter().cloned().collect() + ))) } } + + None } - pub fn is_syntactic_subtype_of(&self, expected_type: &TypeTerm) -> bool { - if let Some(provided_type) = self.is_semantic_subtype_of( expected_type ) { - &provided_type == expected_type + pub fn is_syntactic_subtype_of(&self, expected_type: &TypeTerm) -> Result<usize, Option<(usize, usize)>> { + if let Some((first_match, provided_type)) = self.is_semantic_subtype_of( expected_type ) { + let provided_lnf = self.clone().get_lnf_vec(); + let expected_lnf = expected_type.clone().get_lnf_vec(); + + let l = usize::min( provided_lnf.len(), expected_lnf.len() ); + + for i in 0..l { + + if provided_lnf[i] != expected_lnf[i] { + return Err(Some((first_match, i))) + } + } + + Ok(l-1) } else { - false + Err(None) } } From 62cc40c39cae578f089650af1eb881c4f1a6892b Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Thu, 7 Sep 2023 18:09:01 +0200 Subject: [PATCH 03/10] typeterm editor: avoid nested ladders through more clever event handling instead of dynamically refactoring editor-trees --- nested/src/editors/typeterm/cmd.rs | 35 ++++++++++++++------------- nested/src/editors/typeterm/mod.rs | 39 ------------------------------ 2 files changed, 18 insertions(+), 56 deletions(-) diff --git a/nested/src/editors/typeterm/cmd.rs b/nested/src/editors/typeterm/cmd.rs index f5b9aff..23271eb 100644 --- a/nested/src/editors/typeterm/cmd.rs +++ b/nested/src/editors/typeterm/cmd.rs @@ -4,7 +4,7 @@ use { }, crate::{ type_system::{ReprTree}, - editors::{list::{ListEditor, ListCmd}}, + editors::{list::{ListEditor, ListCmd, ListCursorMode}}, tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor}, commander::ObjCommander }, @@ -64,25 +64,26 @@ impl ObjCommander for TypeTermEditor { } State::Ladder => { - let res = self.send_child_cmd( co.clone() ); - - match res { - TreeNavResult::Continue => { - match c { - '~' => { - self.normalize_nested_ladder(); + if c == '~' { + let i0 = self.cur_node.get().get_edit::<ListEditor>().unwrap(); + + let cur_it = i0.clone().read().unwrap().get_item().clone(); + + if let Some(i) = cur_it { + let tte = i.get_edit::<TypeTermEditor>().unwrap(); + + if tte.read().unwrap().state != State::App { + drop(tte); + drop(i); + + return self.send_child_cmd( + ListCmd::Split.into_repr_tree( &self.ctx ) + ); } - _ => {} } - TreeNavResult::Continue - } - TreeNavResult::Exit => { - match c { - '~' => TreeNavResult::Continue, - _ => TreeNavResult::Exit - } - } } + + self.send_child_cmd( co.clone() ) } State::App => { diff --git a/nested/src/editors/typeterm/mod.rs b/nested/src/editors/typeterm/mod.rs index d018c81..259e20d 100644 --- a/nested/src/editors/typeterm/mod.rs +++ b/nested/src/editors/typeterm/mod.rs @@ -316,45 +316,6 @@ impl TypeTermEditor { self.cur_node.set(other_tt.cur_node.get()); self.state = other_tt.state; } - } else { - } - } - - /* flatten ladder of ladders into one ladder editor - */ - pub fn normalize_nested_ladder(&mut self) { - let mut subladder_list_node = self.cur_node.get().clone(); - let subladder_list_edit = subladder_list_node.get_edit::<ListEditor>().unwrap(); - - let item = subladder_list_edit.write().unwrap().get_item().clone(); - - if let Some(it_node) = item { - if it_node.get_type() == (&self.ctx, "( Type )").into() { - let other_tt = it_node.get_edit::<TypeTermEditor>().unwrap(); - - if other_tt.write().unwrap().state == State::Ladder { - let other = other_tt.read().unwrap().cur_node.get().get_edit::<ListEditor>().unwrap(); - let buf = other.read().unwrap().data.clone(); - - subladder_list_edit.write().unwrap().up(); - subladder_list_edit.write().unwrap().up(); - subladder_list_node.send_cmd_obj( - ListCmd::DeleteNexd.into_repr_tree( &self.ctx ) - ); - - if subladder_list_edit.read().unwrap().get_cursor_warp().tree_addr.len() > 0 { - if subladder_list_edit.read().unwrap().get_cursor_warp().tree_addr[0] == -1 { - subladder_list_edit.write().unwrap().delete_nexd(); - } - } - - let l = buf.len(); - for i in 0..l { - subladder_list_edit.write().unwrap().insert( buf.get(i) ); - } - subladder_list_node.dn(); - } - } } } From 6c80865229997bbd190baf156487278b960d5f51 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Fri, 8 Sep 2023 13:40:06 +0200 Subject: [PATCH 04/10] implement color by depth through viewport to account for dynamic change of tree structure --- nested/src/editors/char/mod.rs | 8 +-- nested/src/editors/integer/ctx.rs | 13 ++--- nested/src/editors/integer/editor.rs | 6 +-- nested/src/editors/list/ctx.rs | 3 +- nested/src/editors/list/editor.rs | 19 +++++-- nested/src/editors/list/pty_editor.rs | 30 ++++------- nested/src/editors/list/segment.rs | 14 ++--- nested/src/editors/product/editor.rs | 2 +- nested/src/editors/product/nav.rs | 4 +- nested/src/editors/sum/editor.rs | 2 +- nested/src/editors/typeterm/cmd.rs | 11 ++-- nested/src/editors/typeterm/ctx.rs | 21 ++++---- nested/src/editors/typeterm/mod.rs | 75 +++++++++++++++------------ nested/src/tree/node.rs | 11 ++-- nested/src/type_system/context.rs | 10 ++-- nested/src/utils/color.rs | 30 ++++++----- 16 files changed, 134 insertions(+), 125 deletions(-) diff --git a/nested/src/editors/char/mod.rs b/nested/src/editors/char/mod.rs index 6e5eb49..63b0c00 100644 --- a/nested/src/editors/char/mod.rs +++ b/nested/src/editors/char/mod.rs @@ -19,8 +19,8 @@ use { pub fn init_ctx( ctx: &mut Context ) { ctx.add_node_ctor( "Char", - Arc::new(|ctx: Arc<RwLock<Context>>, _ty: TypeTerm, _depth: usize| { - Some(CharEditor::new_node(ctx)) + Arc::new(|ctx: Arc<RwLock<Context>>, _ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| { + Some(CharEditor::new_node(ctx, depth)) })); } @@ -69,7 +69,7 @@ impl CharEditor { self.get_port().get_view().unwrap().get() } - pub fn new_node(ctx0: Arc<RwLock<Context>>) -> NestedNode { + pub fn new_node(ctx0: Arc<RwLock<Context>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode { let data = SingletonBuffer::new('\0'); let ctx = ctx0.clone(); let editor = Arc::new(RwLock::new(CharEditor{ ctx, data: data.clone() })); @@ -80,7 +80,7 @@ impl CharEditor { ctx0.read().unwrap().type_term_from_str("( Char )").unwrap(), data.get_port().into() ), - 0 // fixme + depth ) .set_view(data .get_port() diff --git a/nested/src/editors/integer/ctx.rs b/nested/src/editors/integer/ctx.rs index b683f3e..e9189c9 100644 --- a/nested/src/editors/integer/ctx.rs +++ b/nested/src/editors/integer/ctx.rs @@ -1,4 +1,8 @@ + use { + r3vi::{ + view::{OuterViewPort, singleton::*} + }, crate::{ type_system::{Context, TypeTerm}, editors::{ @@ -19,7 +23,7 @@ pub fn init_ctx(ctx: &mut Context) { ctx.add_node_ctor( "Digit", Arc::new( - |ctx: Arc<RwLock<Context>>, ty: TypeTerm, depth: usize| { + |ctx: Arc<RwLock<Context>>, ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| { match ty { TypeTerm::App(args) => { if args.len() > 1 { @@ -50,9 +54,6 @@ pub fn init_ctx(ctx: &mut Context) { ctx.add_morphism(pattern, Arc::new( |mut node, dst_type| { - let _depth = node.depth.get(); - let _editor = node.editor.get().unwrap().downcast::<RwLock<ListEditor>>().unwrap(); - // todo: check src_type parameter to be ( Digit radix ) match dst_type { @@ -87,7 +88,7 @@ pub fn init_ctx(ctx: &mut Context) { ctx.add_node_ctor( "PosInt", Arc::new( - |ctx0: Arc<RwLock<Context>>, dst_typ: TypeTerm, depth: usize| { + |ctx0: Arc<RwLock<Context>>, dst_typ: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| { match dst_typ.clone() { TypeTerm::App(args) => { if args.len() > 1 { @@ -105,7 +106,7 @@ pub fn init_ctx(ctx: &mut Context) { .clone() .into() ]), - depth+1 + depth.map(|d| d+1) ).unwrap(); node = node.morph(dst_typ); diff --git a/nested/src/editors/integer/editor.rs b/nested/src/editors/integer/editor.rs index b2fe84a..8c6c393 100644 --- a/nested/src/editors/integer/editor.rs +++ b/nested/src/editors/integer/editor.rs @@ -84,7 +84,7 @@ impl DigitEditor { } } - pub fn into_node(self, depth: usize) -> NestedNode { + pub fn into_node(self, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode { let data = self.get_data(); let editor = Arc::new(RwLock::new(self)); let ed = editor.write().unwrap(); @@ -99,7 +99,7 @@ impl DigitEditor { TerminalAtom::new( c.unwrap_or('?'), if c.unwrap_or('?').to_digit(r).is_some() { - TerminalStyle::fg_color((100, 140, 100)) + TerminalStyle::fg_color((90, 160, 90)) } else { //TerminalStyle::bg_color((90, 10, 10)) TerminalStyle::fg_color((200, 40, 40)) @@ -146,7 +146,7 @@ impl PosIntEditor { let mut node = Context::make_node( &ctx, (&ctx, format!("( List ( Digit {} ) )", radix).as_str()).into(), - 0 + r3vi::buffer::singleton::SingletonBuffer::new(0).get_port() ).unwrap(); // Set Type diff --git a/nested/src/editors/list/ctx.rs b/nested/src/editors/list/ctx.rs index d42f9c2..f6eb5df 100644 --- a/nested/src/editors/list/ctx.rs +++ b/nested/src/editors/list/ctx.rs @@ -1,4 +1,5 @@ use { + r3vi::{view::{OuterViewPort, singleton::*}}, crate::{ type_system::{Context, TypeTerm}, editors::list::{ListEditor, PTYListController, PTYListStyle} @@ -14,7 +15,7 @@ pub fn init_ctx(ctx: &mut Context) { ctx.add_node_ctor( "List", Arc::new( - |ctx: Arc<RwLock<Context>>, ty: TypeTerm, depth: usize| { + |ctx: Arc<RwLock<Context>>, ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| { match ty { TypeTerm::App(args) => { if args.len() > 1 { diff --git a/nested/src/editors/list/editor.rs b/nested/src/editors/list/editor.rs index d234cb3..9b81408 100644 --- a/nested/src/editors/list/editor.rs +++ b/nested/src/editors/list/editor.rs @@ -1,6 +1,6 @@ use { r3vi::{ - view::{OuterViewPort, singleton::*, sequence::*}, + view::{ViewPort, OuterViewPort, singleton::*, sequence::*}, buffer::{singleton::*, vec::*} }, crate::{ @@ -22,10 +22,12 @@ pub struct ListEditor { 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>>, + depth: OuterViewPort<dyn SingletonView<Item = usize>>, + pub(crate) ctx: Arc<RwLock<Context>>, /// item type @@ -95,13 +97,16 @@ impl ListEditor { data, spillbuf: Arc::new(RwLock::new(Vec::new())), ctx, - typ + typ, + depth: SingletonBuffer::new(0).get_port() } } - pub fn into_node(self, depth: usize) -> NestedNode { + pub fn into_node(mut self, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode { let data = self.get_data(); let ctx = self.ctx.clone(); + + self.depth = depth.clone(); let editor = Arc::new(RwLock::new(self)); let e = editor.read().unwrap(); @@ -231,6 +236,10 @@ impl ListEditor { if let Some(idx) = cur.idx { match cur.mode { ListCursorMode::Insert => { + item.read().unwrap().depth.0.set_view( + self.depth.map(|d| d+1).get_view() + ); + self.data.insert(idx as usize, item.clone()); if self.is_listlist() { cur.mode = ListCursorMode::Select; @@ -280,7 +289,7 @@ impl ListEditor { self.nexd(); let mut b = item.spillbuf.write().unwrap(); - let mut tail_node = Context::make_node(&self.ctx, self.typ.clone(), item.depth.get()).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()); for node in b.iter() { diff --git a/nested/src/editors/list/pty_editor.rs b/nested/src/editors/list/pty_editor.rs index bc5dc8a..e14a642 100644 --- a/nested/src/editors/list/pty_editor.rs +++ b/nested/src/editors/list/pty_editor.rs @@ -1,6 +1,6 @@ use { r3vi::{ - view::{OuterViewPort, sequence::*}, + view::{ViewPort, OuterViewPort, sequence::*}, projection::decorate_sequence::*, }, crate::{ @@ -18,23 +18,20 @@ use { //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> pub struct PTYListStyle { - style: (String, String, String), - depth: usize + style: (String, String, String) } impl PTYListStyle { - pub fn new(style: (&str, &str, &str), depth: usize) -> PTYListStyle { + pub fn new(style: (&str, &str, &str)) -> PTYListStyle { PTYListStyle { - style: (style.0.into(), style.1.into(), style.2.into()), - depth + style: (style.0.into(), style.1.into(), style.2.into()) } } pub fn get_seg_seq_view(&self, editor: &ListEditor) -> OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>> { let seg_seq = ListSegmentSequence::new( editor.get_cursor_port(), - editor.get_data_port(), - self.depth + editor.get_data_port() ); let se = seg_seq.read().unwrap(); se.get_view().map(move |segment| segment.pty_view()) @@ -43,8 +40,7 @@ impl PTYListStyle { pub fn pty_view(&self, editor: &ListEditor) -> OuterViewPort<dyn TerminalView> { let seg_seq = ListSegmentSequence::new( editor.get_cursor_port(), - editor.get_data_port(), - self.depth + editor.get_data_port() ); let seg_seq = seg_seq.read().unwrap(); @@ -59,7 +55,7 @@ impl PTYListStyle { pub fn for_node(node: &mut NestedNode, style: (&str, &str, &str)) { node.view = Some( - Self::new(style, node.depth.get()) + Self::new(style) .pty_view( &node.get_edit::<ListEditor>().unwrap().read().unwrap() ) @@ -75,7 +71,7 @@ pub struct PTYListController { split_char: Option<char>, close_char: Option<char>, - depth: usize + depth: OuterViewPort<dyn SingletonView<Item = usize>> } //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> @@ -85,7 +81,7 @@ impl PTYListController { editor: Arc<RwLock<ListEditor>>, split_char: Option<char>, close_char: Option<char>, - depth: usize + depth: OuterViewPort<dyn SingletonView<Item = usize>> ) -> Self { PTYListController { editor, @@ -113,7 +109,7 @@ impl PTYListController { } let editor = node.get_edit::<ListEditor>().unwrap(); - let controller = Arc::new(RwLock::new(PTYListController::from_editor( editor, split_char, close_char, node.depth.get() ))); + let controller = Arc::new(RwLock::new(PTYListController::from_editor( editor, split_char, close_char, node.depth.clone() ))); node.cmd.set(Some(controller.clone())); node.close_char.set(close_char); @@ -131,10 +127,6 @@ impl PTYListController { self.editor.read().unwrap().get_item() } - pub fn set_depth(&mut self, depth: usize) { - self.depth = depth; - } - pub fn handle_term_event(&mut self, event: &TerminalEvent, _cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult { let mut e = self.editor.write().unwrap(); match event { @@ -176,7 +168,7 @@ impl PTYListController { match cur.mode { ListCursorMode::Insert => { - let mut new_edit = Context::make_node(&e.ctx, e.typ.clone(), self.depth+1).unwrap(); + let mut new_edit = Context::make_node(&e.ctx, e.typ.clone(), self.depth.map(|d| d+1)).unwrap(); new_edit.goto(TreeCursor::home()); match new_edit.send_cmd_obj(cmd_obj.clone()) { diff --git a/nested/src/editors/list/segment.rs b/nested/src/editors/list/segment.rs index aba00c0..4ae0368 100644 --- a/nested/src/editors/list/segment.rs +++ b/nested/src/editors/list/segment.rs @@ -22,7 +22,6 @@ pub enum ListSegment { InsertCursor, Item { editor: NestedNode, - depth: usize, cur_dist: isize, } } @@ -37,9 +36,8 @@ impl PtySegment for ListSegment { .add_style_front(TerminalStyle::bold(true)) }) } - ListSegment::Item{ editor, depth, cur_dist } => { + ListSegment::Item{ editor, cur_dist } => { let e = editor.clone(); - let d = *depth; let cur_dist = *cur_dist; editor.get_view().map_item(move |_pt, atom| { let c = e.get_cursor(); @@ -50,10 +48,11 @@ impl PtySegment for ListSegment { } else { usize::MAX }; + atom .add_style_back(bg_style_from_depth(select)) .add_style_back(TerminalStyle::bold(select==1)) - .add_style_back(fg_style_from_depth(d)) + .add_style_back(fg_style_from_depth(e.depth.get_view().get())) }) } } @@ -64,7 +63,6 @@ pub struct ListSegmentSequence { data: Arc<dyn SequenceView<Item = NestedNode>>, cursor: Arc<dyn SingletonView<Item = ListCursor>>, - depth: usize, cur_cursor: ListCursor, port: ViewPort<dyn SequenceView<Item = ListSegment>>, @@ -95,7 +93,6 @@ impl SequenceView for ListSegmentSequence { ListCursorMode::Select => { ListSegment::Item { editor: self.data.get(idx)?, - depth: self.depth, cur_dist: cur - *idx as isize } } @@ -103,7 +100,6 @@ impl SequenceView for ListSegmentSequence { if *idx < cur as usize { ListSegment::Item { editor: self.data.get(idx)?, - depth: self.depth, cur_dist: cur - *idx as isize } } else if *idx == cur as usize { @@ -111,7 +107,6 @@ impl SequenceView for ListSegmentSequence { } else { ListSegment::Item { editor: self.data.get(&(*idx - 1))?, - depth: self.depth, cur_dist: cur - *idx as isize } } @@ -120,7 +115,6 @@ impl SequenceView for ListSegmentSequence { } else { ListSegment::Item { editor: self.data.get(&idx)?, - depth: self.depth, cur_dist: *idx as isize + 1 } }) @@ -131,14 +125,12 @@ impl ListSegmentSequence { pub fn new( cursor_port: OuterViewPort<dyn SingletonView<Item = ListCursor>>, data_port: OuterViewPort<dyn SequenceView<Item = NestedNode>>, - depth: usize ) -> Arc<RwLock<Self>> { let out_port = ViewPort::new(); let mut proj_helper = ProjectionHelper::new(out_port.update_hooks.clone()); let proj = Arc::new(RwLock::new(ListSegmentSequence { cur_cursor: cursor_port.get_view().get(), port: out_port.clone(), - depth, cursor: proj_helper.new_singleton_arg(0, cursor_port, |s: &mut Self, _msg| { let _old_cursor = s.cur_cursor; diff --git a/nested/src/editors/product/editor.rs b/nested/src/editors/product/editor.rs index 790a38d..97967d1 100644 --- a/nested/src/editors/product/editor.rs +++ b/nested/src/editors/product/editor.rs @@ -238,7 +238,7 @@ impl ObjCommander for ProductEditor { } } } else { - let mut e = Context::make_node(&self.ctx, t.clone(), *ed_depth+1).unwrap(); + let mut e = Context::make_node(&self.ctx, t.clone(), r3vi::buffer::singleton::SingletonBuffer::new(*ed_depth).get_port()).unwrap(); *editor = Some(e.clone()); update_segment = true; diff --git a/nested/src/editors/product/nav.rs b/nested/src/editors/product/nav.rs index c339c97..e681111 100644 --- a/nested/src/editors/product/nav.rs +++ b/nested/src/editors/product/nav.rs @@ -71,7 +71,7 @@ impl TreeNav for ProductEditor { e.goto(c.clone()); } else if c.tree_addr.len() > 0 { // create editor - let mut e = Context::make_node(&self.ctx, t.clone(), *ed_depth+1).unwrap(); + let mut e = Context::make_node(&self.ctx, t.clone(), r3vi::buffer::singleton::SingletonBuffer::new(*ed_depth+1).get_port()).unwrap(); *editor = Some(e.clone()); e.goto(c.clone()); } @@ -128,7 +128,7 @@ impl TreeNav for ProductEditor { } else { // create editor - let mut e = Context::make_node(&self.ctx, t.clone(), *ed_depth+1).unwrap(); + let mut e = Context::make_node(&self.ctx, t.clone(), r3vi::buffer::singleton::SingletonBuffer::new(*ed_depth+1).get_port()).unwrap(); *editor = Some(e.clone()); e.goby(direction); } diff --git a/nested/src/editors/sum/editor.rs b/nested/src/editors/sum/editor.rs index 24c587e..dc0c81e 100644 --- a/nested/src/editors/sum/editor.rs +++ b/nested/src/editors/sum/editor.rs @@ -60,7 +60,7 @@ impl SumEditor { NestedNode::new( ctx.clone(), ReprTree::new_arc(TypeTerm::TypeID(ctx.read().unwrap().get_typeid("Sum").unwrap())), - 0 + r3vi::buffer::singleton::SingletonBuffer::new(0).get_port() ) .set_view(view) .set_editor(editor.clone()) diff --git a/nested/src/editors/typeterm/cmd.rs b/nested/src/editors/typeterm/cmd.rs index 23271eb..56f93d8 100644 --- a/nested/src/editors/typeterm/cmd.rs +++ b/nested/src/editors/typeterm/cmd.rs @@ -44,7 +44,7 @@ impl ObjCommander for TypeTermEditor { TreeNavResult::Exit } _ => { - self.set_state( State::AnySymbol ); + self.set_state( State::FunSymbol ); self.cur_node.get_mut().goto(TreeCursor::home()); self.send_child_cmd( co ) } @@ -67,9 +67,9 @@ impl ObjCommander for TypeTermEditor { if c == '~' { let i0 = self.cur_node.get().get_edit::<ListEditor>().unwrap(); - let cur_it = i0.clone().read().unwrap().get_item().clone(); - - if let Some(i) = cur_it { + if self.get_cursor().tree_addr.len() > 1 { + let cur_it = i0.clone().read().unwrap().get_item().clone(); + if let Some(i) = cur_it { let tte = i.get_edit::<TypeTermEditor>().unwrap(); if tte.read().unwrap().state != State::App { @@ -81,6 +81,9 @@ impl ObjCommander for TypeTermEditor { ); } } + } else { + return TreeNavResult::Continue; + } } self.send_child_cmd( co.clone() ) diff --git a/nested/src/editors/typeterm/ctx.rs b/nested/src/editors/typeterm/ctx.rs index 8036e72..6ee0dbd 100644 --- a/nested/src/editors/typeterm/ctx.rs +++ b/nested/src/editors/typeterm/ctx.rs @@ -1,8 +1,15 @@ use { + r3vi::{ + view::{OuterViewPort, singleton::*} + }, crate::{ type_system::{Context, TypeTerm, MorphismTypePattern}, terminal::{TerminalStyle, TerminalProjections}, - editors::{list::{PTYListStyle, PTYListController}, typeterm::{State, TypeTermEditor}} + editors::{ + list::{PTYListStyle, PTYListController, ListEditor, ListSegmentSequence}, + typeterm::{State, TypeTermEditor} + }, + PtySegment }, std::{sync::{Arc, RwLock}}, cgmath::{Point2} @@ -25,7 +32,7 @@ pub fn init_ctx(ctx: &mut Context) { let ctx : Arc<RwLock<Context>> = Arc::new(RwLock::new(Context::with_parent(Some(node.ctx.clone())))); ctx.write().unwrap().meta_chars.push('~'); - let new_node = TypeTermEditor::with_node( ctx, node.depth.get(), node.clone(), State::Any ); + let new_node = TypeTermEditor::with_node( ctx, node.clone(), State::Any ); Some(new_node) })); @@ -38,7 +45,7 @@ pub fn init_ctx(ctx: &mut Context) { if vertical_view { let editor = node.get_edit::<crate::editors::list::ListEditor>().unwrap(); let mut e = editor.write().unwrap(); - let seg_view = PTYListStyle::new( ("","~",""), node.depth.get() ).get_seg_seq_view( &mut e ); + let seg_view = PTYListStyle::new( ("","~","") ).get_seg_seq_view( &mut e ); node = node.set_view( seg_view.to_grid_vertical().flatten() @@ -71,6 +78,7 @@ pub fn init_ctx(ctx: &mut Context) { Arc::new(|mut node, _dst_type:_| { PTYListController::for_node( &mut node, Some(' '), None ); PTYListStyle::for_node( &mut node, ("","","") ); + Some(node) })); @@ -80,11 +88,6 @@ pub fn init_ctx(ctx: &mut Context) { PTYListController::for_node( &mut node, Some(' '), None ); PTYListStyle::for_node( &mut node, ("","","") ); - // display variables blue color - if let Some(v) = node.view { - node.view = Some( - v.map_item(|_i,p| p.add_style_front(TerminalStyle::fg_color((5, 120, 240))))); - } Some(node) })); @@ -117,7 +120,7 @@ pub fn init_ctx(ctx: &mut Context) { })); ctx.add_node_ctor("Type", Arc::new( - |ctx: Arc<RwLock<Context>>, _ty: TypeTerm, depth: usize| { + |ctx: Arc<RwLock<Context>>, _ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| { Some(TypeTermEditor::new_node(ctx, depth)) })); } diff --git a/nested/src/editors/typeterm/mod.rs b/nested/src/editors/typeterm/mod.rs index 259e20d..15f7e99 100644 --- a/nested/src/editors/typeterm/mod.rs +++ b/nested/src/editors/typeterm/mod.rs @@ -6,6 +6,7 @@ pub use ctx::init_ctx; use { r3vi::{ + view::{OuterViewPort, singleton::*}, buffer::{singleton::*} }, crate::{ @@ -36,9 +37,10 @@ pub struct TypeTermEditor { data: Arc<RwLock<ReprTree>>, close_char: SingletonBuffer<Option<char>>, spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>, + depth: OuterViewPort<dyn SingletonView<Item = usize>>, - depth: usize, - + buf: SingletonBuffer< TypeTerm >, + // editing/parsing state state: State, @@ -47,8 +49,8 @@ pub struct TypeTermEditor { } impl TypeTermEditor { - pub fn from_type_term(ctx: Arc<RwLock<Context>>, depth: usize, term: &TypeTerm) -> NestedNode { - let mut node = TypeTermEditor::new_node(ctx.clone(), depth); + pub fn from_type_term(ctx: Arc<RwLock<Context>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>, term: &TypeTerm) -> NestedNode { + let mut node = TypeTermEditor::new_node(ctx.clone(), depth.clone()); node.goto(TreeCursor::home()); match term { @@ -74,7 +76,7 @@ impl TypeTermEditor { let parent_ctx = editor.read().unwrap().cur_node.get().ctx.clone(); for x in args.iter() { - let arg_node = TypeTermEditor::from_type_term( parent_ctx.clone(), depth+1, x ); + let arg_node = TypeTermEditor::from_type_term( parent_ctx.clone(), depth.map(|d| d+1), x ); node.send_cmd_obj( ReprTree::new_leaf( @@ -92,7 +94,7 @@ impl TypeTermEditor { let parent_ctx = editor.read().unwrap().cur_node.get().ctx.clone(); for x in args.iter() { - let arg_node = TypeTermEditor::from_type_term( parent_ctx.clone(), depth+1, x ); + let arg_node = TypeTermEditor::from_type_term( parent_ctx.clone(), depth.map(|d| d+1), x ); node.send_cmd_obj( ReprTree::new_leaf( @@ -130,28 +132,27 @@ impl TypeTermEditor { fn set_state(&mut self, new_state: State) { let mut node = match new_state { State::Any => { - Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth ).unwrap() + Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth.map(|x| x) ).unwrap() .morph( (&self.ctx, "( Type::Sym )").into() ) - } State::App => { - Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth ).unwrap() + Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth.map(|x| x) ).unwrap() .morph( (&self.ctx, "( Type::App )").into() ) } State::Ladder => { - Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth ).unwrap() + Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth.map(|x| x) ).unwrap() .morph( (&self.ctx, "( Type::Ladder )").into() ) } State::AnySymbol => { - Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth ).unwrap() + Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth.map(|x| x) ).unwrap() .morph( (&self.ctx, "( Type::Sym )").into() ) }, State::FunSymbol => { - Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth ).unwrap() + Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth.map(|x| x) ).unwrap() .morph( (&self.ctx, "( Type::Sym::Fun )").into() ) }, State::VarSymbol => { - Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth ).unwrap() + Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth.map(|x| x) ).unwrap() .morph( (&self.ctx, "( Type::Sym::Var )").into() ) } State::Num => { @@ -160,7 +161,7 @@ impl TypeTermEditor { .morph( (&self.ctx, "( Type::Lit::Num )").into() ) } State::Char => { - Context::make_node( &self.ctx, (&self.ctx, "( Char )").into(), self.depth ).unwrap() + Context::make_node( &self.ctx, (&self.ctx, "( Char )").into(), self.depth.map(|x| x) ).unwrap() .morph( (&self.ctx, "( Type::Lit::Char )").into() ) } }; @@ -173,7 +174,7 @@ impl TypeTermEditor { self.state = new_state; } - pub fn new_node(ctx: Arc<RwLock<Context>>, depth: usize) -> NestedNode { + pub fn new_node(ctx: Arc<RwLock<Context>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode { let ctx : Arc<RwLock<Context>> = Arc::new(RwLock::new(Context::with_parent(Some(ctx)))); ctx.write().unwrap().meta_chars.push('~'); @@ -182,14 +183,13 @@ impl TypeTermEditor { Self::with_node( ctx.clone(), - depth, symb_node, State::Any ) } - fn with_node(ctx: Arc<RwLock<Context>>, depth: usize, node: NestedNode, state: State) -> NestedNode { - let _buffer = SingletonBuffer::<Option<TypeTerm>>::new( None ); + fn with_node(ctx: Arc<RwLock<Context>>, cur_node: NestedNode, state: State) -> NestedNode { + let buf = SingletonBuffer::<TypeTerm>::new( TypeTerm::unit() ); let data = Arc::new(RwLock::new(ReprTree::new( (&ctx, "( Type )") @@ -199,10 +199,11 @@ impl TypeTermEditor { ctx: ctx.clone(), data: data.clone(), state, - cur_node: SingletonBuffer::new(node), + buf, + cur_node: SingletonBuffer::new(cur_node.clone()), close_char: SingletonBuffer::new(None), spillbuf: Arc::new(RwLock::new(Vec::new())), - depth + depth: cur_node.depth.clone() }; let view = editor.cur_node @@ -215,16 +216,16 @@ impl TypeTermEditor { let _cc = editor.cur_node.get().close_char; let editor = Arc::new(RwLock::new(editor)); - let mut node = NestedNode::new(ctx, data, depth) + let mut super_node = NestedNode::new(ctx, data, cur_node.depth) .set_view(view) .set_nav(editor.clone()) .set_cmd(editor.clone()) .set_editor(editor.clone()); - editor.write().unwrap().close_char = node.close_char.clone(); - node.spillbuf = editor.read().unwrap().spillbuf.clone(); - - node + editor.write().unwrap().close_char = super_node.close_char.clone(); + super_node.spillbuf = editor.read().unwrap().spillbuf.clone(); + + super_node } fn forward_spill(&mut self) { @@ -288,16 +289,17 @@ impl TypeTermEditor { let subladder_list_edit = subladder_list_edit.read().unwrap(); if subladder_list_edit.data.len() == 0 { - self.set_state( State::Any ); } } - /* unwrap a ladder if it only contains one element */ pub fn normalize_singleton(&mut self) { eprintln!("normalize singleton"); + + if self.state == State::Ladder{ + let subladder_list_node = self.cur_node.get().clone(); let subladder_list_edit = subladder_list_node.get_edit::<ListEditor>().unwrap(); @@ -312,11 +314,15 @@ impl TypeTermEditor { other_tt.normalize_singleton(); + other_tt.depth.0.set_view( self.depth.map(|x| x).get_view() ); + self.close_char.set(other_tt.close_char.get()); self.cur_node.set(other_tt.cur_node.get()); self.state = other_tt.state; } } + + } } /* in insert mode, morph the previous element into a ladder and continue there @@ -352,14 +358,13 @@ impl TypeTermEditor { _ => { item_typterm.goto(TreeCursor::none()); drop(item_typterm); - + // else create new ladder - let mut list_node = Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth ).unwrap(); + let mut list_node = Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth.map(|d| d+1) ).unwrap(); list_node = list_node.morph( (&self.ctx, "( Type::Ladder )").into() ); let mut new_node = TypeTermEditor::with_node( self.ctx.clone(), - self.depth, list_node, State::Ladder ); @@ -382,18 +387,20 @@ impl TypeTermEditor { } } + // TODO: morph_to_app() / morph_to_list(state) + /* replace with new ladder node with self as first element */ pub fn morph_to_ladder(&mut self) { eprintln!("morph into ladder"); + let old_node = self.cur_node.get().clone(); - *old_node.depth.get_mut() += 1; - /* create a new NestedNode with TerminaltypeEditor, * that has same state & child-node as current node. */ - let old_edit_node = TypeTermEditor::new_node( self.ctx.clone(), self.depth ); + let old_edit_node = TypeTermEditor::new_node( self.ctx.clone(), self.depth.map(|d| d + 1)); + old_node.depth.0.set_view( self.depth.map(|d| d + 1).get_view() ); let 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() ); @@ -401,7 +408,7 @@ impl TypeTermEditor { /* create new list-edit node for the ladder */ - let mut new_node = Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth ).unwrap(); + let mut new_node = Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth.map(|x| x) ).unwrap(); new_node = new_node.morph( (&self.ctx, "( Type::Ladder )").into() ); /* reconfigure current node to display new_node list-editor diff --git a/nested/src/tree/node.rs b/nested/src/tree/node.rs index 2e81ae3..c73da7c 100644 --- a/nested/src/tree/node.rs +++ b/nested/src/tree/node.rs @@ -82,16 +82,13 @@ pub struct NestedNode { pub diag: Option< OuterViewPort<dyn SequenceView<Item = Message>> >, /// depth - pub depth: SingletonBuffer< usize >, + pub depth: OuterViewPort< dyn SingletonView<Item = usize> >, /// abstract editor pub editor: SingletonBuffer< Option< Arc<dyn Any + Send + Sync> > >, - /* TODO: - * - spill buffer (contains overflowing elements as well as 'split-off' parts) - */ pub spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>, /// commander & navigation @@ -107,13 +104,13 @@ pub struct NestedNode { } impl NestedNode { - pub fn new(ctx: Arc<RwLock<Context>>, data: Arc<RwLock<ReprTree>>, depth: usize) -> Self { + pub fn new(ctx: Arc<RwLock<Context>>, data: Arc<RwLock<ReprTree>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> Self { NestedNode { ctx, data, view: None, diag: None, - depth: SingletonBuffer::new(depth), + depth, editor: SingletonBuffer::new(None), spillbuf: Arc::new(RwLock::new(Vec::new())), cmd: SingletonBuffer::new(None), @@ -133,7 +130,7 @@ impl NestedNode { (&ctx, "( Char )"), buf.get_port().into() ), - 0 + SingletonBuffer::new(0).get_port() ) .set_view(buf.get_port() .map(|c| TerminalAtom::from(c)) diff --git a/nested/src/type_system/context.rs b/nested/src/type_system/context.rs index 7e57eb9..7904994 100644 --- a/nested/src/type_system/context.rs +++ b/nested/src/type_system/context.rs @@ -1,4 +1,5 @@ use { + r3vi::{view::{OuterViewPort, singleton::*}, buffer::{singleton::*}}, crate::{ type_system::{TypeDict, TypeTerm, TypeID, ReprTree}, tree::NestedNode @@ -229,7 +230,7 @@ impl Context { self.type_dict.read().unwrap().type_term_to_str(&t) } - pub fn add_node_ctor(&mut self, tn: &str, mk_editor: Arc<dyn Fn(Arc<RwLock<Self>>, TypeTerm, usize) -> Option<NestedNode> + Send + Sync>) { + 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(); @@ -248,7 +249,7 @@ impl Context { drop(dict); self.add_morphism(morphism_pattern, Arc::new(move |node, dst_type| { - mk_editor(node.ctx.clone(), dst_type, node.depth.get()) + mk_editor(node.ctx.clone(), dst_type, node.depth) })); } @@ -275,7 +276,7 @@ impl Context { } } - pub fn make_node(ctx: &Arc<RwLock<Self>>, type_term: TypeTerm, depth: usize) -> Option<NestedNode> { + 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() @@ -284,7 +285,6 @@ impl Context { /* create new context per node ?? too heavy.. whats the reason? TODO */ let new_ctx = Arc::new(RwLock::new(Context::with_parent(Some(ctx.clone())))); - let _new_depth = depth; mk_node( NestedNode::new(new_ctx, ReprTree::new_arc(type_term.clone()), depth), @@ -323,7 +323,7 @@ impl Context { .type_dict.read().unwrap() .type_term_from_str(typename).unwrap(); - if let Some(node) = Context::make_node(&ctx, type_tag, 0) { + if let Some(node) = Context::make_node(&ctx, type_tag, SingletonBuffer::new(0).get_port()) { ctx.write().unwrap().nodes.insert(name, node); } } diff --git a/nested/src/utils/color.rs b/nested/src/utils/color.rs index 25772ee..532a7fe 100644 --- a/nested/src/utils/color.rs +++ b/nested/src/utils/color.rs @@ -5,23 +5,27 @@ use { pub fn bg_style_from_depth(depth: usize) -> TerminalStyle { match depth { 0 => TerminalStyle::bg_color((150,80,230)), - 1 => TerminalStyle::bg_color((75,75,75)), - 2 => TerminalStyle::bg_color((40,40,40)), - 3 => TerminalStyle::bg_color((30,30,30)), - 4 => TerminalStyle::bg_color((25,25,25)), - 5 => TerminalStyle::bg_color((20,20,20)), + 1 => TerminalStyle::bg_color((66,66,66)), + 2 => TerminalStyle::bg_color((44,44,44)), + 3 => TerminalStyle::bg_color((33,33,33)), + 4 => TerminalStyle::bg_color((28,28,28)), + 5 => TerminalStyle::bg_color((21,21,21)), _ => TerminalStyle::default(), } } pub fn fg_style_from_depth(depth: usize) -> TerminalStyle { - match depth % 6 { - 0 => TerminalStyle::fg_color((120, 120, 0)), - 1 => TerminalStyle::fg_color((250, 165, 40)), - 2 => TerminalStyle::fg_color((80, 180, 180)), - 3 => TerminalStyle::fg_color((180, 240, 85)), - 4 => TerminalStyle::fg_color((200, 190, 70)), - _ => TerminalStyle::default() - } + if depth == 0 { + TerminalStyle::fg_color((200, 200, 200)) + } else { + match depth % 5 { + 0 => TerminalStyle::fg_color((128, 106, 97)), + 1 => TerminalStyle::fg_color((100, 120, 232)), + 2 => TerminalStyle::fg_color((180, 100, 96)), + 3 => TerminalStyle::fg_color((188, 155, 18)), + 4 => TerminalStyle::fg_color((135, 182, 134)), + _ => TerminalStyle::default() + } + } } From 119105c6a22567923c25e0e374381da3a2b8dcc4 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Thu, 14 Sep 2023 13:17:50 +0200 Subject: [PATCH 05/10] typeterm editor: improve morphings --- nested/src/editors/list/cmd.rs | 6 +- nested/src/editors/list/ctx.rs | 2 +- nested/src/editors/list/editor.rs | 14 ++- nested/src/editors/list/nav.rs | 6 +- nested/src/editors/list/pty_editor.rs | 1 + nested/src/editors/typeterm/cmd.rs | 166 ++++++++++++++++++-------- nested/src/editors/typeterm/ctx.rs | 20 +++- nested/src/editors/typeterm/mod.rs | 123 +++++++------------ nested/src/editors/typeterm/nav.rs | 1 - 9 files changed, 195 insertions(+), 144 deletions(-) diff --git a/nested/src/editors/list/cmd.rs b/nested/src/editors/list/cmd.rs index d7958a5..1cf3c8e 100644 --- a/nested/src/editors/list/cmd.rs +++ b/nested/src/editors/list/cmd.rs @@ -151,16 +151,16 @@ impl ObjCommander for ListEditor { } else { TreeNavResult::Exit } - } } } else { if let Some(cur_item) = self.get_item_mut() { drop(cmd_repr); - cur_item.write().unwrap().send_cmd_obj(cmd_obj) - } else { + cur_item.write().unwrap().send_cmd_obj(cmd_obj); TreeNavResult::Continue + } else { + TreeNavResult::Exit } } } diff --git a/nested/src/editors/list/ctx.rs b/nested/src/editors/list/ctx.rs index f6eb5df..586db0b 100644 --- a/nested/src/editors/list/ctx.rs +++ b/nested/src/editors/list/ctx.rs @@ -10,7 +10,7 @@ use { //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> pub fn init_ctx(ctx: &mut Context) { - ctx.add_list_typename("ListCmd".into()); + ctx.add_typename("ListCmd".into()); ctx.add_list_typename("List".into()); ctx.add_node_ctor( diff --git a/nested/src/editors/list/editor.rs b/nested/src/editors/list/editor.rs index 9b81408..a926605 100644 --- a/nested/src/editors/list/editor.rs +++ b/nested/src/editors/list/editor.rs @@ -232,14 +232,15 @@ impl ListEditor { /// insert a new element pub fn insert(&mut self, item: Arc<RwLock<NestedNode>>) { + eprintln!("list insert"); + item.read().unwrap().depth.0.set_view( + self.depth.map(|d| d+1).get_view() + ); + let mut cur = self.cursor.get(); if let Some(idx) = cur.idx { match cur.mode { ListCursorMode::Insert => { - item.read().unwrap().depth.0.set_view( - self.depth.map(|d| d+1).get_view() - ); - self.data.insert(idx as usize, item.clone()); if self.is_listlist() { cur.mode = ListCursorMode::Select; @@ -263,7 +264,8 @@ impl ListEditor { } /// split the list off at the current cursor position and return the second half - pub fn split(&mut self) { + pub fn split(&mut self) { + eprintln!("split"); let cur = self.cursor.get(); if let Some(idx) = cur.idx { let idx = idx as usize; @@ -277,6 +279,7 @@ impl ListEditor { } pub fn listlist_split(&mut self) { + eprintln!("listlist split"); let cur = self.get_cursor(); if let Some(mut item) = self.get_item().clone() { @@ -293,6 +296,7 @@ impl ListEditor { tail_node.goto(TreeCursor::home()); for node in b.iter() { + eprintln!("splid :send to tail node"); tail_node .send_cmd_obj( ReprTree::new_leaf( diff --git a/nested/src/editors/list/nav.rs b/nested/src/editors/list/nav.rs index 88bac81..9842ef9 100644 --- a/nested/src/editors/list/nav.rs +++ b/nested/src/editors/list/nav.rs @@ -216,10 +216,12 @@ impl TreeNav for ListEditor { .write().unwrap() .goby(Vector2::new(direction.x, direction.y)) == TreeNavResult::Continue { - self.cursor.set(ListCursor { + let res = self.cursor.set(ListCursor { mode: ListCursorMode::Select, idx: Some(cur.tree_addr[0]) - }) + }); + self.set_leaf_mode(cur.leaf_mode); + res } } diff --git a/nested/src/editors/list/pty_editor.rs b/nested/src/editors/list/pty_editor.rs index e14a642..8238a93 100644 --- a/nested/src/editors/list/pty_editor.rs +++ b/nested/src/editors/list/pty_editor.rs @@ -147,6 +147,7 @@ impl PTYListController { // || Some(c) == child_close_char { e.listlist_split(); + eprintln!("done listlist split"); TreeNavResult::Continue } else if Some(c) == child_close_char { e.goto(TreeCursor::none()); diff --git a/nested/src/editors/typeterm/cmd.rs b/nested/src/editors/typeterm/cmd.rs index 56f93d8..57ad081 100644 --- a/nested/src/editors/typeterm/cmd.rs +++ b/nested/src/editors/typeterm/cmd.rs @@ -52,75 +52,138 @@ impl ObjCommander for TypeTermEditor { } State::Char => { - match c { - '\'' => { - self.cur_node.get_mut().goto(TreeCursor::none()); + match self.send_child_cmd( co ) { + TreeNavResult::Exit => { + match c { + '\'' => { + self.cur_node.get_mut().goto(TreeCursor::none()); + } + _ => {} + } TreeNavResult::Exit - } - _ => { - self.send_child_cmd( co ) - } + }, + TreeNavResult::Continue => TreeNavResult::Continue } } State::Ladder => { - if c == '~' { - let i0 = self.cur_node.get().get_edit::<ListEditor>().unwrap(); - if self.get_cursor().tree_addr.len() > 1 { - let cur_it = i0.clone().read().unwrap().get_item().clone(); - if let Some(i) = cur_it { - let tte = i.get_edit::<TypeTermEditor>().unwrap(); + match self.get_cursor().tree_addr.len() { - if tte.read().unwrap().state != State::App { - drop(tte); - drop(i); + // entire term is selected + 0 => { + match c { + '<' => { + self.morph_to_list(State::App); + TreeNavResult::Continue + } + _ => { TreeNavResult::Exit } + } + } - return self.send_child_cmd( - ListCmd::Split.into_repr_tree( &self.ctx ) - ); + // entire item selected or insert mode + 1 => { + match c { + '~' => { + // ignore '~' since we are already in a ladder + // and cant split current item + TreeNavResult::Continue + } + _ => { + self.send_child_cmd( co.clone() ) + } + } + } + + // some subterm + _ => { + match c { + '~' => { + let i0 = self.cur_node.get().get_edit::<ListEditor>().unwrap(); + let cur_it = i0.clone().read().unwrap().get_item().clone(); + if let Some(i) = cur_it { + let cur_tte = i.get_edit::<TypeTermEditor>().unwrap(); + if cur_tte.read().unwrap().state == State::App || cur_tte.read().unwrap().get_cursor().tree_addr.len() > 1 { + self.send_child_cmd( co.clone() ) + } else { + drop(cur_tte); + drop(i); + + self.send_child_cmd( + ListCmd::Split.into_repr_tree( &self.ctx ) + ) + } + } else { + self.send_child_cmd( co.clone() ) + } + } + _ => { + self.send_child_cmd( co.clone() ) } } - } else { - return TreeNavResult::Continue; } } - - self.send_child_cmd( co.clone() ) } State::App => { - let res = self.send_child_cmd( co.clone() ); - match res { - TreeNavResult::Exit => { + match self.get_cursor().tree_addr.len() { + + // entire Term is selected + 0 => { + match c { '~' => { - self.previous_item_into_ladder(); + self.morph_to_list(State::Ladder); + self.goto(TreeCursor { + tree_addr: vec![ -1 ], + leaf_mode: ListCursorMode::Insert + }); TreeNavResult::Continue - }, - _ => {TreeNavResult::Exit} + } + '<' => { + self.morph_to_list(State::App); + TreeNavResult::Continue + } + _ => { + TreeNavResult::Exit + } } - }, - TreeNavResult::Continue => { - match c { - '>'| - ' ' => { - let i = self.cur_node.get().get_edit::<ListEditor>().unwrap(); - let i = i.read().unwrap(); - if let Some(i) = i.get_item() { - let tte = i.get_edit::<TypeTermEditor>().unwrap(); - let mut tte = tte.write().unwrap(); - if tte.state == State::Ladder { - tte.normalize_singleton(); - } + }, + + // some item is selected + _ => { + match self.send_child_cmd( co.clone() ) { + TreeNavResult::Exit => { + match c { + '~' => { + self.previous_item_into_ladder(); + TreeNavResult::Continue + }, + _ => {TreeNavResult::Exit} } }, - _ => {} + TreeNavResult::Continue => { + match c { + '>'| + ' ' => { + let i = self.cur_node.get().get_edit::<ListEditor>().unwrap(); + let i = i.read().unwrap(); + if let Some(i) = i.get_item() { + let tte = i.get_edit::<TypeTermEditor>().unwrap(); + let mut tte = tte.write().unwrap(); + + if tte.state == State::Ladder { + tte.normalize_singleton(); + } + } + }, + _ => {} + } + TreeNavResult::Continue + } } - - TreeNavResult::Continue } } } @@ -132,11 +195,19 @@ impl ObjCommander for TypeTermEditor { match res { TreeNavResult::Exit => { match c { + '<' => { + self.goto(TreeCursor::none()); + self.morph_to_list(State::App); + TreeNavResult::Continue + } '~' => { - self.morph_to_ladder(); + self.morph_to_list(State::Ladder); + self.set_addr(0); + self.dn(); self.send_cmd_obj( ListCmd::Split.into_repr_tree( &self.ctx ) - ) + ); + TreeNavResult::Continue } _ => { TreeNavResult::Exit @@ -188,7 +259,6 @@ impl ObjCommander for TypeTermEditor { let res = self.send_child_cmd( co.clone() ); self.normalize_empty(); - if let Some(cmd) = co.read().unwrap().get_view::<dyn SingletonView<Item = ListCmd>>() { match cmd.get() { ListCmd::Split => { diff --git a/nested/src/editors/typeterm/ctx.rs b/nested/src/editors/typeterm/ctx.rs index 6ee0dbd..6ba6b47 100644 --- a/nested/src/editors/typeterm/ctx.rs +++ b/nested/src/editors/typeterm/ctx.rs @@ -41,14 +41,29 @@ pub fn init_ctx(ctx: &mut Context) { Arc::new(|mut node, _dst_type: _| { PTYListController::for_node( &mut node, Some('~'), None ); - let vertical_view = false; + let vertical_view = true; if vertical_view { let editor = node.get_edit::<crate::editors::list::ListEditor>().unwrap(); let mut e = editor.write().unwrap(); let seg_view = PTYListStyle::new( ("","~","") ).get_seg_seq_view( &mut e ); node = node.set_view( - seg_view.to_grid_vertical().flatten() + seg_view.to_grid_vertical() + .map_item( + |pt,x| + if pt.y > 0 { + r3vi::buffer::vec::VecBuffer::with_data(vec![ + crate::terminal::make_label("~"), + x.clone() + ]) + .get_port() + .to_sequence() + .to_grid_horizontal() + .flatten() + } else { + x.clone() + } + ).flatten() ); } else { PTYListStyle::for_node( &mut node, ("","~","") ); @@ -100,6 +115,7 @@ pub fn init_ctx(ctx: &mut Context) { ctx.add_morphism( MorphismTypePattern { src_tyid: ctx.get_typeid("Char"), dst_tyid: ctx.get_typeid("Type::Lit::Char").unwrap() }, Arc::new(|mut node, _dst_type:_| { + node.ctx.write().unwrap().meta_chars = vec![ '\'' ]; let mut grid = r3vi::buffer::index_hashmap::IndexBuffer::new(); grid.insert_iter( diff --git a/nested/src/editors/typeterm/mod.rs b/nested/src/editors/typeterm/mod.rs index 15f7e99..172cb26 100644 --- a/nested/src/editors/typeterm/mod.rs +++ b/nested/src/editors/typeterm/mod.rs @@ -124,7 +124,7 @@ impl TypeTermEditor { editor.send_cmd_obj(ReprTree::from_char(&ctx, *c)); } } - + node.goto(TreeCursor::none()); node } @@ -177,6 +177,7 @@ impl TypeTermEditor { pub fn new_node(ctx: Arc<RwLock<Context>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode { let ctx : Arc<RwLock<Context>> = Arc::new(RwLock::new(Context::with_parent(Some(ctx)))); ctx.write().unwrap().meta_chars.push('~'); + ctx.write().unwrap().meta_chars.push('<'); let mut symb_node = Context::make_node( &ctx, (&ctx, "( List Char )").into(), depth ).unwrap(); symb_node = symb_node.morph( (&ctx, "( Type::Sym )").into() ); @@ -298,31 +299,28 @@ impl TypeTermEditor { pub fn normalize_singleton(&mut self) { eprintln!("normalize singleton"); - if self.state == State::Ladder{ - - let subladder_list_node = self.cur_node.get().clone(); - let subladder_list_edit = subladder_list_node.get_edit::<ListEditor>().unwrap(); + if self.state == State::Ladder { + let subladder_list_node = self.cur_node.get().clone(); + let subladder_list_edit = subladder_list_node.get_edit::<ListEditor>().unwrap(); - let subladder_list_edit = subladder_list_edit.read().unwrap(); - if subladder_list_edit.data.len() == 1 { - let it_node = subladder_list_edit.data.get(0); - let it_node = it_node.read().unwrap(); - if it_node.get_type() == (&self.ctx, "( Type )").into() { - let other_tt = it_node.get_edit::<TypeTermEditor>().unwrap(); + let subladder_list_edit = subladder_list_edit.read().unwrap(); + if subladder_list_edit.data.len() == 1 { + let it_node = subladder_list_edit.data.get(0); + let it_node = it_node.read().unwrap(); + if it_node.get_type() == (&self.ctx, "( Type )").into() { + let other_tt = it_node.get_edit::<TypeTermEditor>().unwrap(); - let mut other_tt = other_tt.write().unwrap(); + let mut other_tt = other_tt.write().unwrap(); - other_tt.normalize_singleton(); + other_tt.normalize_singleton(); + other_tt.depth.0.set_view( self.depth.map(|x| x).get_view() ); - other_tt.depth.0.set_view( self.depth.map(|x| x).get_view() ); - - self.close_char.set(other_tt.close_char.get()); - self.cur_node.set(other_tt.cur_node.get()); - self.state = other_tt.state; + self.close_char.set(other_tt.close_char.get()); + self.cur_node.set(other_tt.cur_node.get()); + self.state = other_tt.state; + } } } - - } } /* in insert mode, morph the previous element into a ladder and continue there @@ -338,97 +336,58 @@ impl TypeTermEditor { app_edit.delete_nexd(); } + // select previous element app_edit.goto(TreeCursor{ tree_addr: vec![ cur.tree_addr[0]-1 ], leaf_mode: ListCursorMode::Select }); - - if let Some(item_node) = app_edit.get_item() { + + // get selected element + if let Some(item_node) = app_edit.get_item() { let item_typterm = item_node.get_edit::<TypeTermEditor>().expect("typetermedit"); let mut item_typterm = item_typterm.write().unwrap(); - match item_typterm.state { - - // if item at cursor is Ladder - State::Ladder => { - drop(item_typterm); - - app_edit.dn(); - app_edit.qnexd(); - } - _ => { - item_typterm.goto(TreeCursor::none()); - drop(item_typterm); - - // else create new ladder - let mut list_node = Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth.map(|d| d+1) ).unwrap(); - list_node = list_node.morph( (&self.ctx, "( Type::Ladder )").into() ); - - let mut new_node = TypeTermEditor::with_node( - self.ctx.clone(), - list_node, - State::Ladder - ); - - // 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() - ) - ); - - *app_edit.get_item_mut().unwrap().write().unwrap() = new_node; - app_edit.dn(); - } + if item_typterm.state != State::Ladder { + item_typterm.morph_to_list( State::Ladder ); } + + item_typterm.goto(TreeCursor { + tree_addr: vec![ -1 ], + leaf_mode: ListCursorMode::Insert + }); } } } - - // TODO: morph_to_app() / morph_to_list(state) - /* replace with new ladder node with self as first element + /* replace with new list-node (ladder/app) with self as first element */ - pub fn morph_to_ladder(&mut self) { + pub(super) fn morph_to_list(&mut self, state: State) { eprintln!("morph into ladder"); - - let old_node = self.cur_node.get().clone(); + + let mut old_node = self.cur_node.get().clone(); + + /* reconfigure current node to display new_node list-editor + */ + self.set_state( state ); /* create a new NestedNode with TerminaltypeEditor, * that has same state & child-node as current node. */ - let old_edit_node = TypeTermEditor::new_node( self.ctx.clone(), self.depth.map(|d| d + 1)); - old_node.depth.0.set_view( self.depth.map(|d| d + 1).get_view() ); + let old_edit_node = TypeTermEditor::new_node( self.ctx.clone(), SingletonBuffer::new(0).get_port() ); + old_node.depth.0.set_view( old_edit_node.depth.map(|x|x).get_view() ); + let 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(), self.depth.map(|x| x) ).unwrap(); - new_node = new_node.morph( (&self.ctx, "( Type::Ladder )").into() ); - - /* reconfigure current node to display new_node list-editor - */ - self.close_char.set(new_node.close_char.get()); - self.cur_node.set(new_node); - self.state = State::Ladder; - /* insert old node and split */ self.goto(TreeCursor::home()); - self.send_cmd_obj( + self.send_child_cmd( ReprTree::new_leaf( (&self.ctx, "( NestedNode )"), SingletonBuffer::new( old_edit_node ).get_port().into() ) ); - - self.set_addr(0); - self.dn(); } } diff --git a/nested/src/editors/typeterm/nav.rs b/nested/src/editors/typeterm/nav.rs index 0d3f970..6fb7bf1 100644 --- a/nested/src/editors/typeterm/nav.rs +++ b/nested/src/editors/typeterm/nav.rs @@ -42,4 +42,3 @@ impl TreeNav for TypeTermEditor { self.cur_node.get_mut().goto(new_cur) } } - From 120d0e1df069495157cf496f7209f6435d746e39 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Fri, 15 Sep 2023 15:15:59 +0200 Subject: [PATCH 06/10] context: fix is_list_type for App&Ladder types; properly reset cursor when remaining in same height after insert --- nested/src/editors/list/cmd.rs | 86 +++++++++++++-------------- nested/src/editors/list/editor.rs | 4 +- nested/src/editors/list/pty_editor.rs | 2 + nested/src/type_system/context.rs | 12 ++++ 4 files changed, 59 insertions(+), 45 deletions(-) diff --git a/nested/src/editors/list/cmd.rs b/nested/src/editors/list/cmd.rs index 1cf3c8e..6c10b30 100644 --- a/nested/src/editors/list/cmd.rs +++ b/nested/src/editors/list/cmd.rs @@ -71,55 +71,53 @@ impl ObjCommander for ListEditor { match cur.mode { ListCursorMode::Select => { if let Some(mut item) = self.get_item().clone() { - if self.is_listlist() { - let item_cur = item.get_cursor(); - - match cmd.get() { - ListCmd::DeletePxev => { - if idx > 0 - && item_cur.tree_addr.iter().fold( - true, - |is_zero, x| is_zero && (*x == 0) - ) - { - self.listlist_join_pxev(idx); - TreeNavResult::Continue - } else { - item.send_cmd_obj(cmd_obj) - } - } - - ListCmd::DeleteNexd => { - let item_cur = item.get_cursor_warp(); - let next_idx = idx as usize + 1; - - if next_idx < self.data.len() - && item_cur.tree_addr.iter().fold( - true, - |is_end, x| is_end && (*x == -1) - ) - { - self.listlist_join_nexd(idx as usize); - TreeNavResult::Continue - } else { - item.send_cmd_obj(cmd_obj) - } - } - - ListCmd::Split => { - self.listlist_split(); - TreeNavResult::Continue - } - - _ => { - item.send_cmd_obj(cmd_obj); + let item_cur = item.get_cursor(); + + match cmd.get() { + ListCmd::DeletePxev => { + eprintln!("SELECT: delete pxev"); + if idx > 0 + && item_cur.tree_addr.iter().fold( + true, + |is_zero, x| is_zero && (*x == 0) + ) + { + self.listlist_join_pxev(idx); TreeNavResult::Continue + } else { + item.send_cmd_obj(cmd_obj) } } - } else { - TreeNavResult::Exit + + ListCmd::DeleteNexd => { + let item_cur = item.get_cursor_warp(); + let next_idx = idx as usize + 1; + + if next_idx < self.data.len() + && item_cur.tree_addr.iter().fold( + true, + |is_end, x| is_end && (*x == -1) + ) + { + self.listlist_join_nexd(idx as usize); + TreeNavResult::Continue + } else { + item.send_cmd_obj(cmd_obj) + } + } + + ListCmd::Split => { + self.listlist_split(); + TreeNavResult::Continue + } + + _ => { + item.send_cmd_obj(cmd_obj); + TreeNavResult::Continue + } } } else { + eprintln!("ptylist: no item"); TreeNavResult::Exit } }, diff --git a/nested/src/editors/list/editor.rs b/nested/src/editors/list/editor.rs index a926605..7875864 100644 --- a/nested/src/editors/list/editor.rs +++ b/nested/src/editors/list/editor.rs @@ -245,7 +245,9 @@ impl ListEditor { if self.is_listlist() { cur.mode = ListCursorMode::Select; } else { - cur.idx = Some(idx + 1); + eprintln!("list insert: is not a listlist ({:?})", self.typ); + item.write().unwrap().goto(TreeCursor::none()); + cur.idx = Some(idx + 1); } } diff --git a/nested/src/editors/list/pty_editor.rs b/nested/src/editors/list/pty_editor.rs index 8238a93..ccb5812 100644 --- a/nested/src/editors/list/pty_editor.rs +++ b/nested/src/editors/list/pty_editor.rs @@ -65,6 +65,8 @@ impl PTYListStyle { //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> +// todo: rename to CharController + pub struct PTYListController { pub editor: Arc<RwLock<ListEditor>>, diff --git a/nested/src/type_system/context.rs b/nested/src/type_system/context.rs index 7904994..41df4a5 100644 --- a/nested/src/type_system/context.rs +++ b/nested/src/type_system/context.rs @@ -196,6 +196,18 @@ impl Context { TypeTerm::TypeID(id) => { self.list_types.contains(id) } + TypeTerm::Ladder(args) | + TypeTerm::App(args) => { + if args.len() > 0 { + if self.is_list_type(&args[0]) { + true + } else { + false + } + } else { + false + } + } _ => false } } From 10bff8a32cfba56ef31671883b44c21fab64266b Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Sat, 11 Nov 2023 18:00:26 +0100 Subject: [PATCH 07/10] list editor: add some bounds checks and debug messages --- nested/src/editors/list/cmd.rs | 4 ++++ nested/src/editors/list/editor.rs | 34 ++++++++++++++++++++++++--- nested/src/editors/list/nav.rs | 5 ++-- nested/src/editors/list/pty_editor.rs | 2 +- nested/src/editors/typeterm/mod.rs | 2 +- 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/nested/src/editors/list/cmd.rs b/nested/src/editors/list/cmd.rs index 6c10b30..d991d5d 100644 --- a/nested/src/editors/list/cmd.rs +++ b/nested/src/editors/list/cmd.rs @@ -58,6 +58,8 @@ impl ObjCommander for ListEditor { } else if let Some(cmd) = cmd_repr.get_view::<dyn SingletonView<Item = ListCmd>>() { + eprintln!("pty-list-editor some list cmmd"); + let cur = self.cursor.get(); drop(cmd_repr); @@ -125,6 +127,7 @@ impl ObjCommander for ListEditor { ListCursorMode::Insert => { match cmd.get() { ListCmd::DeletePxev => { + eprintln!("INSERT: delete pxev"); self.delete_pxev(); TreeNavResult::Continue } @@ -147,6 +150,7 @@ impl ObjCommander for ListEditor { } } } else { + eprintln!("ptylist: cursor has no idx"); TreeNavResult::Exit } } diff --git a/nested/src/editors/list/editor.rs b/nested/src/editors/list/editor.rs index 7875864..0ba346b 100644 --- a/nested/src/editors/list/editor.rs +++ b/nested/src/editors/list/editor.rs @@ -194,6 +194,7 @@ impl ListEditor { } } + /// is the element-type also a list-like editor (i.e. impls TreeNav) pub fn is_listlist(&self) -> bool { self.ctx.read().unwrap().is_list_type(&self.typ) } @@ -233,6 +234,7 @@ impl ListEditor { /// insert a new element pub fn insert(&mut self, item: Arc<RwLock<NestedNode>>) { eprintln!("list insert"); + item.read().unwrap().depth.0.set_view( self.depth.map(|d| d+1).get_view() ); @@ -277,6 +279,27 @@ impl ListEditor { ); self.data.remove(idx); } + + /* in case the split leaves an empty item-list + * as a last element, remove it + */ +/* + if self.is_listlist() { + if idx > 0 && idx < self.data.len()+1 { + /* we are in insert mode, + * get element before cursor + */ + let prev_idx = idx - 1; + let prev_node = self.data.get(prev_idx); + let prev_node = prev_node.read().unwrap(); + + if prev_node.get_data_view::<dyn SequenceView<Item = NestedNode>>(vec![].into_iter()).iter().count() == 0 { + drop(prev_node); + self.data.remove(prev_idx); + } + } + } + */ } } @@ -314,7 +337,7 @@ impl ListEditor { drop(item); tail_node.goto(TreeCursor::home()); - if cur.tree_addr.len() > 2 { + if cur.tree_addr.len() > 1 { tail_node.dn(); } @@ -364,13 +387,15 @@ impl ListEditor { ); } + + // fixme: is it oc0 or old_cur ?? if oc0.tree_addr.len() > 1 { pxv_editor.goto(TreeCursor { tree_addr: vec![ old_cur.tree_addr[0], 0 ], leaf_mode: ListCursorMode::Insert }); pxv_editor.send_cmd_obj(ListCmd::DeletePxev.into_repr_tree( &self.ctx )); - } else { + } else if oc0.tree_addr.len() > 0 { pxv_editor.goto(TreeCursor { tree_addr: vec![ old_cur.tree_addr[0] ], leaf_mode: ListCursorMode::Insert @@ -421,17 +446,20 @@ impl ListEditor { ); } + // fixme: is it oc0 or old_cur ?? if oc0.tree_addr.len() > 1 { cur_editor.goto(TreeCursor { tree_addr: vec![ old_cur.tree_addr[0], -1 ], leaf_mode: ListCursorMode::Insert }); cur_editor.send_cmd_obj(ListCmd::DeleteNexd.into_repr_tree( &self.ctx )); - } else { + } else if oc0.tree_addr.len() > 0 { cur_editor.goto(TreeCursor { tree_addr: vec![ old_cur.tree_addr[0] ], leaf_mode: ListCursorMode::Insert }); + } else { + cur_editor.goto(TreeCursor::none()); } } diff --git a/nested/src/editors/list/nav.rs b/nested/src/editors/list/nav.rs index 9842ef9..31d0cc2 100644 --- a/nested/src/editors/list/nav.rs +++ b/nested/src/editors/list/nav.rs @@ -195,6 +195,7 @@ impl TreeNav for ListEditor { TreeNavResult::Exit } else if direction.y > 0 { // dn + eprintln!("dn: data.len() = {}", self.data.len()); self.cursor.set(ListCursor { mode: if self.data.len() > 0 { cur.leaf_mode } else { ListCursorMode::Insert }, idx: Some(0) @@ -210,18 +211,18 @@ impl TreeNav for ListEditor { 1 => { if direction.y > 0 { // dn + if cur.tree_addr[0] < self.data.len() as isize { if self.data .get_mut(cur.tree_addr[0] as usize) .write().unwrap() .goby(Vector2::new(direction.x, direction.y)) == TreeNavResult::Continue { - let res = self.cursor.set(ListCursor { + self.cursor.set(ListCursor { mode: ListCursorMode::Select, idx: Some(cur.tree_addr[0]) }); self.set_leaf_mode(cur.leaf_mode); - res } } diff --git a/nested/src/editors/list/pty_editor.rs b/nested/src/editors/list/pty_editor.rs index ccb5812..c85b9aa 100644 --- a/nested/src/editors/list/pty_editor.rs +++ b/nested/src/editors/list/pty_editor.rs @@ -176,7 +176,7 @@ impl PTYListController { match new_edit.send_cmd_obj(cmd_obj.clone()) { TreeNavResult::Continue => { - e.insert(Arc::new(RwLock::new(new_edit))); + e.insert(Arc::new(RwLock::new(new_edit.clone()))); TreeNavResult::Continue } TreeNavResult::Exit => { diff --git a/nested/src/editors/typeterm/mod.rs b/nested/src/editors/typeterm/mod.rs index 172cb26..b53b0a8 100644 --- a/nested/src/editors/typeterm/mod.rs +++ b/nested/src/editors/typeterm/mod.rs @@ -40,7 +40,7 @@ pub struct TypeTermEditor { depth: OuterViewPort<dyn SingletonView<Item = usize>>, buf: SingletonBuffer< TypeTerm >, - + // editing/parsing state state: State, From 153faf9c13b5faed44290b2488e62d36c81eaf48 Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Sat, 11 Nov 2023 18:00:47 +0100 Subject: [PATCH 08/10] add get_subcursor() --- nested/src/tree/cursor.rs | 11 +++++++++++ nested/src/tree/nav.rs | 1 + nested/src/tree/node.rs | 9 +++------ nested/src/tree/treetype.rs | 4 ++-- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/nested/src/tree/cursor.rs b/nested/src/tree/cursor.rs index 934be6d..9caa659 100644 --- a/nested/src/tree/cursor.rs +++ b/nested/src/tree/cursor.rs @@ -24,6 +24,17 @@ impl TreeCursor { tree_addr: vec![], } } + + pub fn get_subcursor(&self, depth: usize) -> TreeCursor { + TreeCursor { + leaf_mode: self.leaf_mode, + tree_addr: if depth < self.tree_addr.len() { + self.tree_addr[ depth.. ].iter().cloned().collect() + } else { + vec![] + } + } + } } impl Default for TreeCursor { diff --git a/nested/src/tree/nav.rs b/nested/src/tree/nav.rs index 488e26b..67acee3 100644 --- a/nested/src/tree/nav.rs +++ b/nested/src/tree/nav.rs @@ -181,3 +181,4 @@ pub trait TreeNav { } } + diff --git a/nested/src/tree/node.rs b/nested/src/tree/node.rs index c73da7c..75fdf3e 100644 --- a/nested/src/tree/node.rs +++ b/nested/src/tree/node.rs @@ -32,18 +32,15 @@ struct NestedNodeEdit { /// abstract editor pub editor: SingletonBuffer< Option< Arc<dyn Any + Send + Sync> > ->, + >, - pub input_buf:: VecBuffer< NestedNode >, - pub output_buf: VecBuffer< NestedNode >, + pub spillbuf: VecBuffer< NestedNode >, /// commander & navigation pub cmd: SingletonBuffer< Option< Arc<RwLock<dyn ObjCommander + Send + Sync>> > >, - pub close_char: SingletonBuffer< - Option< char > - >, + pub close_char: SingletonBuffer< Option< char > >, // could be replaced by cmd when TreeNav -CmdObjects are used pub tree_nav: SingletonBuffer< diff --git a/nested/src/tree/treetype.rs b/nested/src/tree/treetype.rs index 9fd9ae3..07f0dce 100644 --- a/nested/src/tree/treetype.rs +++ b/nested/src/tree/treetype.rs @@ -7,8 +7,8 @@ use { }; pub trait TreeType { - fn get_type(&self, _addr: &TreeAddr) -> TypeTerm { - TypeTerm::new(TypeID::Var(0)) + fn get_type(&self, addr: &TreeAddr) -> Vec<TypeTerm> { + vec![] } } From 5aac404bf2ee5147278afa2fe94d35b596c96bac Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Sat, 11 Nov 2023 18:01:26 +0100 Subject: [PATCH 09/10] Cargo.toml: update termion & rename to lib-r3vi --- nested/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nested/Cargo.toml b/nested/Cargo.toml index 6793380..7a4c7d0 100644 --- a/nested/Cargo.toml +++ b/nested/Cargo.toml @@ -5,11 +5,11 @@ name = "nested" version = "0.1.0" [dependencies] -#r3vi = { git = "https://git.exobiont.de/senvas/r3vi.git" } -r3vi = { path = "../../r3vi" } +#r3vi = { git = "https://git.exobiont.de/senvas/lib-r3vi.git" } +r3vi = { path = "../../lib-r3vi" } no_deadlocks = "*" cgmath = { version = "0.18.0", features = ["serde"] } -termion = "1.5.5" +termion = "2.0.1" vte = "0.10.1" ansi_colours = "1.0" signal-hook = "0.3.1" From 6b2f8ee66f493a8501f255fb8420d4f279c589eb Mon Sep 17 00:00:00 2001 From: Michael Sippel <micha@fragmental.art> Date: Sun, 12 Nov 2023 18:07:20 +0100 Subject: [PATCH 10/10] use lib-laddertypes & remove old laddertypes implementation --- nested/Cargo.toml | 1 + nested/src/editors/char/mod.rs | 7 +- nested/src/editors/integer/ctx.rs | 3 +- nested/src/editors/integer/editor.rs | 9 +- nested/src/editors/list/cmd.rs | 2 +- nested/src/editors/list/ctx.rs | 3 +- nested/src/editors/list/editor.rs | 9 +- nested/src/editors/list/pty_editor.rs | 10 +- nested/src/editors/product/editor.rs | 5 +- nested/src/editors/product/segment.rs | 3 +- nested/src/editors/sum/editor.rs | 3 +- nested/src/editors/typeterm/cmd.rs | 8 +- nested/src/editors/typeterm/ctx.rs | 3 +- nested/src/editors/typeterm/mod.rs | 47 ++-- nested/src/tree/nav.rs | 4 +- nested/src/tree/node.rs | 9 +- nested/src/tree/treetype.rs | 2 +- nested/src/type_system/context.rs | 23 +- nested/src/type_system/dict.rs | 73 ------ nested/src/type_system/ladder.rs | 71 ----- nested/src/type_system/mod.rs | 11 +- nested/src/type_system/repr_tree.rs | 5 +- nested/src/type_system/term.rs | 361 -------------------------- 23 files changed, 86 insertions(+), 586 deletions(-) delete mode 100644 nested/src/type_system/dict.rs delete mode 100644 nested/src/type_system/ladder.rs delete mode 100644 nested/src/type_system/term.rs diff --git a/nested/Cargo.toml b/nested/Cargo.toml index 7a4c7d0..8814165 100644 --- a/nested/Cargo.toml +++ b/nested/Cargo.toml @@ -7,6 +7,7 @@ version = "0.1.0" [dependencies] #r3vi = { git = "https://git.exobiont.de/senvas/lib-r3vi.git" } r3vi = { path = "../../lib-r3vi" } +laddertypes = { path = "../../lib-laddertypes" } no_deadlocks = "*" cgmath = { version = "0.18.0", features = ["serde"] } termion = "2.0.1" diff --git a/nested/src/editors/char/mod.rs b/nested/src/editors/char/mod.rs index 63b0c00..2521cb1 100644 --- a/nested/src/editors/char/mod.rs +++ b/nested/src/editors/char/mod.rs @@ -6,8 +6,9 @@ use { }, buffer::singleton::* }, + laddertypes::{TypeTerm}, crate::{ - type_system::{Context, ReprTree, TypeTerm}, + type_system::{Context, ReprTree}, terminal::{TerminalAtom}, tree::{NestedNode, TreeNavResult}, commander::{ObjCommander} @@ -34,7 +35,7 @@ impl ObjCommander for CharEditor { let cmd_obj = cmd_obj.read().unwrap(); let cmd_type = cmd_obj.get_type().clone(); - if cmd_type == (&self.ctx, "( Char )").into() { + if cmd_type == Context::parse(&self.ctx, "Char") { if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() { let value = cmd_view.get(); @@ -77,7 +78,7 @@ impl CharEditor { NestedNode::new( ctx0.clone(), ReprTree::new_leaf( - ctx0.read().unwrap().type_term_from_str("( Char )").unwrap(), + ctx0.read().unwrap().type_term_from_str("Char").unwrap(), data.get_port().into() ), depth diff --git a/nested/src/editors/integer/ctx.rs b/nested/src/editors/integer/ctx.rs index e9189c9..99c9aa7 100644 --- a/nested/src/editors/integer/ctx.rs +++ b/nested/src/editors/integer/ctx.rs @@ -3,8 +3,9 @@ use { r3vi::{ view::{OuterViewPort, singleton::*} }, + laddertypes::{TypeTerm}, crate::{ - type_system::{Context, TypeTerm}, + type_system::{Context}, editors::{ list::*, integer::* diff --git a/nested/src/editors/integer/editor.rs b/nested/src/editors/integer/editor.rs index 8c6c393..3e11b34 100644 --- a/nested/src/editors/integer/editor.rs +++ b/nested/src/editors/integer/editor.rs @@ -10,8 +10,9 @@ use { index_hashmap::* } }, + laddertypes::{TypeTerm}, crate::{ - type_system::{Context, TypeTerm, ReprTree}, + type_system::{Context, ReprTree}, editors::list::{ListCmd, PTYListController, PTYListStyle}, terminal::{ TerminalAtom, TerminalStyle, make_label @@ -40,7 +41,7 @@ impl ObjCommander for DigitEditor { let cmd_obj = cmd_obj.read().unwrap(); let cmd_type = cmd_obj.get_type().clone(); - if cmd_type == (&self.ctx, "( Char )").into() { + if cmd_type == Context::parse(&self.ctx, "Char") { if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() { let c = cmd_view.get(); @@ -125,7 +126,7 @@ impl DigitEditor { pub fn get_data(&self) -> Arc<RwLock<ReprTree>> { ReprTree::ascend( &ReprTree::new_leaf( - self.ctx.read().unwrap().type_term_from_str("( Seq u32 )").unwrap(), + self.ctx.read().unwrap().type_term_from_str("<Seq u32>").unwrap(), self.get_data_port().into() ), self.get_type() @@ -145,7 +146,7 @@ impl PosIntEditor { pub fn new(ctx: Arc<RwLock<Context>>, radix: u32) -> Self { let mut node = Context::make_node( &ctx, - (&ctx, format!("( List ( Digit {} ) )", radix).as_str()).into(), + Context::parse(&ctx, format!("<List <Digit {}>>", radix).as_str()), r3vi::buffer::singleton::SingletonBuffer::new(0).get_port() ).unwrap(); diff --git a/nested/src/editors/list/cmd.rs b/nested/src/editors/list/cmd.rs index d991d5d..74c7fee 100644 --- a/nested/src/editors/list/cmd.rs +++ b/nested/src/editors/list/cmd.rs @@ -26,7 +26,7 @@ impl ListCmd { pub fn into_repr_tree(self, ctx: &Arc<RwLock<Context>>) -> Arc<RwLock<ReprTree>> { let buf = r3vi::buffer::singleton::SingletonBuffer::new(self); ReprTree::new_leaf( - (ctx, "( ListCmd )"), + Context::parse(ctx, "ListCmd"), buf.get_port().into() ) } diff --git a/nested/src/editors/list/ctx.rs b/nested/src/editors/list/ctx.rs index 586db0b..91474f0 100644 --- a/nested/src/editors/list/ctx.rs +++ b/nested/src/editors/list/ctx.rs @@ -1,7 +1,8 @@ use { r3vi::{view::{OuterViewPort, singleton::*}}, + laddertypes::{TypeTerm}, crate::{ - type_system::{Context, TypeTerm}, + type_system::{Context}, editors::list::{ListEditor, PTYListController, PTYListStyle} }, std::sync::{Arc, RwLock} diff --git a/nested/src/editors/list/editor.rs b/nested/src/editors/list/editor.rs index 0ba346b..31c1f1b 100644 --- a/nested/src/editors/list/editor.rs +++ b/nested/src/editors/list/editor.rs @@ -3,8 +3,9 @@ use { view::{ViewPort, OuterViewPort, singleton::*, sequence::*}, buffer::{singleton::*, vec::*} }, + laddertypes::{TypeTerm}, crate::{ - type_system::{Context, TypeTerm, ReprTree}, + type_system::{Context, ReprTree}, editors::list::{ListCursor, ListCursorMode, ListCmd}, tree::{NestedNode, TreeNav, TreeCursor}, diagnostics::Diagnostics, @@ -325,7 +326,7 @@ impl ListEditor { tail_node .send_cmd_obj( ReprTree::new_leaf( - (&self.ctx, "( NestedNode )"), + Context::parse(&self.ctx, "NestedNode"), SingletonBuffer::<NestedNode>::new( node.read().unwrap().clone() ).get_port().into() @@ -379,7 +380,7 @@ impl ListEditor { for x in data.iter() { pxv_editor.send_cmd_obj( ReprTree::new_leaf( - (&self.ctx, "( NestedNode )"), + Context::parse(&self.ctx, "NestedNode"), SingletonBuffer::<NestedNode>::new( x.read().unwrap().clone() ).get_port().into() @@ -438,7 +439,7 @@ impl ListEditor { for x in data.iter() { cur_editor.send_cmd_obj( ReprTree::new_leaf( - (&self.ctx, "( NestedNode )"), + Context::parse(&self.ctx, "NestedNode"), SingletonBuffer::<NestedNode>::new( x.read().unwrap().clone() ).get_port().into() diff --git a/nested/src/editors/list/pty_editor.rs b/nested/src/editors/list/pty_editor.rs index c85b9aa..829aef4 100644 --- a/nested/src/editors/list/pty_editor.rs +++ b/nested/src/editors/list/pty_editor.rs @@ -189,12 +189,12 @@ impl PTYListController { let res = item.write().unwrap().send_cmd_obj(cmd_obj.clone()); let child_close_char = item.read().unwrap().close_char.get(); - match res { + match res { TreeNavResult::Continue => TreeNavResult::Continue, TreeNavResult::Exit => { // child editor returned control, probably for meta-char handling.. - if cmd_obj.read().unwrap().get_type().clone() == ctx.type_term_from_str("( Char )").unwrap() { + if cmd_obj.read().unwrap().get_type().clone() == ctx.type_term_from_str("Char").unwrap() { let co = cmd_obj.read().unwrap(); if let Some(cmd_view) = co.get_view::<dyn SingletonView<Item = char>>() { drop(co); @@ -225,13 +225,13 @@ impl ObjCommander for PTYListController { let mut e = self.editor.write().unwrap(); let cmd_type = cmd_obj.read().unwrap().get_type().clone(); - if cmd_type == (&e.ctx, "( ListCmd )").into() - || cmd_type == (&e.ctx, "( NestedNode )").into() + if cmd_type == Context::parse(&e.ctx, "ListCmd").into() + || cmd_type == Context::parse(&e.ctx, "NestedNode").into() { e.send_cmd_obj( cmd_obj ) } - else if cmd_type == (&e.ctx, "( TerminalEvent )").into() { + else if cmd_type == Context::parse(&e.ctx, "TerminalEvent").into() { let co = cmd_obj.read().unwrap(); if let Some(view) = co.get_view::<dyn SingletonView<Item = TerminalEvent>>() { drop( co ); diff --git a/nested/src/editors/product/editor.rs b/nested/src/editors/product/editor.rs index 97967d1..d3bdd9a 100644 --- a/nested/src/editors/product/editor.rs +++ b/nested/src/editors/product/editor.rs @@ -9,8 +9,9 @@ use { index_hashmap::* } }, + laddertypes::{TypeTerm}, crate::{ - type_system::{Context, TypeTerm}, + type_system::{Context}, terminal::{ TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalView @@ -202,7 +203,7 @@ impl ObjCommander for ProductEditor { fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult { let co = cmd_obj.read().unwrap(); let cmd_type = co.get_type().clone(); - let term_event_type = (&self.ctx, "( TerminalEvent )").into(); + let term_event_type = Context::parse(&self.ctx, "TerminalEvent").into(); if cmd_type == term_event_type { if let Some(te_view) = co.get_view::<dyn SingletonView<Item = TerminalEvent>>() { diff --git a/nested/src/editors/product/segment.rs b/nested/src/editors/product/segment.rs index 0e20cb9..0b223f5 100644 --- a/nested/src/editors/product/segment.rs +++ b/nested/src/editors/product/segment.rs @@ -4,8 +4,9 @@ use { OuterViewPort } }, + laddertypes::{TypeTerm}, crate::{ - type_system::{Context, TypeTerm}, + type_system::{Context}, terminal::{ TerminalStyle, TerminalView, make_label diff --git a/nested/src/editors/sum/editor.rs b/nested/src/editors/sum/editor.rs index dc0c81e..14b7798 100644 --- a/nested/src/editors/sum/editor.rs +++ b/nested/src/editors/sum/editor.rs @@ -6,10 +6,11 @@ use { sequence::*, } }, + laddertypes::{TypeTerm}, crate::{ terminal::TerminalView, editors::list::ListCursorMode, - type_system::{Context, TypeTerm, ReprTree}, + type_system::{Context, ReprTree}, tree::{TreeNav, TreeCursor, TreeNavResult}, diagnostics::{Diagnostics, Message}, tree::NestedNode, diff --git a/nested/src/editors/typeterm/cmd.rs b/nested/src/editors/typeterm/cmd.rs index 57ad081..e219cc8 100644 --- a/nested/src/editors/typeterm/cmd.rs +++ b/nested/src/editors/typeterm/cmd.rs @@ -3,7 +3,7 @@ use { view::{singleton::*} }, crate::{ - type_system::{ReprTree}, + type_system::{Context, ReprTree}, editors::{list::{ListEditor, ListCmd, ListCursorMode}}, tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor}, commander::ObjCommander @@ -20,7 +20,7 @@ impl ObjCommander for TypeTermEditor { let cmd_obj = co.clone(); let cmd_obj = cmd_obj.read().unwrap(); - if cmd_obj.get_type().clone() == (&self.ctx, "( Char )").into() { + if cmd_obj.get_type().clone() == Context::parse(&self.ctx, "Char") { if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() { let c = cmd_view.get(); @@ -231,11 +231,11 @@ impl ObjCommander for TypeTermEditor { match &self.state { State::Any => { let cmd_repr = co.read().unwrap(); - if cmd_repr.get_type().clone() == (&self.ctx, "( NestedNode )").into() { + if cmd_repr.get_type().clone() == Context::parse(&self.ctx, "NestedNode") { if let Some(view) = cmd_repr.get_view::<dyn SingletonView<Item = NestedNode>>() { let node = view.get(); - if node.data.read().unwrap().get_type().clone() == (&self.ctx, "( Char )").into() { + if node.data.read().unwrap().get_type().clone() == Context::parse(&self.ctx, "Char") { self.set_state( State::AnySymbol ); } else { self.set_state( State::Ladder ); diff --git a/nested/src/editors/typeterm/ctx.rs b/nested/src/editors/typeterm/ctx.rs index 6ba6b47..4ad5b55 100644 --- a/nested/src/editors/typeterm/ctx.rs +++ b/nested/src/editors/typeterm/ctx.rs @@ -2,8 +2,9 @@ use { r3vi::{ view::{OuterViewPort, singleton::*} }, + laddertypes::{TypeTerm}, crate::{ - type_system::{Context, TypeTerm, MorphismTypePattern}, + type_system::{Context, MorphismTypePattern}, terminal::{TerminalStyle, TerminalProjections}, editors::{ list::{PTYListStyle, PTYListController, ListEditor, ListSegmentSequence}, diff --git a/nested/src/editors/typeterm/mod.rs b/nested/src/editors/typeterm/mod.rs index b53b0a8..d15cbb4 100644 --- a/nested/src/editors/typeterm/mod.rs +++ b/nested/src/editors/typeterm/mod.rs @@ -9,8 +9,9 @@ use { view::{OuterViewPort, singleton::*}, buffer::{singleton::*} }, + laddertypes::{TypeID, TypeTerm}, crate::{ - type_system::{Context, TypeID, TypeTerm, ReprTree}, + type_system::{Context, ReprTree}, editors::{list::{ListCursorMode, ListEditor, ListCmd}}, tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor}, commander::ObjCommander @@ -80,7 +81,7 @@ impl TypeTermEditor { node.send_cmd_obj( ReprTree::new_leaf( - (&ctx, "( NestedNode )"), + Context::parse(&ctx, "NestedNode"), SingletonBuffer::new(arg_node).get_port().into() ) ); @@ -98,7 +99,7 @@ impl TypeTermEditor { node.send_cmd_obj( ReprTree::new_leaf( - (&ctx, "( NestedNode )"), + Context::parse(&ctx, "NestedNode"), SingletonBuffer::new(arg_node).get_port().into() ) ); @@ -132,37 +133,37 @@ impl TypeTermEditor { fn set_state(&mut self, new_state: State) { let mut node = match new_state { State::Any => { - Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth.map(|x| x) ).unwrap() - .morph( (&self.ctx, "( Type::Sym )").into() ) + Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Char>"), self.depth.map(|x| x) ).unwrap() + .morph( Context::parse(&self.ctx, "Type::Sym") ) } State::App => { - Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth.map(|x| x) ).unwrap() - .morph( (&self.ctx, "( Type::App )").into() ) + Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Type>"), self.depth.map(|x| x) ).unwrap() + .morph( Context::parse(&self.ctx, "Type::App") ) } State::Ladder => { - Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth.map(|x| x) ).unwrap() - .morph( (&self.ctx, "( Type::Ladder )").into() ) + Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Type>"), self.depth.map(|x| x) ).unwrap() + .morph( Context::parse(&self.ctx, "Type::Ladder") ) } State::AnySymbol => { - Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth.map(|x| x) ).unwrap() - .morph( (&self.ctx, "( Type::Sym )").into() ) + Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Char>"), self.depth.map(|x| x) ).unwrap() + .morph( Context::parse(&self.ctx, "Type::Sym") ) }, State::FunSymbol => { - Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth.map(|x| x) ).unwrap() - .morph( (&self.ctx, "( Type::Sym::Fun )").into() ) + Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Char>"), self.depth.map(|x| x) ).unwrap() + .morph( Context::parse(&self.ctx, "Type::Sym::Fun") ) }, State::VarSymbol => { - Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth.map(|x| x) ).unwrap() - .morph( (&self.ctx, "( Type::Sym::Var )").into() ) + Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Char>"), self.depth.map(|x| x) ).unwrap() + .morph( Context::parse(&self.ctx, "Type::Sym::Var") ) } State::Num => { crate::editors::integer::PosIntEditor::new(self.ctx.clone(), 10) .into_node() - .morph( (&self.ctx, "( Type::Lit::Num )").into() ) + .morph( Context::parse(&self.ctx, "Type::Lit::Num") ) } State::Char => { - Context::make_node( &self.ctx, (&self.ctx, "( Char )").into(), self.depth.map(|x| x) ).unwrap() - .morph( (&self.ctx, "( Type::Lit::Char )").into() ) + Context::make_node( &self.ctx, Context::parse(&self.ctx, "Char"), self.depth.map(|x| x) ).unwrap() + .morph( Context::parse(&self.ctx, "Type::Lit::Char") ) } }; @@ -179,8 +180,8 @@ impl TypeTermEditor { ctx.write().unwrap().meta_chars.push('~'); ctx.write().unwrap().meta_chars.push('<'); - let mut symb_node = Context::make_node( &ctx, (&ctx, "( List Char )").into(), depth ).unwrap(); - symb_node = symb_node.morph( (&ctx, "( Type::Sym )").into() ); + let mut symb_node = Context::make_node( &ctx, Context::parse(&ctx, "<List Char>"), depth ).unwrap(); + symb_node = symb_node.morph( Context::parse(&ctx, "Type::Sym") ); Self::with_node( ctx.clone(), @@ -193,7 +194,7 @@ impl TypeTermEditor { let buf = SingletonBuffer::<TypeTerm>::new( TypeTerm::unit() ); let data = Arc::new(RwLock::new(ReprTree::new( - (&ctx, "( Type )") + Context::parse(&ctx, "Type") ))); let editor = TypeTermEditor { @@ -307,7 +308,7 @@ impl TypeTermEditor { if subladder_list_edit.data.len() == 1 { let it_node = subladder_list_edit.data.get(0); let it_node = it_node.read().unwrap(); - if it_node.get_type() == (&self.ctx, "( Type )").into() { + if it_node.get_type() == Context::parse(&self.ctx, "Type") { let other_tt = it_node.get_edit::<TypeTermEditor>().unwrap(); let mut other_tt = other_tt.write().unwrap(); @@ -384,7 +385,7 @@ impl TypeTermEditor { self.goto(TreeCursor::home()); self.send_child_cmd( ReprTree::new_leaf( - (&self.ctx, "( NestedNode )"), + Context::parse(&self.ctx, "NestedNode"), SingletonBuffer::new( old_edit_node ).get_port().into() ) ); diff --git a/nested/src/tree/nav.rs b/nested/src/tree/nav.rs index 67acee3..9d85cdd 100644 --- a/nested/src/tree/nav.rs +++ b/nested/src/tree/nav.rs @@ -21,10 +21,10 @@ use { cgmath::Vector2, }; -#[derive(Clone, Copy, Eq, PartialEq)] +#[derive(Clone, Copy, Eq, PartialEq, Debug)] pub enum TreeNavResult { Continue, Exit } -#[derive(Clone, Copy, Eq, PartialEq)] +#[derive(Clone, Copy, Eq, PartialEq, Debug)] pub enum TreeHeightOp { P, Q, Max } pub trait TreeNav { diff --git a/nested/src/tree/node.rs b/nested/src/tree/node.rs index 75fdf3e..1406c96 100644 --- a/nested/src/tree/node.rs +++ b/nested/src/tree/node.rs @@ -5,8 +5,9 @@ use { view::{View, ViewPort, OuterViewPort, AnyOuterViewPort, singleton::*, sequence::*}, buffer::{singleton::*} }, + laddertypes::{TypeTerm}, crate::{ - type_system::{ReprTree, Context, TypeTerm}, + type_system::{ReprTree, Context}, terminal::{TerminalView, TerminalEvent, TerminalEditor, TerminalEditorResult, TerminalAtom}, diagnostics::{Diagnostics, Message}, tree::{TreeNav, TreeCursor, TreeNavResult, TreeHeightOp}, @@ -124,7 +125,7 @@ impl NestedNode { NestedNode::new( ctx.clone(), ReprTree::new_leaf( - (&ctx, "( Char )"), + Context::parse(&ctx, "Char"), buf.get_port().into() ), SingletonBuffer::new(0).get_port() @@ -194,7 +195,7 @@ impl NestedNode { 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| ((&ctx, s)).into()); + 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() @@ -256,7 +257,7 @@ impl TerminalEditor for NestedNode { if let Some(cmd) = self.cmd.get() { cmd.write().unwrap().send_cmd_obj( ReprTree::new_leaf( - self.ctx.read().unwrap().type_term_from_str("( TerminalEvent )").unwrap(), + self.ctx.read().unwrap().type_term_from_str("TerminalEvent").unwrap(), AnyOuterViewPort::from(buf.get_port()) )); } diff --git a/nested/src/tree/treetype.rs b/nested/src/tree/treetype.rs index 07f0dce..9f66849 100644 --- a/nested/src/tree/treetype.rs +++ b/nested/src/tree/treetype.rs @@ -1,7 +1,7 @@ use { + laddertypes::{TypeTerm, TypeID}, crate::{ - type_system::{TypeTerm, TypeID}, tree::{TreeAddr} } }; diff --git a/nested/src/type_system/context.rs b/nested/src/type_system/context.rs index 41df4a5..bf4f8c4 100644 --- a/nested/src/type_system/context.rs +++ b/nested/src/type_system/context.rs @@ -1,7 +1,8 @@ use { r3vi::{view::{OuterViewPort, singleton::*}, buffer::{singleton::*}}, + laddertypes::{TypeDict, TypeTerm, TypeID}, crate::{ - type_system::{TypeDict, TypeTerm, TypeID, ReprTree}, + type_system::{ReprTree}, tree::NestedNode }, std::{ @@ -135,12 +136,6 @@ impl Default for Context { } } -impl Into<TypeTerm> for (&Arc<RwLock<Context>>, &str) { - fn into(self) -> TypeTerm { - self.0.read().unwrap().type_term_from_str(self.1).expect("could not parse type term") - } -} - impl Context { pub fn with_parent(parent: Option<Arc<RwLock<Context>>>) -> Self { Context { @@ -174,6 +169,10 @@ impl Context { } } + pub fn parse(ctx: &Arc<RwLock<Self>>, s: &str) -> TypeTerm { + ctx.read().unwrap().type_term_from_str(s).expect("could not parse type term") + } + pub fn add_typename(&mut self, tn: &str) -> TypeID { self.type_dict.write().unwrap().add_typename(tn.to_string()) } @@ -234,12 +233,12 @@ impl Context { } } - pub fn type_term_from_str(&self, tn: &str) -> Option<TypeTerm> { - self.type_dict.read().unwrap().type_term_from_str(&tn) + pub fn type_term_from_str(&self, tn: &str) -> Result<TypeTerm, laddertypes::parser::ParseError> { + self.type_dict.write().unwrap().parse(&tn) } pub fn type_term_to_str(&self, t: &TypeTerm) -> String { - self.type_dict.read().unwrap().type_term_to_str(&t) + 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>) { @@ -332,8 +331,8 @@ impl Context { /// 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.read().unwrap() - .type_term_from_str(typename).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); diff --git a/nested/src/type_system/dict.rs b/nested/src/type_system/dict.rs deleted file mode 100644 index b8fd44c..0000000 --- a/nested/src/type_system/dict.rs +++ /dev/null @@ -1,73 +0,0 @@ -use { - crate::{ - utils::Bimap, - type_system::{TypeTerm} - } -}; - -//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> - -#[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() - } - - pub fn type_term_from_str(&self, typename: &str) -> Option<TypeTerm> { - TypeTerm::from_str(typename, &self.typenames.mλ) - } - - pub fn type_term_to_str(&self, term: &TypeTerm) -> String { - term.to_str(&self.typenames.my) - } -} - -//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> - diff --git a/nested/src/type_system/ladder.rs b/nested/src/type_system/ladder.rs deleted file mode 100644 index ca7fef0..0000000 --- a/nested/src/type_system/ladder.rs +++ /dev/null @@ -1,71 +0,0 @@ -use { - crate::type_system::{TypeTerm, TypeID}, - std::collections::HashMap -}; - -//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> - -#[derive(Clone, Eq, PartialEq, Hash, Debug)] -pub struct TypeLadder(pub Vec<TypeTerm>); - -//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> - -impl From<Vec<TypeTerm>> for TypeLadder { - fn from(l: Vec<TypeTerm>) -> Self { - TypeLadder(l) - } -} - -impl From<TypeTerm> for TypeLadder { - fn from(l: TypeTerm) -> Self { - TypeLadder(vec![ l ]) - } -} - -impl TypeLadder { - /// if compatible, returns the number of descents neccesary - pub fn is_compatible_with(&self, other: &TypeLadder) -> Option<usize> { - if let Some(other_top_type) = other.0.first() { - for (i, t) in self.0.iter().enumerate() { - if t == other_top_type { - return Some(i); - } - } - - None - } else { - None - } - } - - pub fn is_matching_repr(&self, other: &TypeLadder) -> Result<usize, Option<(usize, usize)>> { - if let Some(start) = self.is_compatible_with(other) { - for (i, (t1, t2)) in self.0.iter().skip(start).zip(other.0.iter()).enumerate() { - if t1 != t2 { - return Err(Some((start, i))); - } - } - - Ok(start) - } else { - Err(None) - } - } - - pub fn to_str1(&self, names: &HashMap<TypeID, String>) -> String { - let mut s = String::new(); - let mut first = true; - - for t in self.0.iter() { - if !first { - s = s + "~"; - } - first = false; - s = s + &t.to_str(names); - } - s - } -} - -//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> - diff --git a/nested/src/type_system/mod.rs b/nested/src/type_system/mod.rs index f52f6ef..6d52a5b 100644 --- a/nested/src/type_system/mod.rs +++ b/nested/src/type_system/mod.rs @@ -1,15 +1,8 @@ pub mod context; - -pub mod dict; -pub mod term; -//pub mod ladder; pub mod repr_tree; pub use { - dict::*, -// ladder::*, - repr_tree::*, - term::*, - context::{Context, MorphismMode, MorphismType, MorphismTypePattern} + context::{Context, MorphismMode, MorphismType, MorphismTypePattern}, + repr_tree::ReprTree }; diff --git a/nested/src/type_system/repr_tree.rs b/nested/src/type_system/repr_tree.rs index eeeb8cf..611565c 100644 --- a/nested/src/type_system/repr_tree.rs +++ b/nested/src/type_system/repr_tree.rs @@ -1,7 +1,8 @@ use { r3vi::view::{AnyOuterViewPort, OuterViewPort, View}, + laddertypes::{TypeTerm}, crate::{ - type_system::{TypeTerm, Context} + type_system::{Context} }, std::{ collections::HashMap, @@ -50,7 +51,7 @@ impl ReprTree { pub fn from_char(ctx: &Arc<RwLock<Context>>, c: char) -> Arc<RwLock<Self>> { let buf = r3vi::buffer::singleton::SingletonBuffer::<char>::new(c); ReprTree::new_leaf( - (ctx, "( Char )"), + Context::parse(ctx, "Char"), buf.get_port().into() ) } diff --git a/nested/src/type_system/term.rs b/nested/src/type_system/term.rs deleted file mode 100644 index 12c1c15..0000000 --- a/nested/src/type_system/term.rs +++ /dev/null @@ -1,361 +0,0 @@ -use { - crate::{type_system::{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)) - } - - /// transform term to have at max 2 entries in Application list - pub fn curry(&self) -> Self { - match self { - TypeTerm::App(head) => { - let mut head = head.clone(); - if head.len() > 2 { - let mut tail = head.split_off(2); - - TypeTerm::App(vec![ - TypeTerm::App(head), - if tail.len() > 1 { - TypeTerm::App(tail).curry() - } else { - tail.remove(0) - } - ]) - } else { - TypeTerm::App(head) - } - } - - TypeTerm::Ladder(l) => { - TypeTerm::Ladder( l.iter().map(|x| x.curry()).collect() ) - } - - atom => { atom.clone() } - } - } - - /// summarize all curried applications into one vec - pub fn decurry(&mut self) -> &mut Self { - match self { - TypeTerm::App(args) => { - if args.len() > 0 { - let mut a0 = args.remove(0); - a0.decurry(); - match a0 { - TypeTerm::App(sub_args) => { - for (i,x) in sub_args.into_iter().enumerate() { - args.insert(i, x); - } - } - other => { args.insert(0, other); } - } - } - } - TypeTerm::Ladder(args) => { - for x in args.iter_mut() { - x.decurry(); - } - } - _ => {} - } - - self - } - - /// does the type contain ladders (false) or is it 'flat' (true) ? - pub fn is_flat(&self) -> bool { - match self { - TypeTerm::TypeID(_) => true, - TypeTerm::Num(_) => true, - TypeTerm::Char(_) => true, - TypeTerm::App(args) => args.iter().fold(true, |s,x| s && x.is_flat()), - TypeTerm::Ladder(_) => false - } - } - - pub fn get_lnf_vec(self) -> Vec<TypeTerm> { - match self.normalize() { - TypeTerm::Ladder( v ) => { - v - }, - _ => { - unreachable!(); - } - } - } - - /// transmute self into Ladder-Normal-Form - /// - /// Example: - /// <Seq <Digit 10>~Char> ⇒ <Seq <Digit 10>>~<Seq Char> - pub fn normalize(self) -> Self { - let mut new_ladder = Vec::<TypeTerm>::new(); - - match self { - TypeTerm::Ladder(args) => { - for x in args.into_iter() { - new_ladder.push(x.normalize()); - } - } - - TypeTerm::App(args) => { - let mut args_iter = args.into_iter(); - if let Some(head) = args_iter.next() { - - let mut stage1_args = vec![ head.clone() ]; - let mut stage2_args = vec![ head.clone() ]; - - let mut done = false; - - for x in args_iter { - match x.normalize() { - TypeTerm::Ladder(mut ladder) => { - // normalize this ladder - - if !done { - if ladder.len() > 2 { - stage1_args.push( ladder.remove(0) ); - stage2_args.push( TypeTerm::Ladder(ladder.to_vec()) ); - done = true; - } else if ladder.len() == 1 { - stage1_args.push( ladder[0].clone() ); - stage2_args.push( ladder[0].clone() ); - } else { - // empty type ? - } - - } else { - stage1_args.push( TypeTerm::Ladder(ladder.clone()) ); - stage2_args.push( TypeTerm::Ladder(ladder.clone()) ); - } - }, - _ => { - unreachable!("x is in LNF"); - } - } - } - - new_ladder.push(TypeTerm::Ladder(stage1_args)); - new_ladder.push(TypeTerm::Ladder(stage2_args)); - } - } - - atom => { - new_ladder.push(atom); - } - } - - TypeTerm::Ladder( new_ladder ) - } - - pub fn is_semantic_supertype_of(&self, t: &TypeTerm) -> Option<( usize, TypeTerm )> { - t.is_semantic_subtype_of(self) - } - - // returns ladder-step of first match and provided representation-type - pub fn is_semantic_subtype_of(&self, expected_type: &TypeTerm) -> Option<( usize, TypeTerm )> { - let provided_lnf = self.clone().get_lnf_vec(); - let expected_lnf = expected_type.clone().get_lnf_vec(); - - for i in 0..provided_lnf.len() { - if provided_lnf[i] == expected_lnf[0] { - return Some((i, TypeTerm::Ladder( - provided_lnf[i..].into_iter().cloned().collect() - ))) - } - } - - None - } - - pub fn is_syntactic_subtype_of(&self, expected_type: &TypeTerm) -> Result<usize, Option<(usize, usize)>> { - if let Some((first_match, provided_type)) = self.is_semantic_subtype_of( expected_type ) { - let provided_lnf = self.clone().get_lnf_vec(); - let expected_lnf = expected_type.clone().get_lnf_vec(); - - let l = usize::min( provided_lnf.len(), expected_lnf.len() ); - - for i in 0..l { - - if provided_lnf[i] != expected_lnf[i] { - return Err(Some((first_match, i))) - } - } - - Ok(l-1) - } else { - Err(None) - } - } - - /* this function is deprecated and only partially working, - wontfix, will be replaced by TypeTerm-Editor - */ - pub fn from_str(s: &str, names: &HashMap<String, TypeID>) -> Option<Self> { - let mut term_stack = Vec::<Option<TypeTerm>>::new(); - - for token in s.split_whitespace() { - match token { - "(" => { - term_stack.push(None); - } - ")" => { - let t = term_stack.pop().unwrap(); - if term_stack.len() > 0 { - let f = term_stack.last_mut().unwrap(); - if let Some(f) = f { - f.arg(t.unwrap()); - } else { - //error - } - } else { - return t; - } - } - atom => { - if let Some(f) = term_stack.last_mut() { - match f { - Some(f) => { - let mut chars = atom.chars(); - let first = chars.next().unwrap(); - - if first.is_numeric() { - f.num_arg(i64::from_str_radix(atom, 10).unwrap()); - } else if first == '\'' { - if let Some(mut c) = chars.next() { - if c == '\\' { - if let Some('n') = chars.next() { - c = '\n'; - } - } - f.char_arg(c); - } - } else { - f.arg(TypeTerm::new( - names.get(atom) - .expect(&format!("invalid atom {}", atom)).clone() - )); - } - } - None => { - *f = Some(TypeTerm::new( - names.get(atom).expect(&format!("invalid atom {}", atom)).clone(), - )); - } - } - } - } - } - } - - None - } - - pub fn to_str(&self, names: &HashMap<TypeID, String>) -> String { - match self { - TypeTerm::App(args) => { - let mut out = String::new(); - - out.push_str(&"<"); - - let mut first = true; - for x in args.iter() { - if !first { - out.push_str(&" "); - } else { - first = false; - } - - out.push_str(&x.to_str(names)); - } - - out.push_str(&">"); - - out - } - - TypeTerm::Ladder(l) => { - let mut out = String::new(); - - let mut first = true; - for x in l.iter() { - if !first { - out.push_str(&"~"); - } else { - first = false; - } - - out.push_str(&x.to_str(names)); - } - - out - } - - TypeTerm::Num(n) => format!("{}", n), - TypeTerm::Char('\n') => format!("'\\n'"), - TypeTerm::Char(c) => format!("'{}'", c), - TypeTerm::TypeID(id) => format!("{}", names[id]), - } - } -}