some work on repr tree example
This commit is contained in:
parent
97a5b580df
commit
47a35f22b7
6 changed files with 170 additions and 151 deletions
|
@ -14,6 +14,7 @@ use {
|
||||||
nested_tty::{
|
nested_tty::{
|
||||||
DisplaySegment, TTYApplication,
|
DisplaySegment, TTYApplication,
|
||||||
TerminalCompositor, TerminalStyle, TerminalView,
|
TerminalCompositor, TerminalStyle, TerminalView,
|
||||||
|
TerminalAtom
|
||||||
},
|
},
|
||||||
r3vi::{
|
r3vi::{
|
||||||
buffer::{singleton::*, vec::*},
|
buffer::{singleton::*, vec::*},
|
||||||
|
@ -21,112 +22,126 @@ use {
|
||||||
std::sync::{Arc, RwLock},
|
std::sync::{Arc, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
struct ParseDigit { radix: u32 }
|
|
||||||
impl Morphism for ParseDigit {
|
|
||||||
fn new(
|
|
||||||
ctx: &Arc<RwLock<Context>>
|
|
||||||
) -> Self {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setup_projection(&self, repr_tree: Arc<RwLock<ReprTree>>) {
|
|
||||||
if let Some( char_view ) = repr_tree.get_out(Context::parse(&ctx, "Char~")) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get_morphism( ) -> Morphism {
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
#[async_std::main]
|
#[async_std::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
/* setup context & create Editor-Tree
|
/* setup context & create Editor-Tree
|
||||||
*/
|
*/
|
||||||
let ctx = Arc::new(RwLock::new(Context::new()));
|
let ctx = Arc::new(RwLock::new(Context::new()));
|
||||||
|
|
||||||
/* Create a Char-Node with editor & view
|
/* structure of Repr-Tree
|
||||||
|
*
|
||||||
|
* === Repr-Tree ===
|
||||||
|
*
|
||||||
|
* <Digit 10>
|
||||||
|
* / | \
|
||||||
|
* / | \
|
||||||
|
* / | \
|
||||||
|
* u32 [ EditTree ] Char
|
||||||
|
* - Editor \
|
||||||
|
* - Display [ EditTree ]
|
||||||
|
* / | \ - Editor
|
||||||
|
* / | \ - Display
|
||||||
|
* TTY PixelBuf SDF / | \
|
||||||
|
* / | \
|
||||||
|
* TTY PixelBuf SDF
|
||||||
|
*/
|
||||||
|
let rt_digit = ReprTree::new_arc( Context::parse(&ctx, "<Digit 10>") );
|
||||||
|
let port_char = r3vi::view::ViewPort::<dyn r3vi::view::singleton::SingletonView<Item = char>>::new();
|
||||||
|
let port_u32 = r3vi::view::ViewPort::<dyn r3vi::view::singleton::SingletonView<Item = u32>>::new();
|
||||||
|
let port_edit = r3vi::view::ViewPort::<dyn r3vi::view::singleton::SingletonView<Item = NestedNode>>::new();
|
||||||
|
let port_char_edit = r3vi::view::ViewPort::<dyn r3vi::view::singleton::SingletonView<Item = NestedNode>>::new();
|
||||||
|
|
||||||
|
rt_digit.write().unwrap()
|
||||||
|
.insert_leaf(
|
||||||
|
vec![ Context::parse(&ctx, "Char") ].into_iter(),
|
||||||
|
port_char.outer().into()
|
||||||
|
);
|
||||||
|
|
||||||
|
rt_digit.write().unwrap()
|
||||||
|
.insert_leaf(
|
||||||
|
vec![ Context::parse(&ctx, "Char"), Context::parse(&ctx, "EditTree") ].into_iter(),
|
||||||
|
port_char_edit.outer().into()
|
||||||
|
);
|
||||||
|
|
||||||
|
rt_digit.write().unwrap()
|
||||||
|
.insert_leaf(
|
||||||
|
vec![ Context::parse(&ctx, "EditTree") ].into_iter(),
|
||||||
|
port_edit.outer().into()
|
||||||
|
);
|
||||||
|
|
||||||
|
rt_digit.write().unwrap()
|
||||||
|
.insert_leaf(
|
||||||
|
vec![ Context::parse(&ctx, "u32") ].into_iter(),
|
||||||
|
port_u32.outer().into()
|
||||||
|
);
|
||||||
|
|
||||||
|
/* setup projections between representations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let mut char_obj = ReprTree::make_leaf(
|
// created by Char ==> Char~EditTree
|
||||||
Context::parse(&ctx, "Char"),
|
let mut edittree_char =
|
||||||
SingletonBuffer::new('X').get_port().into()
|
nested::editors::char::CharEditor::new_edit_tree(
|
||||||
);
|
ctx.clone(),
|
||||||
|
r3vi::buffer::singleton::SingletonBuffer::<usize>::new(0).get_port()
|
||||||
|
);
|
||||||
|
|
||||||
|
node_edit_char = nested_tty::editors::edittree_make_char_view( edittree_char );
|
||||||
|
let mut edit_char = node_edit_char.get_edit::< nested::editors::char::CharEditor >().unwrap();
|
||||||
|
port_char.attach_to( edit_char.read().unwrap().get_port() );
|
||||||
|
|
||||||
|
let buf_edit_char = r3vi::buffer::singleton::SingletonBuffer::new( node_edit_char.clone() );
|
||||||
|
port_char_edit.attach_to( buf_edit_char.get_port() );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// created by <Digit 10> ==> <Digit 10>~EditTree
|
||||||
|
let mut node_edit_digit =
|
||||||
|
nested::editors::integer::DigitEditor::new(
|
||||||
|
ctx.clone(),
|
||||||
|
16
|
||||||
|
).into_node(
|
||||||
|
r3vi::buffer::singleton::SingletonBuffer::<usize>::new(0).get_port()
|
||||||
|
);
|
||||||
|
|
||||||
|
node_edit_digit = nested_tty::editors::edittree_make_digit_view( node_edit_digit );
|
||||||
|
let mut edit_digit = node_edit_digit.get_edit::< nested::editors::integer::DigitEditor >().unwrap();
|
||||||
|
|
||||||
|
// created by <Digit 10> ==> <Digit 10>~U32
|
||||||
|
port_u32.attach_to( port_char.outer().map(|c| c.to_digit(16).unwrap_or(0)) );
|
||||||
|
// port_u32.attach_to( edit_digit.read().unwrap().get_data_port().map(|d| d.unwrap_or(0)) );
|
||||||
|
|
||||||
|
let port_proj_u32_to_char = port_u32.outer().map(|val| char::from_digit(val, 16).unwrap_or('?') );
|
||||||
|
|
||||||
|
let buf_edit_digit = r3vi::buffer::singleton::SingletonBuffer::new( node_edit_digit );
|
||||||
|
port_edit.attach_to( buf_edit_digit.get_port() );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
char_obj.insert_branch(
|
ctx.write().unwrap()
|
||||||
Context::parse(&ctx, "EditTree"),
|
.morphisms
|
||||||
SingletonBuffer::new(
|
.add_morphism(
|
||||||
NestedNode::new()
|
MorphismType {
|
||||||
|
src_type: Context::parse(&ctx, "Char"),
|
||||||
|
dst_type: Context::parse(&ctx, "Char~EditTree")
|
||||||
|
},
|
||||||
|
|
||||||
|
|rt, _σ| {
|
||||||
|
rt.write().unwrap()
|
||||||
|
.insert_branch(
|
||||||
|
Context::parse(&ctx, "")
|
||||||
|
);
|
||||||
|
}
|
||||||
)
|
)
|
||||||
);
|
|
||||||
|
|
||||||
let mut vec_obj = ReprTree::make_leaf(
|
|
||||||
Context::parse(&ctx, "<Vec Char>"),
|
|
||||||
VecBuffer::new(vec!['a', 'b', 'c']).get_port().into()
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut char_edit = Context::new_edit_tree(
|
|
||||||
&ctx,
|
|
||||||
// node type
|
|
||||||
Context::parse(&ctx, "Char"),
|
|
||||||
// depth
|
|
||||||
SingletonBuffer::new(0).get_port(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
*/
|
*/
|
||||||
// add a display view to the node
|
|
||||||
//node1 = nested_tty::editors::node_make_tty_view(node1);
|
|
||||||
|
|
||||||
/* Create a <List Char>-Node with editor & view
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
let mut node2 = Context::make_node(
|
|
||||||
&ctx,
|
|
||||||
// node type
|
|
||||||
Context::parse(&ctx, "<List Char>"),
|
|
||||||
// depth
|
|
||||||
SingletonBuffer::new(0).get_port(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
*/
|
|
||||||
// add a display view to the node
|
|
||||||
//node2 = nested_tty::editors::node_make_tty_view(node2);
|
|
||||||
|
|
||||||
/* Create a <List Char>-Node with editor & view
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
let mut node3 = Context::make_node(
|
|
||||||
&ctx,
|
|
||||||
// node type
|
|
||||||
Context::parse(&ctx, "<List <List Char>>"),
|
|
||||||
// depth
|
|
||||||
SingletonBuffer::new(0).get_port(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
*/
|
|
||||||
// add a display view to the node
|
|
||||||
//node3 = nested_tty::editors::node_make_tty_view(node3);
|
|
||||||
|
|
||||||
/* setup terminal
|
/* setup terminal
|
||||||
*/
|
*/
|
||||||
let app = TTYApplication::new({
|
let app = TTYApplication::new({
|
||||||
/* event handler
|
/* event handler
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let ctx = ctx.clone();
|
let ctx = ctx.clone();
|
||||||
// let node1 = node1.clone();
|
let node1 = buf_edit_digit.clone();
|
||||||
// let node2 = node2.clone();
|
|
||||||
// let node3 = node3.clone();
|
|
||||||
move |ev| {
|
move |ev| {
|
||||||
// let mut node1 = node1.clone();
|
node1.get().send_cmd_obj(ev.to_repr_tree(&ctx));
|
||||||
// let mut node2 = node2.clone();
|
|
||||||
// let mut node3 = node3.clone();
|
|
||||||
// node1.send_cmd_obj(ev.to_repr_tree(&ctx));
|
|
||||||
// node2.send_cmd_obj(ev.to_repr_tree(&ctx));
|
|
||||||
// node3.send_cmd_obj(ev.to_repr_tree(&ctx));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -142,6 +157,7 @@ async fn main() {
|
||||||
})
|
})
|
||||||
.offset(Vector2::new(5, 0)),
|
.offset(Vector2::new(5, 0)),
|
||||||
);
|
);
|
||||||
|
compositor.write().unwrap().push( buf_edit_digit.get().display_view().offset(Vector2::new(0,2)) );
|
||||||
|
|
||||||
/* let label = ctx.read().unwrap().type_term_to_str(&node1.get_type());
|
/* let label = ctx.read().unwrap().type_term_to_str(&node1.get_type());
|
||||||
compositor
|
compositor
|
||||||
|
@ -153,30 +169,6 @@ async fn main() {
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.push(node1.display_view().offset(Vector2::new(15, 2)));
|
.push(node1.display_view().offset(Vector2::new(15, 2)));
|
||||||
*/
|
|
||||||
/*
|
|
||||||
let label2 = ctx.read().unwrap().type_term_to_str(&node2.get_type());
|
|
||||||
compositor
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.push(nested_tty::make_label(&label2).offset(Vector2::new(0, 3)));
|
|
||||||
|
|
||||||
compositor
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.push(node2.display_view().offset(Vector2::new(15, 3)));
|
|
||||||
|
|
||||||
|
|
||||||
let label3 = ctx.read().unwrap().type_term_to_str(&node3.get_type());
|
|
||||||
compositor
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.push(nested_tty::make_label(&label3).offset(Vector2::new(0, 4)));
|
|
||||||
|
|
||||||
compositor
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.push(node3.display_view().offset(Vector2::new(25, 4)));
|
|
||||||
*/
|
*/
|
||||||
/* write the changes in the view of `term_port` to the terminal
|
/* write the changes in the view of `term_port` to the terminal
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -71,19 +71,16 @@ impl CharEditor {
|
||||||
self.get_port().get_view().unwrap().get()
|
self.get_port().get_view().unwrap().get()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_node(ctx0: Arc<RwLock<Context>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode {
|
pub fn new_edit_tree(
|
||||||
|
ctx0: Arc<RwLock<Context>>,
|
||||||
|
depth: OuterViewPort<dyn SingletonView<Item = usize>>
|
||||||
|
) -> NestedNode {
|
||||||
let data = SingletonBuffer::new('\0');
|
let data = SingletonBuffer::new('\0');
|
||||||
let ctx = ctx0.clone();
|
let ctx = ctx0.clone();
|
||||||
let editor = Arc::new(RwLock::new(CharEditor{ ctx, data: data.clone() }));
|
let editor = Arc::new(RwLock::new(CharEditor{ ctx, data: data.clone() }));
|
||||||
|
|
||||||
NestedNode::new(
|
NestedNode::new(
|
||||||
ctx0.clone(),
|
ctx0.clone(),
|
||||||
/*
|
|
||||||
ReprTree::new_leaf(
|
|
||||||
ctx0.read().unwrap().type_term_from_str("Char").unwrap(),
|
|
||||||
data.get_port().into()
|
|
||||||
),
|
|
||||||
*/
|
|
||||||
depth
|
depth
|
||||||
)
|
)
|
||||||
.set_cmd( editor.clone() )
|
.set_cmd( editor.clone() )
|
||||||
|
|
|
@ -49,9 +49,7 @@ impl ObjCommander for DigitEditor {
|
||||||
/* in case the character c is not in the range of digit-chars,
|
/* in case the character c is not in the range of digit-chars,
|
||||||
add a message to the diagnostics view
|
add a message to the diagnostics view
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
let message = IndexBuffer::from_iter(vec![
|
let message = IndexBuffer::from_iter(vec![
|
||||||
(Point2::new(1, 0), make_label("invalid digit '")),
|
(Point2::new(1, 0), make_label("invalid digit '")),
|
||||||
(Point2::new(2, 0), make_label(&format!("{}", c))
|
(Point2::new(2, 0), make_label(&format!("{}", c))
|
||||||
|
@ -89,34 +87,33 @@ impl DigitEditor {
|
||||||
let ed = editor.write().unwrap();
|
let ed = editor.write().unwrap();
|
||||||
let r = ed.radix;
|
let r = ed.radix;
|
||||||
|
|
||||||
NestedNode::new(ed.ctx.clone(), /*data,*/ depth)
|
NestedNode::new(ed.ctx.clone(), depth)
|
||||||
|
.set_editor(editor.clone())
|
||||||
.set_cmd(editor.clone())
|
.set_cmd(editor.clone())
|
||||||
/*
|
|
||||||
.set_view(
|
|
||||||
ed.data
|
|
||||||
.get_port()
|
|
||||||
.map(move |c| {
|
|
||||||
TerminalAtom::new(
|
|
||||||
c.unwrap_or('?'),
|
|
||||||
if c.unwrap_or('?').to_digit(r).is_some() {
|
|
||||||
TerminalStyle::fg_color((90, 160, 90))
|
|
||||||
} else {
|
|
||||||
//TerminalStyle::bg_color((90, 10, 10))
|
|
||||||
TerminalStyle::fg_color((200, 40, 40))
|
|
||||||
},
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.to_grid()
|
|
||||||
)
|
|
||||||
.set_diag(
|
.set_diag(
|
||||||
ed.msg.get_port().to_sequence()
|
ed.msg.get_port().to_sequence()
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn attach_to(&mut self, source: OuterViewPort<dyn SingletonView<Item = u32>>) {
|
||||||
|
/*
|
||||||
|
source.add_observer(
|
||||||
|
Arc::new(NotifyFnObserver::new(|_msg| {
|
||||||
|
self.data.set( source.get() )
|
||||||
|
}))
|
||||||
|
);
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_data_port(&self) -> OuterViewPort<dyn SingletonView<Item = Option<u32>>> {
|
pub fn get_data_port(&self) -> OuterViewPort<dyn SingletonView<Item = Result<u32, char>>> {
|
||||||
let radix = self.radix;
|
let radix = self.radix;
|
||||||
self.data.get_port().map(move |c| c?.to_digit(radix))
|
self.data.get_port().map(move |c|
|
||||||
|
if let Some(d) = c.unwrap_or('?').to_digit(radix) {
|
||||||
|
Ok(d)
|
||||||
|
} else {
|
||||||
|
Err(c.unwrap_or('?'))
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_type(&self) -> TypeTerm {
|
pub fn get_type(&self) -> TypeTerm {
|
||||||
|
@ -134,7 +131,6 @@ impl DigitEditor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct PosIntEditor {
|
pub struct PosIntEditor {
|
||||||
radix: u32,
|
radix: u32,
|
||||||
digits: NestedNode,
|
digits: NestedNode,
|
||||||
|
|
|
@ -4,7 +4,7 @@ pub mod list;
|
||||||
//pub mod sum;
|
//pub mod sum;
|
||||||
|
|
||||||
pub mod char;
|
pub mod char;
|
||||||
//pub mod integer;
|
pub mod integer;
|
||||||
//pub mod typeterm;
|
//pub mod typeterm;
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,3 +24,4 @@ pub trait ObjCommander {
|
||||||
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult;
|
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ pub use {
|
||||||
};
|
};
|
||||||
|
|
||||||
use {
|
use {
|
||||||
r3vi::view::{AnyOuterViewPort, OuterViewPort, View},
|
r3vi::view::{AnyOuterViewPort, OuterViewPort, View, singleton::*},
|
||||||
laddertypes::{TypeTerm},
|
laddertypes::{TypeTerm},
|
||||||
std::{
|
std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
@ -100,6 +100,13 @@ impl ReprTree {
|
||||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
|
||||||
|
pub fn view_char(&self) -> OuterViewPort<dyn SingletonView<Item = char>> {
|
||||||
|
self.get_port::<dyn SingletonView<Item = char>>().expect("no char-view available")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn view_u64(&self) -> OuterViewPort<dyn SingletonView<Item = u64>> {
|
||||||
|
self.get_port::<dyn SingletonView<Item = u64>>().expect("no u64-view available")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_port<V: View + ?Sized + 'static>(&self) -> Option<OuterViewPort<V>>
|
pub fn get_port<V: View + ?Sized + 'static>(&self) -> Option<OuterViewPort<V>>
|
||||||
where
|
where
|
||||||
|
|
|
@ -13,22 +13,22 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
make_label,
|
make_label,
|
||||||
DisplaySegment,
|
DisplaySegment,
|
||||||
atom::TerminalAtom
|
atom::{TerminalAtom, TerminalStyle}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/*
|
|
||||||
pub fn node_make_char_view(
|
pub fn edittree_make_char_view(
|
||||||
node: NestedNode
|
node: NestedNode
|
||||||
) -> NestedNode {
|
) -> NestedNode {
|
||||||
node.disp.view
|
node.disp.view
|
||||||
.write().unwrap()
|
.write().unwrap()
|
||||||
.insert_branch(ReprTree::new_leaf(
|
.insert_branch(ReprTree::new_leaf(
|
||||||
Context::parse(&node.ctx, "TerminalView"),
|
Context::parse(&node.ctx, "TerminalView"),
|
||||||
node.data
|
node.get_edit::< nested::editors::char::CharEditor >()
|
||||||
|
.unwrap()
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get_port::<dyn SingletonView<Item = char>>()
|
.get_port()
|
||||||
.expect("unable to get Char-view")
|
|
||||||
.map(move |c| TerminalAtom::from(if c == '\0' { ' ' } else { c }))
|
.map(move |c| TerminalAtom::from(if c == '\0' { ' ' } else { c }))
|
||||||
.to_grid()
|
.to_grid()
|
||||||
.into(),
|
.into(),
|
||||||
|
@ -37,6 +37,32 @@ pub fn node_make_char_view(
|
||||||
node
|
node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn edittree_make_digit_view(
|
||||||
|
node: NestedNode
|
||||||
|
) -> NestedNode {
|
||||||
|
node.disp.view
|
||||||
|
.write().unwrap()
|
||||||
|
.insert_branch(ReprTree::new_leaf(
|
||||||
|
Context::parse(&node.ctx, "TerminalView"),
|
||||||
|
node.get_edit::< nested::editors::integer::DigitEditor >()
|
||||||
|
.unwrap()
|
||||||
|
.read()
|
||||||
|
.unwrap()
|
||||||
|
.get_data_port()
|
||||||
|
.map(move |digit|
|
||||||
|
match digit {
|
||||||
|
Ok(digit) => TerminalAtom::new( char::from_digit(digit, 16).unwrap_or('?'), TerminalStyle::fg_color((220, 220, 0)) ),
|
||||||
|
Err(c) => TerminalAtom::new( c, TerminalStyle::fg_color((220, 0, 0)) )
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.to_grid()
|
||||||
|
.into(),
|
||||||
|
));
|
||||||
|
|
||||||
|
node
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
pub fn node_make_seq_view(
|
pub fn node_make_seq_view(
|
||||||
mut node: NestedNode
|
mut node: NestedNode
|
||||||
) -> NestedNode {
|
) -> NestedNode {
|
||||||
|
|
Loading…
Reference in a new issue