refactor ReprTree

- ReprLeaf with In- & Out-Ports
- Optional Buffers
This commit is contained in:
Michael Sippel 2024-03-15 18:54:25 +01:00
parent 03dc9f1133
commit 658f5c1000
Signed by: senvas
GPG key ID: F96CF119C34B64A6
17 changed files with 946 additions and 242 deletions

View file

@ -8,17 +8,19 @@ use {
cgmath::Vector2, cgmath::Vector2,
nested::{ nested::{
editors::ObjCommander, editors::ObjCommander,
repr_tree::{Context, ReprTree}, repr_tree::{Context, ReprTree, ReprTreeExt},
edit_tree::{EditTree} edit_tree::{EditTree}
}, },
nested_tty::{ nested_tty::{
DisplaySegment, TTYApplication, DisplaySegment, TTYApplication,
TerminalCompositor, TerminalStyle, TerminalView, TerminalCompositor, TerminalStyle, TerminalView,
TerminalAtom TerminalAtom, TerminalEvent
}, },
r3vi::{ r3vi::{
buffer::{singleton::*, vec::*}, buffer::{singleton::*, vec::*},
view::{port::UpdateTask}
}, },
// termion::{},
std::sync::{Arc, RwLock}, std::sync::{Arc, RwLock},
}; };
@ -48,8 +50,8 @@ async fn main() {
// It provides the necessary bridge to the rendering- & input-backend. // It provides the necessary bridge to the rendering- & input-backend.
ctx.write().unwrap().set_edittree_hook( ctx.write().unwrap().set_edittree_hook(
Arc::new( Arc::new(
move |et: Arc<RwLock<EditTree>>, t: laddertypes::TypeTerm| { move |et: &mut EditTree, t: laddertypes::TypeTerm| {
let mut et = et.write().unwrap(); // let mut et = et.write().unwrap();
if let Ok(σ) = laddertypes::unify(&t, &char_type.clone()) { if let Ok(σ) = laddertypes::unify(&t, &char_type.clone()) {
*et = nested_tty::editors::edittree_make_char_view(et.clone()); *et = nested_tty::editors::edittree_make_char_view(et.clone());
@ -95,31 +97,49 @@ async fn main() {
* / | \ * / | \
* TTY PixelBuf SDF * TTY PixelBuf SDF
*/ */
let rt_digit = ReprTree::new_arc( Context::parse(&ctx, "<Digit 16>") ); let mut rt_digit = ReprTree::new_arc( Context::parse(&ctx, "<Digit 16>") );
/* add initial representation /* add initial representation
* <Digit 16> ~ Char * <Digit 16> ~ Char
*/ */
rt_digit.write().unwrap() rt_digit.insert_leaf(
.insert_leaf( Context::parse(&ctx, "Char"),
vec![ Context::parse(&ctx, "Char") ].into_iter(), nested::repr_tree::ReprLeaf::from_singleton_buffer( SingletonBuffer::new('5') )
SingletonBuffer::new('4').get_port().into() );
);
/* furthermore, setup projections to and from u8 value,
* this synchronizes the buffers
*/
ctx.read().unwrap().morphisms.apply_morphism(
rt_digit.clone(),
&Context::parse(&ctx, "<Digit 16>~Char"),
&Context::parse(&ctx, "<Digit 16>~_256~machine::UInt8")
);
/* setup TTY-Display for DigitEditor /* setup TTY-Display for DigitEditor
*
* `setup_edittree` will setup the projection
* Char -> Char~EditTree
* and call the hook defined above with `set_edittree_hook()`
*
*/ */
let edittree_digit = ctx.read().unwrap() let edittree_digit = ctx.read().unwrap()
.setup_edittree( .setup_edittree(
rt_digit rt_digit.clone(),
.read().unwrap() r3vi::buffer::singleton::SingletonBuffer::new(0).get_port()
.descend( Context::parse(&ctx, "Char") ).unwrap() );
.clone(),
r3vi::buffer::singleton::SingletonBuffer::new(0).get_port()); let mut digit_u8_buffer = rt_digit
.descend(Context::parse(&ctx, "_256~machine::UInt8")).unwrap()
.singleton_buffer::<u8>();
//--- //---
let rt_string = ReprTree::new_arc( Context::parse(&ctx, "<List <Digit 10>>") ); let rt_string = ReprTree::new_arc( Context::parse(&ctx, "<List Char>") );
let edittree = ctx.read().unwrap()
.setup_edittree(rt_string.clone(), r3vi::buffer::singleton::SingletonBuffer::new(0).get_port()); let edittree_list = ctx.read().unwrap()
.setup_edittree(
rt_string.clone(),
r3vi::buffer::singleton::SingletonBuffer::new(0).get_port());
/* setup terminal /* setup terminal
*/ */
@ -127,9 +147,22 @@ async fn main() {
/* event handler /* event handler
*/ */
let ctx = ctx.clone(); let ctx = ctx.clone();
let et1 = edittree.clone(); let mut editors = Vec::new();
editors.push(edittree_digit.clone());
editors.push(edittree_list.clone());
let edit_select = Arc::new(RwLock::new(0));
move |ev| { move |ev| {
et1.write().unwrap().send_cmd_obj(ev.to_repr_tree(&ctx)); match ev {
TerminalEvent::Input(termion::event::Event::Key(termion::event::Key::Char('\t'))) => {
let mut i = edit_select.write().unwrap();
*i = (*i + 1) % editors.len();
}
_ => {
let i = edit_select.read().unwrap();
editors[*i].get().send_cmd_obj(ev.to_repr_tree(&ctx));
}
}
} }
}); });
@ -150,25 +183,37 @@ async fn main() {
); );
comp.push( comp.push(
edittree_digit.read().unwrap().display_view() edittree_digit.get().display_view()
.offset(Vector2::new(0,2)) .offset(Vector2::new(2,2))
); );
let label_str = ctx.read().unwrap().type_term_to_str(&rt_digit.read().unwrap().get_type()); let label_str = ctx.read().unwrap().type_term_to_str(&rt_digit.read().unwrap().get_type());
comp.push( comp.push(
nested_tty::make_label(&label_str) nested_tty::make_label(&label_str)
.map_item(|_pt,atom| atom.add_style_front(TerminalStyle::fg_color((90,90,90))))
.offset(Vector2::new(0, 1)) .offset(Vector2::new(0, 1))
); );
comp.push( comp.push(
edittree.read().unwrap().display_view() digit_u8_buffer.get_port().map(
.offset(Vector2::new(0,4)) |d| nested_tty::make_label(&format!("Digit={}", d))
)
.to_grid()
.flatten()
.offset(Vector2::new(2,3))
);
comp.push(
edittree_list.get().display_view()
.offset(Vector2::new(2,6))
); );
let label_str = ctx.read().unwrap().type_term_to_str(&rt_string.read().unwrap().get_type()); let label_str = ctx.read().unwrap().type_term_to_str(&rt_string.read().unwrap().get_type());
comp.push( comp.push(
nested_tty::make_label(&label_str) nested_tty::make_label(&label_str)
.offset(Vector2::new(0, 3)) .map_item(|_pt, atom| atom.add_style_front(TerminalStyle::fg_color((90,90,90))))
.offset(Vector2::new(0, 5))
); );
} }

View file

@ -3,12 +3,13 @@ use {
view::{ view::{
OuterViewPort, OuterViewPort,
singleton::*, singleton::*,
port::UpdateTask
}, },
buffer::singleton::* buffer::singleton::*
}, },
laddertypes::{TypeTerm}, laddertypes::{TypeTerm},
crate::{ crate::{
repr_tree::{Context, ReprTree}, repr_tree::{Context, ReprTree, ReprTreeExt},
edit_tree::{EditTree, TreeNavResult}, edit_tree::{EditTree, TreeNavResult},
editors::ObjCommander, editors::ObjCommander,
}, },
@ -17,7 +18,6 @@ use {
}; };
pub fn init_ctx( ctx: Arc<RwLock<Context>> ) { pub fn init_ctx( ctx: Arc<RwLock<Context>> ) {
let morphtype = let morphtype =
crate::repr_tree::MorphismType { crate::repr_tree::MorphismType {
src_type: Context::parse(&ctx, "Char"), src_type: Context::parse(&ctx, "Char"),
@ -37,19 +37,25 @@ pub fn init_ctx( ctx: Arc<RwLock<Context>> ) {
/* Create EditTree object /* Create EditTree object
*/ */
let mut edittree_char = CharEditor::new_edit_tree( rt.view_char().0.update();
let char_buf = rt.write().unwrap().singleton_buffer::<char>().unwrap();
eprintln!("make edittree: char val = {}", char_buf.get());
let mut edittree = CharEditor::new_edit_tree(
ctx.clone(), ctx.clone(),
SingletonBuffer::new('>'), char_buf,
r3vi::buffer::singleton::SingletonBuffer::<usize>::new(0).get_port() r3vi::buffer::singleton::SingletonBuffer::<usize>::new(0).get_port()
); );
/* Insert EditTree into ReprTree eprintln!("insert Char~EditTree");
*/ rt.write().unwrap()
let mut rt = rt.write().unwrap(); .insert_branch(
rt.insert_leaf( ReprTree::from_singleton_buffer(
vec![ Context::parse(&ctx, "EditTree") ].into_iter(), Context::parse(&ctx, "EditTree"),
SingletonBuffer::new( Arc::new(RwLock::new( edittree_char )) ).get_port().into() SingletonBuffer::new(edittree)
); )
);
} }
} }
); );
@ -105,7 +111,7 @@ impl CharEditor {
data: SingletonBuffer<char>, data: SingletonBuffer<char>,
depth: OuterViewPort<dyn SingletonView<Item = usize>> depth: OuterViewPort<dyn SingletonView<Item = usize>>
) -> EditTree { ) -> EditTree {
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() }));

View file

@ -0,0 +1,52 @@
use {
r3vi::view::singleton::SingletonView,
crate::{
repr_tree::{ReprTree, Context},
edit_tree::{TreeNav, TreeNavResult},
editors::{ObjCommander, digit::DigitEditor}
},
std::sync::{Arc, RwLock}
};
impl ObjCommander for DigitEditor {
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
let cmd_obj = cmd_obj.read().unwrap();
let cmd_type = cmd_obj.get_type().clone();
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();
self.msg.clear();
if self.ctx.read().unwrap().meta_chars.contains(&c) {
return TreeNavResult::Exit;
} else if c.to_digit(self.radix).is_none() {
/* in case the character c is not in the range of digit-chars,
add a message to the diagnostics view
*/
/*
let message = IndexBuffer::from_iter(vec![
(Point2::new(1, 0), make_label("invalid digit '")),
(Point2::new(2, 0), make_label(&format!("{}", c))
.map_item(|_p,a| a.add_style_back(TerminalStyle::fg_color((140,140,250))))),
(Point2::new(3, 0), make_label("'"))
]);
self.msg.push(crate::diagnostics::make_error(message.get_port().flatten()));
*/
self.data.set(c);
} else {
self.data.set(c);
}
}
}
TreeNavResult::Continue
}
}

View file

@ -0,0 +1,149 @@
use {
laddertypes::TypeTerm,
r3vi::{
buffer::singleton::SingletonBuffer,
view::{
AnyOuterViewPort,
singleton::*
}
},
crate::{
repr_tree::{Context, ReprTree, ReprTreeExt, ReprLeaf},
editors::digit::DigitEditor,
},
std::sync::{Arc, RwLock}
};
pub fn init_ctx( ctx: Arc<RwLock<Context>> ) {
// todo: proper scoping of Radix variable
ctx.write().unwrap().add_varname("Radix");
let morphtype =
crate::repr_tree::MorphismType {
src_type: Context::parse(&ctx, "<Digit Radix>"),
dst_type: Context::parse(&ctx, "<Digit Radix>~EditTree")
};
ctx.write().unwrap()
.morphisms
.add_morphism(
morphtype,
{
let ctx = ctx.clone();
move |src_rt, σ| {
let radix =
match σ.get( &laddertypes::TypeID::Var(ctx.read().unwrap().get_var_typeid("Radix").unwrap()) ) {
Some(TypeTerm::Num(n)) => *n as u32,
_ => 0
};
/* Create EditTree object
*/
let mut edittree = DigitEditor::new(
ctx.clone(),
radix,
src_rt.descend(
Context::parse(&ctx, "Char")
).unwrap()
.singleton_buffer::<char>()
).into_node(
r3vi::buffer::singleton::SingletonBuffer::<usize>::new(0).get_port()
);
src_rt.write().unwrap()
.insert_branch(
ReprTree::from_singleton_buffer(
Context::parse(&ctx, "EditTree"),
SingletonBuffer::new(edittree)
)
);
}
}
);
let morphtype =
crate::repr_tree::MorphismType {
src_type: Context::parse(&ctx, "<Digit Radix>~Char"),
dst_type: Context::parse(&ctx, "<Digit Radix>~_256~machine::UInt8")
};
ctx.write().unwrap()
.morphisms
.add_morphism(
morphtype,
{
let ctx = ctx.clone();
move |rt: &mut Arc<RwLock<ReprTree>>, σ: &std::collections::HashMap<laddertypes::TypeID, TypeTerm>| {
/* infer radix from type
*/
let radix =
match σ.get( &laddertypes::TypeID::Var(ctx.read().unwrap().get_var_typeid("Radix").unwrap()) ) {
Some(TypeTerm::Num(n)) => (*n) as u32,
_ => 0
};
if radix <= 256 {
if let Some(src_rt) = rt.descend(Context::parse(&ctx, "Char")) {
/* insert projected view into ReprTree
*/
let u8_view =
src_rt.view_char()
.map(move |c| c.to_digit(radix).unwrap_or(0) as u8);
rt.write().unwrap().attach_leaf_to::<dyn SingletonView<Item = u8>>(
Context::parse(&ctx, "_256~machine::UInt8").get_lnf_vec().into_iter(),
u8_view
);
} else {
eprintln!("could not find required source representation: <Digit {}>~Char", radix);
}
} else {
eprintln!("radix too large ({})", radix);
}
}
}
);
let morphtype =
crate::repr_tree::MorphismType {
src_type: Context::parse(&ctx, "<Digit Radix>~_256~machine::UInt8"),
dst_type: Context::parse(&ctx, "<Digit Radix>~Char")
};
ctx.write().unwrap().morphisms
.add_morphism(morphtype, {
let ctx = ctx.clone();
move |rt: &mut Arc<RwLock<ReprTree>>, σ: &std::collections::HashMap<laddertypes::TypeID, TypeTerm>| {
/* infer radix from type
*/
let radix =
match σ.get( &laddertypes::TypeID::Var(ctx.read().unwrap().get_var_typeid("Radix").unwrap()) ) {
Some(TypeTerm::Num(n)) => (*n) as u32,
_ => 0
};
if radix <= 256 {
/* insert projected view into ReprTree
*/
let char_view =
rt.descend(Context::parse(&ctx, "_256~machine::UInt8"))
.unwrap()
.view_u8()
.map(move |digit| char::from_digit(digit as u32, radix).unwrap_or('?'));
rt.write().unwrap().attach_leaf_to::<dyn SingletonView<Item = char>>(
Context::parse(&ctx, "Char").get_lnf_vec().into_iter(),
char_view
);
} else {
eprintln!("radix too large ({})", radix);
}
}
});
}

View file

@ -0,0 +1,89 @@
use {
laddertypes::TypeTerm,
r3vi::{
view::{OuterViewPort,singleton::*},
buffer::{singleton::*, vec::*}
},
crate::{
repr_tree::{ReprTree, Context},
edit_tree::{
EditTree,
diagnostics::Message
}
},
std::sync::{Arc, RwLock}
};
pub struct DigitEditor {
pub(super) ctx: Arc<RwLock<Context>>,
pub(super) radix: u32,
pub(super) data: SingletonBuffer<char>,
pub(super) msg: VecBuffer<Message>,
}
impl DigitEditor {
pub fn new(ctx: Arc<RwLock<Context>>, radix: u32, data: SingletonBuffer<char>) -> Self {
DigitEditor {
ctx,
radix,
data,
msg: VecBuffer::new(),
}
}
pub fn into_node(self, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> EditTree {
// let data = self.get_data();
let editor = Arc::new(RwLock::new(self));
let ed = editor.write().unwrap();
let r = ed.radix;
EditTree::new(ed.ctx.clone(), depth)
.set_editor(editor.clone())
.set_cmd(editor.clone())
.set_diag(
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 = Result<u32, char>>> {
let radix = self.radix;
self.data.get_port().map(move |c|
if let Some(d) = c.to_digit(radix) {
Ok(d)
} else {
Err(c)
}
)
}
pub fn get_type(&self) -> TypeTerm {
TypeTerm::TypeID(self.ctx.read().unwrap().get_typeid("Digit").unwrap())
}
/*
pub fn get_data(&self) -> Arc<RwLock<ReprTree>> {
ReprTree::ascend(
&ReprTree::from_view(
self.ctx.read().unwrap().type_term_from_str("<Seq u32>").unwrap(),
self.get_data_port()
),
self.get_type()
)
}
*/
}

View file

@ -0,0 +1,8 @@
pub mod ctx;
pub mod cmd;
pub mod editor;
pub use editor::DigitEditor;
pub use ctx::init_ctx;

View file

@ -24,10 +24,9 @@ pub enum ListCmd {
impl ListCmd { impl ListCmd {
// note: cant use Into becaue of ctx (maybe global typedict?) // note: cant use Into becaue of ctx (maybe global typedict?)
pub fn into_repr_tree(self, ctx: &Arc<RwLock<Context>>) -> Arc<RwLock<ReprTree>> { pub fn into_repr_tree(self, ctx: &Arc<RwLock<Context>>) -> Arc<RwLock<ReprTree>> {
let buf = r3vi::buffer::singleton::SingletonBuffer::new(self); ReprTree::from_singleton_buffer(
ReprTree::new_leaf( Context::parse(ctx, "ListCmd"),
Context::parse(ctx, "ListCmd"), r3vi::buffer::singleton::SingletonBuffer::new(self)
buf.get_port().into()
) )
} }
} }

View file

@ -2,7 +2,7 @@ use {
r3vi::{view::{OuterViewPort, singleton::*}, buffer::singleton::*}, r3vi::{view::{OuterViewPort, singleton::*}, buffer::singleton::*},
laddertypes::{TypeTerm}, laddertypes::{TypeTerm},
crate::{ crate::{
repr_tree::{Context}, repr_tree::{Context, ReprTree},
editors::list::{ListEditor}//, PTYListController, PTYListStyle} editors::list::{ListEditor}//, PTYListController, PTYListStyle}
}, },
std::sync::{Arc, RwLock} std::sync::{Arc, RwLock}
@ -13,6 +13,7 @@ use {
pub fn init_ctx(ctx: Arc<RwLock<Context>>) { pub fn init_ctx(ctx: Arc<RwLock<Context>>) {
ctx.write().unwrap().add_list_typename("List".into()); ctx.write().unwrap().add_list_typename("List".into());
ctx.write().unwrap().add_varname("Item"); ctx.write().unwrap().add_varname("Item");
let mt = crate::repr_tree::MorphismType { let mt = crate::repr_tree::MorphismType {
src_type: Context::parse(&ctx, "<List Item>"), src_type: Context::parse(&ctx, "<List Item>"),
dst_type: Context::parse(&ctx, "<List Item>~EditTree") dst_type: Context::parse(&ctx, "<List Item>~EditTree")
@ -21,9 +22,10 @@ pub fn init_ctx(ctx: Arc<RwLock<Context>>) {
mt, mt,
{ {
let ctx = ctx.clone(); let ctx = ctx.clone();
move |rt, σ| { move |src_rt, σ| {
let item_id = laddertypes::TypeID::Var( ctx.read().unwrap().get_var_typeid("Item").unwrap() ); let item_id = laddertypes::TypeID::Var( ctx.read().unwrap().get_var_typeid("Item").unwrap() );
if let Some( item_type ) = σ.get( &item_id ) { if let Some( item_type ) = σ.get( &item_id ) {
let mut edittree_list = ListEditor::new( let mut edittree_list = ListEditor::new(
ctx.clone(), ctx.clone(),
item_type.clone() item_type.clone()
@ -31,10 +33,11 @@ pub fn init_ctx(ctx: Arc<RwLock<Context>>) {
r3vi::buffer::singleton::SingletonBuffer::<usize>::new(0).get_port() r3vi::buffer::singleton::SingletonBuffer::<usize>::new(0).get_port()
); );
let mut rt = rt.write().unwrap(); src_rt.write().unwrap().insert_branch(
rt.insert_leaf( ReprTree::from_singleton_buffer(
vec![ Context::parse(&ctx, "EditTree") ].into_iter(), Context::parse(&ctx, "EditTree"),
SingletonBuffer::new( Arc::new(RwLock::new( edittree_list )) ).get_port().into() SingletonBuffer::new(edittree_list)
)
); );
} else { } else {
eprintln!("no item type"); eprintln!("no item type");

View file

@ -101,7 +101,6 @@ impl ListEditor {
} }
pub fn into_node(mut self, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> EditTree { pub fn into_node(mut self, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> EditTree {
let data = self.get_data();
let ctx = self.ctx.clone(); let ctx = self.ctx.clone();
self.depth = depth.clone(); self.depth = depth.clone();
@ -155,7 +154,7 @@ impl ListEditor {
|x| x.read().unwrap().clone() |x| x.read().unwrap().clone()
) )
} }
/*
pub fn get_data(&self) -> Arc<RwLock<ReprTree>> { pub fn get_data(&self) -> Arc<RwLock<ReprTree>> {
let data_view = self.get_data_port(); let data_view = self.get_data_port();
ReprTree::new_leaf( ReprTree::new_leaf(
@ -163,7 +162,7 @@ impl ListEditor {
data_view.into() data_view.into()
) )
} }
*/
pub fn get_item(&self) -> Option<EditTree> { pub fn get_item(&self) -> Option<EditTree> {
if let Some(idx) = self.cursor.get().idx { if let Some(idx) = self.cursor.get().idx {
let idx = crate::utils::modulo(idx as isize, self.data.len() as isize) as usize; let idx = crate::utils::modulo(idx as isize, self.data.len() as isize) as usize;
@ -309,22 +308,23 @@ impl ListEditor {
let mut b = item.ctrl.spillbuf.write().unwrap(); let mut b = item.ctrl.spillbuf.write().unwrap();
let rt = ReprTree::new_arc(self.typ.clone()); let rt = ReprTree::new_arc(self.typ.clone());
let new_edittree = self.ctx.read().unwrap() let edittree = self.ctx.read().unwrap()
.setup_edittree( .setup_edittree(
rt, rt,
self.depth.map(|d| d+1) self.depth.map(|d| d+1)
); );
let mut tail_node = new_edittree.write().unwrap();
let mut tail_node = edittree.get_mut();
tail_node.goto(TreeCursor::home()); tail_node.goto(TreeCursor::home());
for node in b.iter() { for node in b.iter() {
tail_node tail_node
.send_cmd_obj( .send_cmd_obj(
ReprTree::new_leaf( ReprTree::from_singleton_buffer(
Context::parse(&self.ctx, "NestedNode"), Context::parse(&self.ctx, "EditTree"),
SingletonBuffer::<EditTree>::new( SingletonBuffer::<EditTree>::new(
node.read().unwrap().clone() node.read().unwrap().clone()
).get_port().into() )
) )
); );
} }
@ -340,7 +340,7 @@ impl ListEditor {
drop(tail_node); drop(tail_node);
self.insert( self.insert(
new_edittree edittree.value.clone()
); );
} else { } else {
@ -376,11 +376,11 @@ impl ListEditor {
let data = cur_editor.ctrl.spillbuf.read().unwrap(); let data = cur_editor.ctrl.spillbuf.read().unwrap();
for x in data.iter() { for x in data.iter() {
pxv_editor.send_cmd_obj( pxv_editor.send_cmd_obj(
ReprTree::new_leaf( ReprTree::from_singleton_buffer(
Context::parse(&self.ctx, "NestedNode"), Context::parse(&self.ctx, "EditTree"),
SingletonBuffer::<EditTree>::new( SingletonBuffer::<EditTree>::new(
x.read().unwrap().clone() x.read().unwrap().clone()
).get_port().into() )
) )
); );
} }
@ -435,11 +435,11 @@ impl ListEditor {
for x in data.iter() { for x in data.iter() {
cur_editor.send_cmd_obj( cur_editor.send_cmd_obj(
ReprTree::new_leaf( ReprTree::from_singleton_buffer(
Context::parse(&self.ctx, "NestedNode"), Context::parse(&self.ctx, "EditTree"),
SingletonBuffer::<EditTree>::new( SingletonBuffer::<EditTree>::new(
x.read().unwrap().clone() x.read().unwrap().clone()
).get_port().into() )
) )
); );
} }

View file

@ -2,7 +2,7 @@ use {
r3vi::{view::{OuterViewPort, singleton::*}, buffer::{singleton::*}}, r3vi::{view::{OuterViewPort, singleton::*}, buffer::{singleton::*}},
laddertypes::{TypeDict, TypeTerm, TypeID}, laddertypes::{TypeDict, TypeTerm, TypeID},
crate::{ crate::{
repr_tree::{ReprTree, MorphismType, GenericReprTreeMorphism, MorphismBase}, repr_tree::{ReprTree, ReprTreeExt, MorphismType, GenericReprTreeMorphism, MorphismBase},
edit_tree::EditTree edit_tree::EditTree
}, },
std::{ std::{
@ -29,7 +29,7 @@ pub struct Context {
pub list_types: Vec< TypeID >, pub list_types: Vec< TypeID >,
pub meta_chars: Vec< char >, pub meta_chars: Vec< char >,
edittree_hook: Arc< dyn Fn(Arc<RwLock<EditTree>>, TypeTerm) + Send +Sync +'static >, edittree_hook: Arc< dyn Fn(&mut EditTree, TypeTerm) + Send +Sync +'static >,
/// recursion /// recursion
parent: Option<Arc<RwLock<Context>>>, parent: Option<Arc<RwLock<Context>>>,
@ -64,7 +64,7 @@ impl Context {
Context::with_parent(None) Context::with_parent(None)
} }
pub fn set_edittree_hook(&mut self, hook: Arc< dyn Fn(Arc<RwLock<EditTree>>, TypeTerm) + Send +Sync +'static >) { pub fn set_edittree_hook(&mut self, hook: Arc< dyn Fn(&mut EditTree, TypeTerm) + Send +Sync +'static >) {
self.edittree_hook = hook; self.edittree_hook = hook;
} }
@ -78,7 +78,7 @@ impl Context {
pub fn make_repr(ctx: &Arc<RwLock<Self>>, t: &TypeTerm) -> Arc<RwLock<ReprTree>> { pub fn make_repr(ctx: &Arc<RwLock<Self>>, t: &TypeTerm) -> Arc<RwLock<ReprTree>> {
let rt = Arc::new(RwLock::new(ReprTree::new( TypeTerm::unit() ))); let rt = Arc::new(RwLock::new(ReprTree::new( TypeTerm::unit() )));
ctx.read().unwrap().morphisms.morph( rt.clone(), t ); ctx.read().unwrap().morphisms.apply_morphism( rt.clone(), &TypeTerm::unit(), t );
rt rt
} }
@ -180,30 +180,32 @@ impl Context {
&self, &self,
rt: Arc<RwLock<ReprTree>>, rt: Arc<RwLock<ReprTree>>,
depth: OuterViewPort<dyn SingletonView<Item = usize>> depth: OuterViewPort<dyn SingletonView<Item = usize>>
) -> Arc<RwLock<EditTree>> { ) -> SingletonBuffer<EditTree> {
let ladder = TypeTerm::Ladder(vec![ let ladder = TypeTerm::Ladder(vec![
rt.read().unwrap().get_type().clone(), rt.read().unwrap().get_type().clone(),
self.type_term_from_str("EditTree").expect("") self.type_term_from_str("EditTree").expect("")
]); ]);
self.morphisms.morph( eprintln!("setp_edittree: apply morphism T -> T~EditTree");
self.morphisms.apply_morphism(
rt.clone(), rt.clone(),
&rt.get_type(),
&ladder &ladder
); );
let new_edittree = rt eprintln!("get repr-node of editTree");
.read().unwrap() if let Some(new_edittree) =
.descend( rt.descend(self.type_term_from_str("EditTree").unwrap())
self.type_term_from_str("EditTree").expect("") {
).unwrap() let buf = new_edittree.singleton_buffer::<EditTree>();
.read().unwrap() (*self.edittree_hook)(
.get_view::<dyn SingletonView<Item = Arc<RwLock<EditTree>> >>() &mut *buf.get_mut(),
.unwrap() rt.read().unwrap().get_type().clone()
.get(); );
buf
(*self.edittree_hook)( new_edittree.clone(), rt.read().unwrap().get_type().clone() ); } else {
unreachable!();
new_edittree }
} }
} }

View file

@ -1,27 +1,50 @@
pub mod context; pub mod context;
pub mod morphism; pub mod morphism;
#[cfg(test)]
mod tests;
pub use { pub use {
context::{Context}, context::{Context},
morphism::{MorphismType, GenericReprTreeMorphism, MorphismBase} morphism::{MorphismType, GenericReprTreeMorphism, MorphismBase}
}; };
use { use {
r3vi::view::{AnyOuterViewPort, OuterViewPort, View, singleton::*}, r3vi::{
view::{
ViewPort, OuterViewPort,
AnyViewPort, AnyInnerViewPort, AnyOuterViewPort,
port::UpdateTask,
View,
singleton::*, sequence::*
},
buffer::{singleton::*, vec::*}
},
laddertypes::{TypeTerm}, laddertypes::{TypeTerm},
std::{ std::{
collections::HashMap, collections::HashMap,
sync::{Arc, RwLock}, sync::{Arc, RwLock},
any::Any
}, },
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
#[derive(Clone)] #[derive(Clone)]
pub struct ReprTree { pub struct ReprLeaf {
out_port: AnyViewPort,
in_port: AnyInnerViewPort,
data: Option< Arc<dyn Any + Send + Sync> >,
/// keepalive for the observer that updates the buffer from in_port
keepalive: Option<Arc<dyn Any + Send + Sync>>,
}
#[derive(Clone)]
pub struct ReprTree {
type_tag: TypeTerm, type_tag: TypeTerm,
port: Option<AnyOuterViewPort>,
branches: HashMap<TypeTerm, Arc<RwLock<ReprTree>>>, branches: HashMap<TypeTerm, Arc<RwLock<ReprTree>>>,
leaf: Option< ReprLeaf >
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -38,18 +61,282 @@ impl std::fmt::Debug for ReprTree {
} }
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl ReprLeaf {
pub fn from_view<V>( src_port: OuterViewPort<V> ) -> Self
where V: View + ?Sized + 'static,
V::Msg: Clone
{
let mut in_port = ViewPort::<V>::new();
in_port.attach_to(src_port);
let mut buf_port = ViewPort::<V>::new();
buf_port.attach_to(in_port.outer());
ReprLeaf {
keepalive: None,
in_port: in_port.inner().into(),
out_port: buf_port.into(),
data: None,
}
}
pub fn attach_to<V>(&mut self, src_port: OuterViewPort<V>)
where V: View + ?Sized + 'static,
V::Msg: Clone
{
self.in_port.clone()
.downcast::<V>().ok().unwrap()
.0.attach_to( src_port );
}
pub fn from_singleton_buffer<T>( buffer: SingletonBuffer<T> ) -> Self
where T: Clone + Send + Sync + 'static
{
let in_port = ViewPort::<dyn SingletonView<Item = T>>::new();
ReprLeaf {
keepalive: Some(buffer.attach_to(in_port.outer())),
in_port: in_port.inner().into(),
out_port: buffer.get_port().0.into(),
data: Some(buffer.into_inner())
}
}
pub fn as_singleton_buffer<T>(&mut self) -> Option<SingletonBuffer<T>>
where T: Clone + Send + Sync + 'static
{
let sgl_port = self.get_port::< dyn SingletonView<Item = T> >().unwrap().0;
let data_arc =
if let Some(data) = self.data.as_ref() {
data.clone().downcast::<RwLock<T>>().ok()
} else {
sgl_port.update();
let value = sgl_port.outer().get_view().unwrap().get();
eprintln!("make new data ARC from old value");
Some(Arc::new(RwLock::new( value )))
};
if let Some(data_arc) = data_arc {
self.data = Some(data_arc.clone() as Arc<dyn Any + Send + Sync>);
let buf = SingletonBuffer {
value: data_arc,
port: sgl_port.inner()
};
self.keepalive = Some(buf.attach_to(
self.in_port.0.clone()
.downcast::<dyn SingletonView<Item = T>>()
.ok().unwrap()
.outer()
));
Some(buf)
} else {
None
}
}
pub fn get_port<V>(&self) -> Option<OuterViewPort<V>>
where V: View + ?Sized + 'static,
V::Msg: Clone
{
self.out_port.clone().downcast::<V>().ok().map(|p| p.outer())
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl ReprTree {
pub fn new(type_tag: impl Into<TypeTerm>) -> Self {
ReprTree {
type_tag: type_tag.into(),
branches: HashMap::new(),
leaf: None
}
}
pub fn new_arc(type_tag: impl Into<TypeTerm>) -> Arc<RwLock<Self>> {
Arc::new(RwLock::new(Self::new(type_tag)))
}
pub fn get_type(&self) -> &TypeTerm {
&self.type_tag
}
pub fn insert_branch(&mut self, repr: Arc<RwLock<ReprTree>>) {
self.branches.insert(repr.clone().read().unwrap().type_tag.clone(), repr.clone());
}
pub fn from_char(ctx: &Arc<RwLock<Context>>, c: char ) -> Arc<RwLock<Self>> {
ReprTree::from_singleton_buffer(
Context::parse(ctx, "Char"),
SingletonBuffer::new(c)
)
}
pub fn from_view<V>( type_tag: impl Into<TypeTerm>, view: OuterViewPort<V> ) -> Arc<RwLock<Self>>
where V: View + ?Sized + 'static,
V::Msg: Clone
{
let mut rt = ReprTree::new(type_tag);
rt.leaf = Some(ReprLeaf::from_view(view));
Arc::new(RwLock::new(rt))
}
pub fn from_singleton_buffer<T>( type_tag: impl Into<TypeTerm>, buf: SingletonBuffer<T> ) -> Arc<RwLock<Self>>
where T: Clone + Send + Sync + 'static
{
let mut rt = ReprTree::new(type_tag);
rt.leaf = Some(ReprLeaf::from_singleton_buffer(buf));
Arc::new(RwLock::new(rt))
}
/// find, and if necessary, create corresponding path in repr-tree.
/// Attach src_port to input of that node
pub fn attach_leaf_to<V>(
&mut self,
mut type_ladder: impl Iterator<Item = TypeTerm>,
src_port: OuterViewPort<V>
)
where V: View + ?Sized + 'static,
V::Msg: Clone
{
if let Some(rung_type) = type_ladder.next() {
if let Some(next_repr) = self.branches.get(&rung_type) {
next_repr.write().unwrap().attach_leaf_to(type_ladder, src_port);
} else {
let mut next_repr = ReprTree::new(rung_type.clone());
next_repr.attach_leaf_to(type_ladder, src_port);
self.insert_branch(Arc::new(RwLock::new(next_repr)));
}
} else {
if let Some(leaf) = self.leaf.as_mut() {
leaf.attach_to(src_port);
} else {
self.leaf = Some(ReprLeaf::from_view(src_port));
}
}
}
pub fn insert_leaf(
&mut self,
mut type_ladder: impl Iterator<Item = TypeTerm>,
leaf: ReprLeaf
) {
if let Some(type_term) = type_ladder.next() {
if let Some(next_repr) = self.branches.get(&type_term) {
next_repr.write().unwrap().insert_leaf(type_ladder, leaf);
} else {
let mut next_repr = ReprTree::new(type_term.clone());
next_repr.insert_leaf(type_ladder, leaf);
self.insert_branch(Arc::new(RwLock::new(next_repr)));
}
} else {
self.leaf = Some(leaf)
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub fn descend_one(&self, dst_type: impl Into<TypeTerm>) -> Option<Arc<RwLock<ReprTree>>> {
let dst_type = dst_type.into();
assert!( dst_type.is_flat() );
self.branches.get(&dst_type).cloned()
}
pub fn descend_ladder(rt: &Arc<RwLock<Self>>, mut repr_ladder: impl Iterator<Item = TypeTerm>) -> Option<Arc<RwLock<ReprTree>>> {
if let Some(first) = repr_ladder.next() {
let rt = rt.read().unwrap();
repr_ladder.fold(
rt.descend_one(first),
|s, t| s?.descend(t))
} else {
Some(rt.clone())
}
}
pub fn descend(rt: &Arc<RwLock<Self>>, dst_type: impl Into<TypeTerm>) -> Option<Arc<RwLock<ReprTree>>> {
ReprTree::descend_ladder(rt, dst_type.into().get_lnf_vec().into_iter())
}
pub fn ascend(rt: &Arc<RwLock<Self>>, type_term: impl Into<TypeTerm>) -> Arc<RwLock<ReprTree>> {
let mut n = Self::new(type_term);
n.insert_branch(rt.clone());
Arc::new(RwLock::new(n))
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub fn singleton_buffer<T: Clone + Send + Sync + 'static>(&mut self) -> Option<SingletonBuffer<T>> {
if let Some(leaf) = self.leaf.as_mut() {
leaf.as_singleton_buffer::<T>()
} else {
None
}
}
/*
pub fn vec_buffer<T: Clone + Send + Sync + 'static>(&self) -> Option<VecBuffer<T>> {
}
*/
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub fn get_port<V: View + ?Sized + 'static>(&self) -> Option<OuterViewPort<V>>
where
V::Msg: Clone,
{
if let Some(leaf) = self.leaf.as_ref() {
leaf.get_port::<V>()
} else {
None
}
}
pub fn get_view<V: View + ?Sized + 'static>(&self) -> Option<Arc<V>>
where
V::Msg: Clone,
{
self.get_port::<V>()?
.get_view()
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub fn view_seq<T: 'static>(&self) -> OuterViewPort<dyn SequenceView<Item = T>> {
self.get_port::<dyn SequenceView<Item = T>>().expect("no sequence-view available")
}
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_u8(&self) -> OuterViewPort<dyn SingletonView<Item = u8>> {
self.get_port::<dyn SingletonView<Item = u8>>().expect("no u8-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 trait ReprTreeExt { pub trait ReprTreeExt {
fn get_type(&self) -> TypeTerm; fn get_type(&self) -> TypeTerm;
fn insert_leaf(&mut self, type_ladder: impl Iterator<Item = TypeTerm>, port: AnyOuterViewPort); fn insert_leaf(&mut self, type_ladder: impl Into<TypeTerm>, leaf: ReprLeaf);
fn insert_branch(&mut self, repr: Arc<RwLock<ReprTree>>); fn insert_branch(&mut self, repr: Arc<RwLock<ReprTree>>);
fn descend(&self, target_type: impl Into<TypeTerm>) -> Option<Arc<RwLock<ReprTree>>>; fn descend(&self, target_type: impl Into<TypeTerm>) -> Option<Arc<RwLock<ReprTree>>>;
fn descend_ladder(&self, ladder: impl Iterator<Item = TypeTerm>) -> Option<Arc<RwLock<ReprTree>>>;
fn view_char(&self) -> OuterViewPort<dyn SingletonView<Item = char>>; fn view_char(&self) -> OuterViewPort<dyn SingletonView<Item = char>>;
fn view_u8(&self) -> OuterViewPort<dyn SingletonView<Item = u8>>; fn view_u8(&self) -> OuterViewPort<dyn SingletonView<Item = u8>>;
fn view_u64(&self) -> OuterViewPort<dyn SingletonView<Item = u64>>; fn view_u64(&self) -> OuterViewPort<dyn SingletonView<Item = u64>>;
fn singleton_buffer<T: Clone + Send + Sync + 'static>(&self) -> SingletonBuffer<T>;
// fn vec_buffer<T: Clone + Send + Sync + 'static>(&self) -> VecBuffer<T>;
} }
impl ReprTreeExt for Arc<RwLock<ReprTree>> { impl ReprTreeExt for Arc<RwLock<ReprTree>> {
@ -57,8 +344,8 @@ impl ReprTreeExt for Arc<RwLock<ReprTree>> {
self.read().unwrap().get_type().clone() self.read().unwrap().get_type().clone()
} }
fn insert_leaf(&mut self, type_ladder: impl Iterator<Item = TypeTerm>, port: AnyOuterViewPort) { fn insert_leaf(&mut self, type_ladder: impl Into<TypeTerm>, leaf: ReprLeaf) {
self.write().unwrap().insert_leaf(type_ladder, port) self.write().unwrap().insert_leaf(type_ladder.into().get_lnf_vec().into_iter(), leaf)
} }
fn insert_branch(&mut self, repr: Arc<RwLock<ReprTree>>) { fn insert_branch(&mut self, repr: Arc<RwLock<ReprTree>>) {
@ -66,11 +353,7 @@ impl ReprTreeExt for Arc<RwLock<ReprTree>> {
} }
fn descend(&self, target_type: impl Into<TypeTerm>) -> Option<Arc<RwLock<ReprTree>>> { fn descend(&self, target_type: impl Into<TypeTerm>) -> Option<Arc<RwLock<ReprTree>>> {
self.read().unwrap().descend(target_type) ReprTree::descend( self, target_type )
}
fn descend_ladder(&self, ladder: impl Iterator<Item = TypeTerm>) -> Option<Arc<RwLock<ReprTree>>> {
ReprTree::descend_ladder(self, ladder)
} }
fn view_char(&self) -> OuterViewPort<dyn SingletonView<Item = char>> { fn view_char(&self) -> OuterViewPort<dyn SingletonView<Item = char>> {
@ -84,125 +367,16 @@ impl ReprTreeExt for Arc<RwLock<ReprTree>> {
fn view_u64(&self) -> OuterViewPort<dyn SingletonView<Item = u64>> { fn view_u64(&self) -> OuterViewPort<dyn SingletonView<Item = u64>> {
self.read().unwrap().view_u64() self.read().unwrap().view_u64()
} }
fn singleton_buffer<T: Clone + Send + Sync + 'static>(&self) -> SingletonBuffer<T> {
self.write().unwrap().singleton_buffer::<T>().expect("")
}
/*
fn vec_buffer<T: Clone + Send + Sync + 'static>(&self) -> VecBuffer<T> {
self.read().unwrap().vec_buffer::<T>().expect("")
}
*/
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl ReprTree {
pub fn new(type_tag: impl Into<TypeTerm>) -> Self {
ReprTree {
type_tag: type_tag.into(),
port: None,
branches: HashMap::new(),
}
}
pub fn new_arc(type_tag: impl Into<TypeTerm>) -> Arc<RwLock<Self>> {
Arc::new(RwLock::new(Self::new(type_tag)))
}
pub fn get_type(&self) -> &TypeTerm {
&self.type_tag
}
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(
Context::parse(ctx, "Char"),
buf.get_port().into()
)
}
pub fn from_u64(ctx: &Arc<RwLock<Context>>, v: u64) -> Arc<RwLock<Self>> {
let buf = r3vi::buffer::singleton::SingletonBuffer::<u64>::new(v);
ReprTree::new_leaf(
Context::parse(ctx, "<MachineInt 64>"),
buf.get_port().into()
)
}
pub fn new_leaf(type_tag: impl Into<TypeTerm>, port: AnyOuterViewPort) -> Arc<RwLock<Self>> {
let mut tree = ReprTree::new(type_tag.into());
tree.insert_leaf(vec![].into_iter(), port);
Arc::new(RwLock::new(tree))
}
pub fn insert_branch(&mut self, repr: Arc<RwLock<ReprTree>>) {
self.branches.insert(repr.clone().read().unwrap().type_tag.clone(), repr.clone());
}
pub fn insert_leaf(
&mut self,
mut type_ladder: impl Iterator<Item = TypeTerm>,
port: AnyOuterViewPort,
) {
if let Some(type_term) = type_ladder.next() {
if let Some(next_repr) = self.branches.get(&type_term) {
next_repr.write().unwrap().insert_leaf(type_ladder, port);
} else {
let mut next_repr = ReprTree::new(type_term.clone());
next_repr.insert_leaf(type_ladder, port);
self.insert_branch(Arc::new(RwLock::new(next_repr)));
}
} else {
self.port = Some(port);
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
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_u8(&self) -> OuterViewPort<dyn SingletonView<Item = u8>> {
self.get_port::<dyn SingletonView<Item = u8>>().expect("no u8-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>>
where
V::Msg: Clone,
{
Some(
self.port
.clone()?
.downcast::<V>()
.ok()?
)
}
pub fn get_view<V: View + ?Sized + 'static>(&self) -> Option<Arc<V>>
where
V::Msg: Clone,
{
self.get_port::<V>()?
.get_view()
}
pub fn descend(&self, dst_type: impl Into<TypeTerm>) -> Option<Arc<RwLock<ReprTree>>> {
self.branches.get(&dst_type.into()).cloned()
}
pub fn descend_ladder(rt: &Arc<RwLock<Self>>, mut repr_ladder: impl Iterator<Item = TypeTerm>) -> Option<Arc<RwLock<ReprTree>>> {
if let Some(first) = repr_ladder.next() {
let rt = rt.read().unwrap();
repr_ladder.fold(
rt.descend(first),
|s, t| s?.read().unwrap().descend(t))
} else {
Some(rt.clone())
}
}
pub fn ascend(rt: &Arc<RwLock<Self>>, type_term: impl Into<TypeTerm>) -> Arc<RwLock<ReprTree>> {
let mut n = Self::new(type_term);
n.insert_branch(rt.clone());
Arc::new(RwLock::new(n))
}
}

View file

@ -1,7 +1,8 @@
use { use {
laddertypes::{TypeTerm, TypeID}, laddertypes::{TypeTerm, TypeID},
r3vi::view::AnyOuterViewPort,
crate::{ crate::{
repr_tree::{ReprTree}, repr_tree::{ReprTree, ReprTreeExt, ReprLeaf},
}, },
std::{ std::{
sync::{Arc, RwLock}, sync::{Arc, RwLock},
@ -20,8 +21,9 @@ pub struct MorphismType {
#[derive(Clone)] #[derive(Clone)]
pub struct GenericReprTreeMorphism { pub struct GenericReprTreeMorphism {
morph_type: MorphismType, morph_type: MorphismType,
repr_tree_op: Arc< setup_projection: Arc<
dyn Fn( Arc<RwLock<ReprTree>>, &HashMap<TypeID, TypeTerm> ) dyn Fn( &mut Arc<RwLock<ReprTree>>, &HashMap<TypeID, TypeTerm> )
// -> Result< ReprLeaf, () >
+ Send + Sync + Send + Sync
> >
} }
@ -43,12 +45,15 @@ impl MorphismBase {
pub fn add_morphism( pub fn add_morphism(
&mut self, &mut self,
morph_type: MorphismType, morph_type: MorphismType,
repr_tree_op: impl Fn( Arc<RwLock<ReprTree>>, &HashMap<TypeID, TypeTerm> ) + Send + Sync + 'static setup_projection:
impl Fn( &mut Arc<RwLock<ReprTree>>, &HashMap<TypeID, TypeTerm> )
// -> Result< ReprLeaf, () /* TODO: error */ >
+ Send + Sync + 'static
) { ) {
self.morphisms.push( self.morphisms.push(
GenericReprTreeMorphism { GenericReprTreeMorphism {
morph_type, morph_type,
repr_tree_op: Arc::new(repr_tree_op) setup_projection: Arc::new(setup_projection)
} }
); );
} }
@ -75,14 +80,15 @@ impl MorphismBase {
None None
} }
pub fn morph( pub fn apply_morphism(
&self, &self,
repr_tree: Arc<RwLock<ReprTree>>, mut repr_tree: Arc<RwLock<ReprTree>>,
target_type: &TypeTerm src_type: &TypeTerm,
dst_type: &TypeTerm
) { ) {
let t = repr_tree.read().unwrap().get_type().clone(); // let t = repr_tree.read().unwrap().get_type().clone();
if let Some((m, σ)) = self.find_morphism( &t, target_type ) { if let Some((m, σ)) = self.find_morphism( &src_type, dst_type ) {
(m.repr_tree_op)( repr_tree.clone(), &σ ); (m.setup_projection)( &mut repr_tree, &σ );
} else { } else {
eprintln!("could not find morphism"); eprintln!("could not find morphism");
} }

View file

@ -0,0 +1,168 @@
use {
r3vi::{
buffer::singleton::{
SingletonBuffer
},
view::port::UpdateTask
},
crate::{
repr_tree::{Context, ReprTreeExt, ReprTree, ReprLeaf}
},
std::sync::{Arc, RwLock}
};
#[test]
fn char_view() {
let ctx = Arc::new(RwLock::new(Context::new()));
crate::editors::digit::init_ctx( ctx.clone() );
let mut rt_digit = ReprTree::new_arc( Context::parse(&ctx, "<Digit 16>") );
rt_digit.insert_leaf(
Context::parse(&ctx, "Char"),
ReprLeaf::from_singleton_buffer( SingletonBuffer::new('5') )
);
//<><><><>
let mut digit_char_buffer = rt_digit
.descend( Context::parse(&ctx, "Char") ).unwrap()
.singleton_buffer::<char>();
assert_eq!( digit_char_buffer.get(), '5' );
//<><><><>
let digit_char_view = rt_digit
.descend(Context::parse(&ctx, "Char")).unwrap()
.view_char();
assert_eq!( digit_char_view.get_view().unwrap().get(), '5' );
//<><><><>
// `Char-view` is correctly coupled to `char-buffer`
digit_char_buffer.set('2');
assert_eq!( digit_char_view.get_view().unwrap().get(), '2' );
}
#[test]
fn digit_projection_char_to_u8() {
let ctx = Arc::new(RwLock::new(Context::new()));
crate::editors::digit::init_ctx( ctx.clone() );
let mut rt_digit = ReprTree::new_arc( Context::parse(&ctx, "<Digit 16>") );
rt_digit.insert_leaf(
Context::parse(&ctx, "Char"),
ReprLeaf::from_singleton_buffer( SingletonBuffer::new('5') )
);
//<><><><>
// add another representation
ctx.read().unwrap().morphisms.apply_morphism(
rt_digit.clone(),
&Context::parse(&ctx, "<Digit 16>~Char"),
&Context::parse(&ctx, "<Digit 16>~_256~machine::UInt8")
);
let digit_u8_view = rt_digit
.descend(Context::parse(&ctx, "_256~machine::UInt8")).unwrap()
.view_u8();
assert_eq!( digit_u8_view.get_view().unwrap().get(), 5 as u8 );
// projection behaves accordingly , when buffer is changed
let mut digit_char_buffer = rt_digit
.descend( Context::parse(&ctx, "Char") ).unwrap()
.singleton_buffer::<char>();
digit_char_buffer.set('2');
assert_eq!( digit_u8_view.get_view().unwrap().get(), 2 as u8 );
}
#[test]
fn digit_projection_u8_to_char() {
let ctx = Arc::new(RwLock::new(Context::new()));
crate::editors::digit::init_ctx( ctx.clone() );
let mut rt_digit = ReprTree::new_arc( Context::parse(&ctx, "<Digit 16>") );
rt_digit.insert_leaf(
Context::parse(&ctx, "_256~machine::UInt8"),
ReprLeaf::from_singleton_buffer( SingletonBuffer::new(5 as u8) )
);
//<><><><>
// add another representation
ctx.read().unwrap().morphisms.apply_morphism(
rt_digit.clone(),
&Context::parse(&ctx, "<Digit 16>~_256~machine::UInt8"),
&Context::parse(&ctx, "<Digit 16>~Char")
);
let digit_u8_view = rt_digit
.descend(Context::parse(&ctx, "Char")).unwrap()
.view_char();
assert_eq!( digit_u8_view.get_view().unwrap().get(), '5' );
}
#[test]
fn char_buffered_projection() {
let ctx = Arc::new(RwLock::new(Context::new()));
crate::editors::digit::init_ctx( ctx.clone() );
let mut rt_digit = ReprTree::new_arc( Context::parse(&ctx, "<Digit 16>") );
rt_digit.insert_leaf(
Context::parse(&ctx, "_256~machine::UInt8"),
ReprLeaf::from_singleton_buffer( SingletonBuffer::new(8 as u8) )
);
let mut digit_u8_buffer = rt_digit
.descend(Context::parse(&ctx, "_256~machine::UInt8")).unwrap()
.singleton_buffer::<u8>();
assert_eq!( digit_u8_buffer.get(), 8 );
rt_digit.insert_leaf(
Context::parse(&ctx, "Char"),
ReprLeaf::from_singleton_buffer( SingletonBuffer::new('5') )
);
let digit_char_buf = rt_digit
.descend(Context::parse(&ctx, "Char")).unwrap()
.singleton_buffer::<char>();
let digit_char_view = rt_digit
.descend(Context::parse(&ctx, "Char")).unwrap()
.view_char();
// before setting up the morphism, char-view remains as initialized
assert_eq!( digit_char_buf.get(), '5' );
assert_eq!( digit_char_view.get_view().unwrap().get(), '5' );
// now we attach the char-repr to the u8-repr
ctx.read().unwrap().morphisms.apply_morphism(
rt_digit.clone(),
&Context::parse(&ctx, "<Digit 16>~_256~machine::UInt8"),
&Context::parse(&ctx, "<Digit 16>~Char")
);
// char buffer and view should now follow the u8-buffer
assert_eq!( digit_char_view.get_view().unwrap().get(), '8' );
assert_eq!( digit_char_buf.get(), '8' );
// now u8-buffer changes, and char-buffer should change accordingly
digit_u8_buffer.set(3);
assert_eq!( digit_u8_buffer.get(), 3 );
// char buffer should follow
digit_char_view.0.update();
assert_eq!( digit_char_buf.get(), '3' );
assert_eq!( digit_char_view.get_view().unwrap().get(), '3' );
}

View file

@ -68,20 +68,20 @@ impl TerminalEvent {
match self { match self {
TerminalEvent::Input(Event::Key(key)) => { TerminalEvent::Input(Event::Key(key)) => {
if let Some(tree_nav_cmd) = neo2_treenav_keymap(key) { if let Some(tree_nav_cmd) = neo2_treenav_keymap(key) {
ReprTree::new_leaf( ReprTree::from_singleton_buffer(
Context::parse(&ctx, "TreeNavCmd"), Context::parse(&ctx, "TreeNavCmd"),
SingletonBuffer::new(tree_nav_cmd).get_port().into() SingletonBuffer::new(tree_nav_cmd)
) )
} else if let Some(tree_nav_cmd) = universal_treenav_keymap(key) { } else if let Some(tree_nav_cmd) = universal_treenav_keymap(key) {
ReprTree::new_leaf( ReprTree::from_singleton_buffer(
Context::parse(&ctx, "TreeNavCmd"), Context::parse(&ctx, "TreeNavCmd"),
SingletonBuffer::new(tree_nav_cmd).get_port().into() SingletonBuffer::new(tree_nav_cmd)
) )
} else { } else {
if let Some(list_cmd) = tty_list_keymap(key) { if let Some(list_cmd) = tty_list_keymap(key) {
ReprTree::new_leaf( ReprTree::from_singleton_buffer(
Context::parse(&ctx, "ListCmd"), Context::parse(&ctx, "ListCmd"),
SingletonBuffer::new(list_cmd).get_port().into() SingletonBuffer::new(list_cmd)
) )
} else { } else {
match key { match key {
@ -89,9 +89,9 @@ impl TerminalEvent {
ReprTree::from_char(&ctx, *c) ReprTree::from_char(&ctx, *c)
} }
_ => { _ => {
ReprTree::new_leaf( ReprTree::from_singleton_buffer(
Context::parse(&ctx, "TerminalEvent"), Context::parse(&ctx, "TerminalEvent"),
SingletonBuffer::new(self.clone()).get_port().into() SingletonBuffer::new(self.clone())
) )
} }
} }
@ -99,9 +99,9 @@ impl TerminalEvent {
} }
} }
_ => { _ => {
ReprTree::new_leaf( ReprTree::from_singleton_buffer(
Context::parse(&ctx, "TerminalEvent"), Context::parse(&ctx, "TerminalEvent"),
SingletonBuffer::new(self.clone()).get_port().into() SingletonBuffer::new(self.clone())
) )
} }
} }

View file

@ -94,12 +94,12 @@ impl PTYListStyle {
pub fn for_node(node: &mut EditTree, style: (&str, &str, &str)) { pub fn for_node(node: &mut EditTree, style: (&str, &str, &str)) {
node.disp.view node.disp.view
.write().unwrap() .write().unwrap()
.insert_branch(ReprTree::new_leaf( .insert_branch(ReprTree::from_view(
Context::parse(&node.ctx, "TerminalView"), Context::parse(&node.ctx, "TerminalView"),
Self::new(style) Self::new(style)
.pty_view( .pty_view(
&node.get_edit::<ListEditor>().unwrap().read().unwrap() &node.get_edit::<ListEditor>().unwrap().read().unwrap()
).into() )
)); ));
} }
} }
@ -225,6 +225,7 @@ impl PTYListController {
rt, rt,
self.depth.map(|d| d+1) self.depth.map(|d| d+1)
); );
/*
let mut ne = new_edittree.write().unwrap(); let mut ne = new_edittree.write().unwrap();
match ne.send_cmd_obj(cmd_obj.clone()) { match ne.send_cmd_obj(cmd_obj.clone()) {
TreeNavResult::Continue => { TreeNavResult::Continue => {
@ -233,9 +234,12 @@ impl PTYListController {
TreeNavResult::Continue TreeNavResult::Continue
} }
TreeNavResult::Exit => { TreeNavResult::Exit => {
*/
TreeNavResult::Exit TreeNavResult::Exit
/*
} }
} }
*/
}, },
ListCursorMode::Select => { ListCursorMode::Select => {
if let Some(item) = e.get_item_mut() { if let Some(item) = e.get_item_mut() {

View file

@ -17,12 +17,14 @@ use {
} }
}; };
pub fn edittree_make_char_view( pub fn edittree_make_char_view(
node: EditTree node: EditTree
) -> EditTree { ) -> EditTree {
eprintln!("nested-tty: EditTree make char-view");
node.disp.view node.disp.view
.write().unwrap() .write().unwrap()
.insert_branch(ReprTree::new_leaf( .insert_branch(ReprTree::from_view(
Context::parse(&node.ctx, "TerminalView"), Context::parse(&node.ctx, "TerminalView"),
node.get_edit::< nested::editors::char::CharEditor >() node.get_edit::< nested::editors::char::CharEditor >()
.unwrap() .unwrap()
@ -31,7 +33,6 @@ pub fn edittree_make_char_view(
.get_port() .get_port()
.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(),
)); ));
node node
@ -42,7 +43,7 @@ pub fn edittree_make_digit_view(
) -> EditTree { ) -> EditTree {
node.disp.view node.disp.view
.write().unwrap() .write().unwrap()
.insert_branch(ReprTree::new_leaf( .insert_branch(ReprTree::from_view(
Context::parse(&node.ctx, "TerminalView"), Context::parse(&node.ctx, "TerminalView"),
node.get_edit::< nested::editors::digit::DigitEditor >() node.get_edit::< nested::editors::digit::DigitEditor >()
.unwrap() .unwrap()
@ -56,7 +57,6 @@ pub fn edittree_make_digit_view(
} }
) )
.to_grid() .to_grid()
.into(),
)); ));
node node

View file

@ -39,13 +39,12 @@ pub trait DisplaySegment {
} }
use nested::repr_tree::Context; use nested::repr_tree::{Context, ReprTreeExt};
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
impl DisplaySegment for nested::edit_tree::EditTree { impl DisplaySegment for nested::edit_tree::EditTree {
fn display_view(&self) -> OuterViewPort<dyn TerminalView> { fn display_view(&self) -> OuterViewPort<dyn TerminalView> {
if let Some( tv_repr ) = self.disp.view if let Some( tv_repr ) = self.disp.view
.read().unwrap()
.descend( Context::parse(&self.ctx, "TerminalView") ) .descend( Context::parse(&self.ctx, "TerminalView") )
{ {
if let Some(port) = if let Some(port) =