From 3968baffe172196167049f98b77c1b34bb2eaa4b Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Mon, 3 Jul 2023 12:32:03 +0200 Subject: [PATCH] wip --- nested/src/editors/list/editor.rs | 97 ++++++++++++++------------- nested/src/editors/list/nav.rs | 11 ++- nested/src/editors/list/pty_editor.rs | 35 +++++++--- nested/src/tree/node.rs | 74 ++++++++++---------- nested/src/type_system/context.rs | 2 +- nested/src/type_system/editor.rs | 37 +++------- nested/src/type_system/make_editor.rs | 4 +- 7 files changed, 132 insertions(+), 128 deletions(-) diff --git a/nested/src/editors/list/editor.rs b/nested/src/editors/list/editor.rs index d98d9f2..32a1e76 100644 --- a/nested/src/editors/list/editor.rs +++ b/nested/src/editors/list/editor.rs @@ -16,7 +16,7 @@ use { pub struct ListEditor { pub(super) cursor: SingletonBuffer, - pub data: VecBuffer, + pub data: VecBuffer< Arc> >, pub(super) addr_port: OuterViewPort>, pub(super) mode_port: OuterViewPort>, @@ -64,7 +64,7 @@ impl ListEditor { typ: TypeTerm, ) -> Self { let cursor = SingletonBuffer::new(ListCursor::default()); - let data = VecBuffer::::new(); + let data = VecBuffer::>>::new(); ListEditor { mode_port: cursor @@ -77,7 +77,7 @@ impl ListEditor { ListCursorMode::Insert => ip, ListCursorMode::Select => { if let Some(idx) = c.idx { - data.get(idx as usize).get_mode_view() + data.get(idx as usize).read().unwrap().get_mode_view() } else { ip } @@ -99,7 +99,7 @@ impl ListEditor { if cur.mode == ListCursorMode::Select { if let Some(idx) = cur.idx { if idx >= 0 && idx < data.len() as isize { - return data.get(idx as usize).get_addr_view(); + return data.get(idx as usize).read().unwrap().get_addr_view(); } } } @@ -131,7 +131,7 @@ impl ListEditor { .set_data(data) .set_editor(editor.clone()) .set_nav(editor.clone()) - //.set_cmd(editor.clone()) + //.set_cmd(editor.clone()) .set_diag(e .get_data_port() .enumerate() @@ -169,7 +169,9 @@ impl ListEditor { } pub fn get_data_port(&self) -> OuterViewPort> { - self.data.get_port().to_sequence() + self.data.get_port().to_sequence().map( + |x| x.read().unwrap().clone() + ) } pub fn get_data(&self) -> Arc> { @@ -184,7 +186,7 @@ impl ListEditor { if let Some(idx) = self.cursor.get().idx { let idx = crate::utils::modulo(idx as isize, self.data.len() as isize) as usize; if idx < self.data.len() { - Some(self.data.get(idx)) + Some(self.data.get(idx).read().unwrap().clone()) } else { None } @@ -193,7 +195,7 @@ impl ListEditor { } } - pub fn get_item_mut(&mut self) -> Option> { + pub fn get_item_mut(&mut self) -> Option>>> { if let Some(idx) = self.cursor.get().idx { let idx = crate::utils::modulo(idx as isize, self.data.len() as isize) as usize; if idx < self.data.len() { @@ -208,14 +210,6 @@ impl ListEditor { pub fn is_listlist(&self) -> bool { self.ctx.read().unwrap().is_list_type(&self.typ) - /* - match self.typ.clone() { - TypeTerm::Type { id, args } => { - id == self.ctx.read().unwrap().get_typeid("List").unwrap() - }, - TypeTerm::Num(_) => false - } - */ } /// delete all items @@ -246,10 +240,9 @@ impl ListEditor { } /// insert a new element - pub fn insert(&mut self, item: NestedNode) { + pub fn insert(&mut self, item: Arc>) { let mut cur = self.cursor.get(); if let Some(idx) = cur.idx { - match cur.mode { ListCursorMode::Insert => { self.data.insert(idx as usize, item.clone()); @@ -276,6 +269,7 @@ impl ListEditor { /// split the list off at the current cursor position and return the second half pub fn split(&mut self) -> ListEditor { + eprintln!("split!"); let mut le = ListEditor::new( Arc::new(RwLock::new(self.ctx.read().unwrap().clone())), self.typ.clone()); @@ -290,12 +284,16 @@ impl ListEditor { if self.is_listlist() { if idx > 0 && idx < self.data.len()+1 { + let prev_idx = idx - 1; // we are in insert mode, last element before cursor let prev_node = self.data.get(prev_idx); - if let Some(prev_editor) = prev_node.editor.clone() { - prev_editor.0.update(); - let prev_editor = prev_editor.get_view().unwrap().get().unwrap().downcast::>().unwrap(); + eprintln!("try locking prev node"); + let prev_node = prev_node.read().unwrap(); + eprintln!("locked prev node"); + + if let Some(prev_editor) = prev_node.editor.get() { + let prev_editor = prev_editor.downcast::>().unwrap(); let prev_editor = prev_editor.write().unwrap(); prev_editor.get_data_port().0.update(); @@ -347,24 +345,28 @@ impl ListEditor { } } - pub fn listlist_split(&mut self) { + eprintln!("listlist split"); let cur = self.get_cursor(); - if let Some(item) = self.get_item_mut() { + + eprintln!("cur = {:?}", cur); + if let Some(item) = self.get_item() { + eprintln!("got item"); +// let item = item.read().unwrap(); let depth = item.depth; - if let Some(head_editor) = item.editor.clone() { - - head_editor.0.update(); - let head = head_editor.get_view().unwrap().get().unwrap().downcast::>().unwrap(); + if let Some(head_editor) = item.editor.get() { + eprintln!("got head editor"); + let head = head_editor.downcast::>().unwrap(); let mut head = head.write().unwrap(); if head.data.len() > 0 { - + eprintln!("data len > 0"); if cur.tree_addr.len() > 2 { head.listlist_split(); } + eprintln!("split head"); let mut tail = head.split(); head.goto(TreeCursor::none()); @@ -388,15 +390,16 @@ impl ListEditor { None }; - let mut tail_node = tail.into_node(depth); - tail_node = tail_node.set_ctx(item.ctx.clone().unwrap()); + let mut tail_node = tail.into_node(depth.get()); - // if let Some(item_type) = item_type { - tail_node = tail_node.morph(self.typ.clone()); + //if let Some(item_type) = item_type { + //eprintln!("morph to {}", self.ctx.read().unwrap().type_term_to_str(&self.typ)); + tail_node = tail_node.morph(self.typ.clone()); //} - + + //eprintln!("insert node"); self.insert( - tail_node + Arc::new(RwLock::new(tail_node)) ); } } @@ -406,15 +409,14 @@ impl ListEditor { pub fn listlist_join_pxev(&mut self, idx: isize, item: &NestedNode) { { let prev_editor = self.data.get_mut(idx as usize-1); - let prev_editor = prev_editor.editor.clone(); - if let Some(prev_editor) = prev_editor { - prev_editor.0.update(); - if let Ok(prev_editor) = prev_editor.get_view().unwrap().get().unwrap().downcast::>() { + let prev_editor = prev_editor.read().unwrap(); + + if let Some(prev_editor) = prev_editor.editor.get() { + if let Ok(prev_editor) = prev_editor.downcast::>() { let mut prev_editor = prev_editor.write().unwrap(); - let cur_editor = item.editor.clone().unwrap(); - cur_editor.0.update(); - let cur_editor = cur_editor.get_view().unwrap().get().unwrap().downcast::>().unwrap(); + let cur_editor = item.editor.get().unwrap(); + let cur_editor = cur_editor.downcast::>().unwrap(); let cur_editor = cur_editor.write().unwrap(); prev_editor.join(&cur_editor); @@ -434,14 +436,13 @@ impl ListEditor { pub fn listlist_join_nexd(&mut self, next_idx: usize, item: &NestedNode) { { - let next_editor = self.data.get_mut(next_idx).editor.clone(); - if let Some(next_editor) = next_editor { - next_editor.0.update(); - if let Ok(next_editor) = next_editor.get_view().unwrap().get().unwrap().downcast::>() { + let next_editor = self.data.get(next_idx); + let next_editor = next_editor.read().unwrap(); + if let Some(next_editor) = next_editor.editor.get() { + if let Ok(next_editor) = next_editor.downcast::>() { let mut next_editor = next_editor.write().unwrap(); - let cur_editor = item.editor.clone().unwrap(); - cur_editor.0.update(); - let cur_editor = cur_editor.get_view().unwrap().get().unwrap().downcast::>().unwrap(); + let cur_editor = item.editor.get().unwrap(); + let cur_editor = cur_editor.downcast::>().unwrap(); let mut cur_editor = cur_editor.write().unwrap(); cur_editor.join(&next_editor); diff --git a/nested/src/editors/list/nav.rs b/nested/src/editors/list/nav.rs index a2a3b74..00966c0 100644 --- a/nested/src/editors/list/nav.rs +++ b/nested/src/editors/list/nav.rs @@ -43,7 +43,7 @@ impl TreeNav for ListEditor { ListCursorMode::Select => { if let Some(i) = cur.idx { if i < self.data.len() as isize { - let mut sub_cur = self.data.get(i as usize).get_cursor_warp(); + let mut sub_cur = self.data.get(i as usize).read().unwrap().get_cursor_warp(); sub_cur.tree_addr.insert(0, i as isize - self.data.len() as isize); return sub_cur; } else { @@ -75,7 +75,7 @@ impl TreeNav for ListEditor { ListCursorMode::Select => { if let Some(i) = cur.idx { if i < self.data.len() as isize { - let mut sub_cur = self.data.get(i as usize).get_cursor(); + let mut sub_cur = self.data.get(i as usize).read().unwrap().get_cursor(); if sub_cur.tree_addr.len() > 0 { sub_cur.tree_addr.insert(0, i as isize); return sub_cur; @@ -99,7 +99,7 @@ impl TreeNav for ListEditor { let old_cur = self.cursor.get(); if let Some(i) = old_cur.idx { if i < self.data.len() as isize { - self.data.get_mut(i as usize).goto(TreeCursor::none()); + self.data.get_mut(i as usize).write().unwrap().goto(TreeCursor::none()); } } @@ -122,6 +122,7 @@ impl TreeNav for ListEditor { if new_cur.leaf_mode == ListCursorMode::Select && self.data.len() > 0 { self.data .get_mut(idx as usize) + .write().unwrap() .goto(TreeCursor { leaf_mode: ListCursorMode::Select, tree_addr: vec![] @@ -141,6 +142,7 @@ impl TreeNav for ListEditor { self.data .get_mut(idx as usize) + .write().unwrap() .goto(TreeCursor { leaf_mode: new_cur.leaf_mode, tree_addr: new_cur.tree_addr[1..].iter().cloned().collect(), @@ -189,6 +191,7 @@ impl TreeNav for ListEditor { 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 { self.cursor.set(ListCursor { @@ -224,6 +227,7 @@ impl TreeNav for ListEditor { if idx < self.data.len() as isize { self.data .get_mut(idx as usize) + .write().unwrap() .goto(TreeCursor { leaf_mode: cur.leaf_mode, tree_addr: vec![] @@ -247,6 +251,7 @@ impl TreeNav for ListEditor { if cur.tree_addr[0] < self.data.len() as isize { match self.data .get_mut(cur.tree_addr[0] as usize) + .write().unwrap() .goby(direction) { TreeNavResult::Exit => { diff --git a/nested/src/editors/list/pty_editor.rs b/nested/src/editors/list/pty_editor.rs index c6fb3ea..fe1cb57 100644 --- a/nested/src/editors/list/pty_editor.rs +++ b/nested/src/editors/list/pty_editor.rs @@ -61,7 +61,7 @@ impl PTYListStyle { pub fn for_node(node: &mut NestedNode, style: (&str, &str, &str)) { node.view = Some( - Self::new(style, node.depth) + Self::new(style, node.depth.get()) .pty_view( &node.get_edit::().unwrap().read().unwrap() ) @@ -115,10 +115,10 @@ impl PTYListController { } let editor = node.get_edit::().unwrap(); - let controller = Arc::new(RwLock::new(PTYListController::from_editor( editor, split_char, close_char, node.depth ))); + let controller = Arc::new(RwLock::new(PTYListController::from_editor( editor, split_char, close_char, node.depth.get() ))); - node.cmd = Some(controller.clone()); - node.close_char = close_char; + node.cmd.set(Some(controller.clone())); + node.close_char.set(close_char); } pub fn get_data_port(&self) -> OuterViewPort> { @@ -136,6 +136,20 @@ impl PTYListController { pub fn set_depth(&mut self, depth: usize) { self.depth = depth; } + +/* + pub fn handle_node_event(&mut self, c: &NestedNode) -> TreeNavResult { + + } + + pub fn handle_char_event(&mut self, c: &char) -> TreeNavResult { + + } + + pub fn handle_term_event(&mut self, e: &TerminalEvent) -> TreeNavResult { + +} + */ } use r3vi::view::singleton::SingletonView; @@ -161,10 +175,10 @@ impl ObjCommander for PTYListController { if let Some(idx) = cur.idx { match cur.mode { ListCursorMode::Select => { - *e.data.get_mut(idx as usize) = node_view.get(); + *e.data.get_mut(idx as usize) = Arc::new(RwLock::new(node_view.get())); } ListCursorMode::Insert => { - e.data.insert(idx as usize, node_view.get()); + e.data.insert(idx as usize, Arc::new(RwLock::new(node_view.get()))); } } } @@ -212,7 +226,7 @@ impl ObjCommander for PTYListController { if ! remove { */ - e.insert(node); + e.insert(Arc::new(RwLock::new(node))); TreeNavResult::Continue } @@ -310,7 +324,7 @@ impl ObjCommander for PTYListController { match new_edit.send_cmd_obj(cmd_obj.clone()) { TreeNavResult::Continue => { - e.insert(new_edit); + e.insert(Arc::new(RwLock::new(new_edit))); TreeNavResult::Continue } @@ -322,7 +336,7 @@ impl ObjCommander for PTYListController { }, ListCursorMode::Select => { if let Some(mut item) = e.get_item_mut() { - match item.send_cmd_obj(cmd_obj.clone()) { + match item.write().unwrap().send_cmd_obj(cmd_obj.clone()) { TreeNavResult::Continue => { TreeNavResult::Continue } @@ -337,10 +351,9 @@ impl ObjCommander for PTYListController { //eprintln!("close char = {:?}", item.close_char); if Some(c) == self.split_char { - //eprintln!("listlist_split"); e.listlist_split(); TreeNavResult::Continue - } else if Some(c) == item.close_char { + } else if Some(c) == item.read().unwrap().close_char.get() { //eprintln!("listedit: exit from select (close)"); //item.goto(TreeCursor::none()); e.cursor.set(ListCursor { diff --git a/nested/src/tree/node.rs b/nested/src/tree/node.rs index 360cd2d..d2dc585 100644 --- a/nested/src/tree/node.rs +++ b/nested/src/tree/node.rs @@ -16,36 +16,42 @@ use { }; #[derive(Clone)] -pub struct NestedNode { - /// depth - pub depth: usize, - +pub struct NestedNode { /// context - pub ctx: Option>>, - - /// abstract editor - pub editor: Option>>>>, + pub ctx: Option< Arc> >, /// abstract data view - pub data: Option>>, + pub data: Option< Arc> >, /// display view - pub view: Option>, + pub view: Option< OuterViewPort >, /// diagnostics - pub diag: Option>>, + pub diag: Option< OuterViewPort> >, - /// commander - pub close_char: Option, - pub cmd: Option>>, + /// depth + pub depth: SingletonBuffer< usize >, - /// tree navigation - pub tree_nav: Option>>, + /// abstract editor + pub editor: SingletonBuffer< + Option< Arc > + >, + + /// commander & navigation + pub cmd: SingletonBuffer< + Option< Arc> > + >, + pub close_char: SingletonBuffer< + Option< char > + >, + pub tree_nav: SingletonBuffer< + Option< Arc> > + >, } impl ObjCommander for NestedNode { fn send_cmd_obj(&mut self, cmd_obj: Arc>) -> TreeNavResult { - if let Some(cmd) = self.cmd.as_ref() { + if let Some(cmd) = self.cmd.get() { // todo: filter out tree-nav cmds and send them to tree_nav cmd.write().unwrap().send_cmd_obj(cmd_obj) } else { @@ -74,7 +80,7 @@ impl TerminalEditor for NestedNode { fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { let buf = SingletonBuffer::new(event.clone()); - if let (Some(cmd),Some(ctx)) = (self.cmd.as_ref(),self.ctx.as_ref()) { + if let (Some(cmd),Some(ctx)) = (self.cmd.get(),self.ctx.as_ref()) { cmd.write().unwrap().send_cmd_obj( ReprTree::new_leaf( ctx.read().unwrap().type_term_from_str("( TerminalEvent )").unwrap(), @@ -88,7 +94,7 @@ impl TerminalEditor for NestedNode { impl TreeNav for NestedNode { fn get_cursor(&self) -> TreeCursor { - if let Some(tn) = self.tree_nav.as_ref() { + if let Some(tn) = self.tree_nav.get() { tn.read().unwrap().get_cursor() } else { TreeCursor::default() @@ -96,7 +102,7 @@ impl TreeNav for NestedNode { } fn get_addr_view(&self) -> OuterViewPort> { - if let Some(tn) = self.tree_nav.as_ref() { + if let Some(tn) = self.tree_nav.get() { tn.read().unwrap().get_addr_view() } else { OuterViewPort::default() @@ -104,7 +110,7 @@ impl TreeNav for NestedNode { } fn get_mode_view(&self) -> OuterViewPort> { - if let Some(tn) = self.tree_nav.as_ref() { + if let Some(tn) = self.tree_nav.get() { tn.read().unwrap().get_mode_view() } else { OuterViewPort::default() @@ -112,7 +118,7 @@ impl TreeNav for NestedNode { } fn get_cursor_warp(&self) -> TreeCursor { - if let Some(tn) = self.tree_nav.as_ref() { + if let Some(tn) = self.tree_nav.get() { tn.read().unwrap().get_cursor_warp() } else { TreeCursor::default() @@ -124,7 +130,7 @@ impl TreeNav for NestedNode { } fn goby(&mut self, direction: Vector2) -> TreeNavResult { - if let Some(tn) = self.tree_nav.as_ref() { + if let Some(tn) = self.tree_nav.get() { tn.write().unwrap().goby(direction) } else { TreeNavResult::Exit @@ -132,7 +138,7 @@ impl TreeNav for NestedNode { } fn goto(&mut self, new_cursor: TreeCursor) -> TreeNavResult { - if let Some(tn) = self.tree_nav.as_ref() { + if let Some(tn) = self.tree_nav.get() { tn.write().unwrap().goto(new_cursor) } else { TreeNavResult::Exit @@ -149,15 +155,15 @@ impl Diagnostics for NestedNode { impl NestedNode { pub fn new(depth: usize) -> Self { NestedNode { - depth, ctx: None, data: None, - editor: None, view: None, diag: None, - cmd: None, - close_char: None, - tree_nav: None + depth: SingletonBuffer::new(depth), + editor: SingletonBuffer::new(None), + cmd: SingletonBuffer::new(None), + close_char: SingletonBuffer::new(None), + tree_nav: SingletonBuffer::new(None) } } @@ -197,7 +203,7 @@ impl NestedNode { } pub fn set_editor(mut self, editor: Arc) -> Self { - self.editor = Some(SingletonBuffer::new(Some(editor)).get_port()); + self.editor.set(Some(editor)); self } @@ -207,12 +213,12 @@ impl NestedNode { } pub fn set_cmd(mut self, cmd: Arc>) -> Self { - self.cmd = Some(cmd); + self.cmd.set(Some(cmd)); self } pub fn set_nav(mut self, nav: Arc>) -> Self { - self.tree_nav = Some(nav); + self.tree_nav.set(Some(nav)); self } @@ -268,8 +274,8 @@ impl NestedNode { } */ pub fn get_edit(&self) -> Option>> { - if let Some(edit) = self.editor.clone() { - if let Ok(edit) = edit.get_view().unwrap().get().unwrap().downcast::>() { + if let Some(edit) = self.editor.get() { + if let Ok(edit) = edit.downcast::>() { Some(edit) } else { None diff --git a/nested/src/type_system/context.rs b/nested/src/type_system/context.rs index 0edf8ae..0f57836 100644 --- a/nested/src/type_system/context.rs +++ b/nested/src/type_system/context.rs @@ -189,7 +189,7 @@ impl Context { self.add_morphism(morphism_pattern, Arc::new(move |node, dst_type| { let ctx = node.ctx.clone().unwrap(); let depth = node.depth; - mk_editor(ctx, dst_type, depth) + mk_editor(ctx, dst_type, depth.get()) })); } diff --git a/nested/src/type_system/editor.rs b/nested/src/type_system/editor.rs index d19312a..6c27701 100644 --- a/nested/src/type_system/editor.rs +++ b/nested/src/type_system/editor.rs @@ -33,7 +33,7 @@ pub struct TypeTermEditor { ctx: Arc>, state: State, - cur_node: SingletonBuffer + cur_node: SingletonBuffer< NestedNode > } impl TypeTermEditor { @@ -64,17 +64,15 @@ impl TypeTermEditor { Arc::new( |mut node, _dst_type:_| { //eprintln!("morphism to typeterm"); - PTYListController::for_node( &mut node, Some(' '), None ); PTYListStyle::for_node( &mut node, ("","","") ); - - let mut new_node = TypeTermEditor::with_node( node.ctx.clone().unwrap(), node.depth, node.clone(), State::Any ); + let mut new_node = TypeTermEditor::with_node( node.ctx.clone().unwrap(), node.depth.get(), node.clone(), State::Any ); let item_nodes = node.get_edit::().clone().unwrap(); let item_nodes = item_nodes.read().unwrap(); for i in 0..item_nodes.data.len() { - if let Some(x) = item_nodes.data.get(i).data { + if let Some(x) = &item_nodes.data.get(i).read().unwrap().data { //eprintln!("item with {:?}", x); //let c = x.read().unwrap().get_view::>().unwrap().get(); new_node.send_cmd_obj( @@ -99,7 +97,6 @@ impl TypeTermEditor { let mut node = match new_state { State::Char => { let mut node = Context::make_node( &self.ctx, (&self.ctx, "( Char )").into(), 0 ).unwrap(); - let mut grid = r3vi::buffer::index_hashmap::IndexBuffer::new(); grid.insert_iter( @@ -110,7 +107,7 @@ impl TypeTermEditor { ] ); - node.close_char = Some('\''); + node.close_char.set(Some('\'')); node.view = Some( grid.get_port() .flatten() @@ -153,21 +150,6 @@ impl TypeTermEditor { cur_node: SingletonBuffer::new(node) }; - let ed_view = editor.cur_node - .get_port() - .map( - |node| - match node.editor { - Some(e) => { - e - }, - None => { - r3vi::buffer::singleton::SingletonBuffer::new(None).get_port() - } - } - ) - .flatten(); - let view = editor.cur_node .get_port() .map( @@ -190,12 +172,10 @@ impl TypeTermEditor { let mut node = NestedNode::new(depth) .set_ctx(ctx) - .set_view( view ) + .set_view(view) .set_nav(editor.clone()) - .set_cmd(editor.clone()); - - node.editor = Some(ed_view); - //node.editor.unwrap().get_view().unwrap().get().unwrap() + .set_cmd(editor.clone()) + .set_editor(editor.clone()); node } @@ -280,7 +260,7 @@ impl ObjCommander for TypeTermEditor { } } } - + State::List => { match self.cur_node.get_mut().send_cmd_obj( co ) { TreeNavResult::Continue => { @@ -308,7 +288,6 @@ impl ObjCommander for TypeTermEditor { TreeNavResult::Exit } } - } } } diff --git a/nested/src/type_system/make_editor.rs b/nested/src/type_system/make_editor.rs index 748ea29..f340e80 100644 --- a/nested/src/type_system/make_editor.rs +++ b/nested/src/type_system/make_editor.rs @@ -192,8 +192,8 @@ pub fn init_math_ctx(parent: Arc>) -> Arc> { ctx.write().unwrap().add_morphism(pattern, Arc::new( |mut node, dst_type| { - let depth = node.depth; - let editor = node.editor.clone().unwrap().get_view().unwrap().get().unwrap().downcast::>().unwrap(); + let depth = node.depth.get(); + let editor = node.editor.get().unwrap().downcast::>().unwrap(); // todo: check src_type parameter to be ( Digit radix )