Compare commits

...

3 commits

5 changed files with 361 additions and 11 deletions
Cargo.toml
examples/tty-05-dictionary
lib-nested-core/src
editors/list
repr_tree

View file

@ -10,5 +10,6 @@ members = [
"examples/tty-02-digit",
"examples/tty-03-string",
"examples/tty-04-posint",
"examples/tty-05-dictionary",
]

View file

@ -0,0 +1,19 @@
[package]
name = "tty-05-dictionary"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
laddertypes = { path = "../../../lib-laddertypes" }
r3vi = { path = "../../../lib-r3vi" }
nested = { path = "../../lib-nested-core" }
nested-tty = { path = "../../lib-nested-tty" }
termion = "*"
cgmath = "*"
[dependencies.async-std]
version = "1.9.0"
features = ["unstable", "attributes"]

View file

@ -0,0 +1,279 @@
extern crate cgmath;
extern crate nested;
extern crate nested_tty;
extern crate r3vi;
extern crate termion;
use {
cgmath::Vector2,
nested::{
editors::{
ObjCommander
},
repr_tree::{Context, ReprTree, ReprTreeExt, ReprLeaf},
edit_tree::{EditTree, TreeNav, TreeCursor}
},
laddertypes::{
bimap::Bimap,
sugar::SugaredTypeTerm
},
nested_tty::{
DisplaySegment, TTYApplication,
TerminalCompositor, TerminalStyle, TerminalView,
TerminalAtom, TerminalEvent
},
r3vi::{
buffer::{singleton::*, vec::*},
view::{port::UpdateTask, singleton::*, list::*, sequence::*},
projection::*
},
std::sync::{Arc, RwLock},
};
#[async_std::main]
async fn main() {
/* setup context
*/
let ctx = Arc::new(RwLock::new(Context::new()));
nested::editors::char::init_ctx( ctx.clone() );
nested::editors::digit::init_ctx( ctx.clone() );
nested::editors::integer::init_ctx( ctx.clone() );
nested::editors::list::init_ctx( ctx.clone() );
nested_tty::setup_edittree_hook(&ctx);
let dict = Arc::new(RwLock::new(Bimap::<String, u64>::new()));
dict.write().unwrap().insert( "Nop".into(), 0 );
dict.write().unwrap().insert( "Jmp".into(), 1 );
dict.write().unwrap().insert( "Call".into(), 2 );
dict.write().unwrap().insert( "Branch".into(), 3 );
dict.write().unwrap().insert( "Ret".into(), 4 );
dict.write().unwrap().insert( "Lit".into(), 5 );
dict.write().unwrap().insert( "Pick".into(), 6 );
dict.write().unwrap().insert( "Roll".into(), 7 );
dict.write().unwrap().insert( "Dup".into(), 8 );
dict.write().unwrap().insert( "Drop".into(), 9 );
dict.write().unwrap().insert( "Swap".into(), 10 );
dict.write().unwrap().insert( "Rot".into(), 11 );
let symbol_morph_str_to_u64 = nested::repr_tree::GenericReprTreeMorphism::new(
Context::parse(&ctx, "Instruction ~ Mnemonic ~ <Seq~List~Vec Char>"),
Context::parse(&ctx, "Instruction ~ Opcode ~ ~ machine.UInt64"),
{
let ctx = ctx.clone();
let dict = dict.clone();
move |rt, σ| {
let str_view = rt
.descend(Context::parse(&ctx, "Instruction ~ Mnemonic ~ <Seq~List~Vec Char>")).unwrap()
.vec_buffer::<char>()
.get_port();
let u64_view = str_view
.to_singleton()
.map({
let old_value = Arc::new(RwLock::new(0));
let dict = dict.clone();
move |chars| {
let str_val = chars.iter().collect::<String>();
let dict = &dict.read().unwrap().;
let mut old_value = old_value.write().unwrap();
if let Some( new_value ) = dict.get( &str_val ) {
*old_value = new_value.clone();
new_value.clone()
} else {
old_value.clone()
}
}
});
rt.attach_leaf_to(
Context::parse(&ctx, "Opcode ~ ~ machine.UInt64"),
u64_view
);
}
}
);
let symbol_morph_u64_to_str = nested::repr_tree::GenericReprTreeMorphism::new(
Context::parse(&ctx, "Instruction ~ Opcode ~ ~ machine.UInt64"),
Context::parse(&ctx, "Instruction ~ Mnemonic ~ <Seq Char>"),
{
let ctx = ctx.clone();
let dict = dict.clone();
move |rt, σ| {
let u64_view = rt
.descend(Context::parse(&ctx, "Instruction ~ Opcode ~ ~ machine.UInt64")).unwrap()
.view_u64();
let str_view =
u64_view
.map({
let dict = dict.clone();
let old_value = Arc::new(RwLock::new( VecBuffer::<char>::new() ));
move |idx| {
let dict = &dict.read().unwrap().my;
let mut old_value = old_value.write().unwrap();
if let Some( new_value ) = dict.get( &idx ) {
*old_value = VecBuffer::<char>::with_data(
new_value.chars().collect::<Vec<char>>()
);
}
old_value.get_port().to_sequence()
}
})
.to_sequence()
.flatten();
rt.attach_leaf_to(
Context::parse(&ctx, "Instruction ~ Mnemonic ~ <Seq Char>"),
str_view
);
}
}
);
ctx.write().unwrap().morphisms.add_morphism( symbol_morph_u64_to_str );
ctx.write().unwrap().morphisms.add_morphism( symbol_morph_str_to_u64 );
let mut symbol_rt = nested::repr_tree::ReprTree::from_str(Context::parse(&ctx, "
Instruction ~ Mnemonic ~ <Seq~List~Vec Char>
"),
"Call"
);
// this is required to initialize the <Vec EditTree> representation,
// and to take the value from <Vec Char>
ctx.read().unwrap().build_repr_tree(
&symbol_rt,
Context::parse(&ctx, "Instruction ~ Mnemonic ~ <Seq~List~Vec Char>"),
vec![
Context::parse(&ctx, "Instruction ~ Opcode ~ ~ <PosInt 10 BigEndian> ~ EditTree"),
Context::parse(&ctx, "Instruction ~ Mnemonic ~ <Seq~List Char> ~ EditTree"),
]);
symbol_rt.write().unwrap().detach( &ctx );
fn set_master(
ctx: &Arc<RwLock<Context>>,
rt: &Arc<RwLock<ReprTree>>,
mut leaves: Vec< laddertypes::TypeTerm >,
master_idx: usize
) {
eprintln!("set master to {}", master_idx);
if master_idx < leaves.len() {
let master = leaves.remove( master_idx );
rt.write().unwrap().detach( &ctx );
ctx.read().unwrap().build_repr_tree(
rt,
master,
leaves
);
}
}
let editor_types = vec![
Context::parse(&ctx,
"Instruction ~ Mnemonic ~ <Seq~List Char> ~ EditTree"),
Context::parse(&ctx,
"Instruction ~ Opcode ~ ~ <PosInt 10 BigEndian> ~ EditTree"),
Context::parse(&ctx,
"Instruction ~ Opcode ~ ~ <PosInt 16 BigEndian> ~ EditTree"),
];
set_master(&ctx, &symbol_rt, editor_types.clone(), 0);
let mut list_editor = nested::editors::list::ListEditor::new(ctx.clone(), Context::parse(&ctx, "<Seq Char>"));
// add all desired editors to the list
for leaf in editor_types.iter() {
let et =
symbol_rt
.descend(leaf.clone()).unwrap()
.edittree(&ctx).get();
et.write().unwrap().goto(TreeCursor::none());
list_editor.data.push(et);
}
let mut edittree = list_editor.into_node(SingletonBuffer::new(0).get_port());
edittree.goto(TreeCursor{
leaf_mode: nested::editors::list::ListCursorMode::Insert,
tree_addr: vec![0, 0]
});
let edittree = Arc::new(RwLock::new(edittree));
/* setup terminal
*/
let app = TTYApplication::new({
/* event handler
*/
let ctx = ctx.clone();
let symbol_rt = symbol_rt.clone();
let last_idx = RwLock::new(0);
let editor_types = editor_types.clone();
move |ev| {
let cur = edittree.read().unwrap().get_cursor();
if cur.tree_addr.len() > 0 {
let mut li = last_idx.write().unwrap();
let ci = cur.tree_addr[0];
if *li != ci {
eprintln!("----------------------------------");
set_master(
&ctx,
&symbol_rt,
editor_types.clone(),
ci as usize
);
*li = ci;
}
}
edittree.write().unwrap().send_cmd_obj(ev.to_repr_tree(&ctx));
}
});
/* Setup the compositor to serve as root-view
* by routing it to the `app.port` Viewport,
* so it will be displayed on TTY-output.
*/
let compositor = TerminalCompositor::new(app.port.inner());
/* Now add some views to our compositor
*/
{
let mut comp = compositor.write().unwrap();
fn show_edit_tree(
ctx: &Arc<RwLock<Context>>,
comp: &mut TerminalCompositor,
rt: &Arc<RwLock<ReprTree>>,
y: i16
) {
let rt_edittree = rt.descend(Context::parse(&ctx, "EditTree")).expect("descend");
let halo_type = rt_edittree.read().unwrap().get_halo_type().clone();
let edittree = rt_edittree.read().unwrap().get_view::<dyn r3vi::view::singleton::SingletonView<Item = Arc<RwLock<EditTree>>>>().unwrap().get().read().unwrap().clone();
comp.push( nested_tty::make_label( &ctx.read().unwrap().type_term_to_str(&halo_type) )
.map_item(|_pt, atom| atom.add_style_front(TerminalStyle::fg_color((90,90,90))))
.offset(Vector2::new(1,y)));
comp.push( edittree.display_view()
.map_item(|_pt, atom|
atom.add_style_front(TerminalStyle::bg_color((80,80,80)))
)
.offset(Vector2::new(1,y+1)));
}
show_edit_tree( &ctx, &mut comp, &symbol_rt.descend(Context::parse(&ctx, "Instruction ~ Mnemonic ~ <Seq~List Char>")).unwrap(), 1 );
show_edit_tree( &ctx, &mut comp, &symbol_rt.descend(Context::parse(&ctx, "Instruction ~ Opcode ~ ~ <PosInt 10 BigEndian>")).unwrap(), 3 );
show_edit_tree( &ctx, &mut comp, &symbol_rt.descend(Context::parse(&ctx, "Instruction ~ Opcode ~ ~ <PosInt 16 BigEndian>")).unwrap(), 5 );
}
/* write the changes in the view of `term_port` to the terminal
*/
app.show().await.expect("output error!");
}

View file

@ -84,6 +84,20 @@ pub fn init_ctx(ctx: Arc<RwLock<Context>>) {
}
);
let seq_morph_to_list_char = GenericReprTreeMorphism::new(
Context::parse(&ctx, "<Seq Char>"),
Context::parse(&ctx, "<Seq Char>~<List Char>"),
{
let ctx = ctx.clone();
move |src_rt, σ| {
src_rt.attach_leaf_to(
Context::parse(&ctx, "<List Char>"),
src_rt.view_seq::<char>().to_list()
);
}
}
);
let list_morph_to_vec_char = GenericReprTreeMorphism::new(
Context::parse(&ctx, "<List Char>"),
Context::parse(&ctx, "<List Char>~<Vec Char>"),
@ -98,6 +112,34 @@ pub fn init_ctx(ctx: Arc<RwLock<Context>>) {
}
);
let seq_morph_to_list_u64 = GenericReprTreeMorphism::new(
Context::parse(&ctx, "<Seq machine.UInt64>"),
Context::parse(&ctx, "<Seq machine.UInt64>~<List machine.UInt64>"),
{
let ctx = ctx.clone();
move |src_rt, σ| {
src_rt.attach_leaf_to(
Context::parse(&ctx, "<List machine.UInt64>"),
src_rt.view_seq::<u64>().to_list()
);
}
}
);
let list_morph_to_vec_u64 = GenericReprTreeMorphism::new(
Context::parse(&ctx, "<List machine.UInt64>"),
Context::parse(&ctx, "<List machine.UInt64>~<Vec machine.UInt64>"),
{
let ctx = ctx.clone();
move |src_rt, σ| {
src_rt.attach_leaf_to(
Context::parse(&ctx, "<Vec machine.UInt64>"),
src_rt.view_list::<u64>()
);
}
}
);
let list_morph_from_vec_char = GenericReprTreeMorphism::new(
Context::parse(&ctx, "<List Char>~<Vec Char>"),
Context::parse(&ctx, "<List Char>"),
@ -129,7 +171,10 @@ pub fn init_ctx(ctx: Arc<RwLock<Context>>) {
ctx.write().unwrap().morphisms.add_morphism( list_morph_editsetup1 );
ctx.write().unwrap().morphisms.add_morphism( list_morph_editsetup3 );
ctx.write().unwrap().morphisms.add_morphism( list_morph_from_vec_char );
ctx.write().unwrap().morphisms.add_morphism( seq_morph_to_list_char );
ctx.write().unwrap().morphisms.add_morphism( seq_morph_to_list_u64 );
ctx.write().unwrap().morphisms.add_morphism( list_morph_to_vec_char );
ctx.write().unwrap().morphisms.add_morphism( list_morph_to_vec_u64 );
ctx.write().unwrap().morphisms.add_morphism( list_morph_to_vec_edittree );
}

View file

@ -1,9 +1,15 @@
use {
r3vi::{view::{OuterViewPort, singleton::*}, buffer::{singleton::*}},
laddertypes::{TypeDict, TypeTerm, TypeID, MorphismType, MorphismBase, Morphism},
crate::{
repr_tree::{ReprTree, ReprTreeExt, GenericReprTreeMorphism},
edit_tree::EditTree
edit_tree::EditTree,
repr_tree::{GenericReprTreeMorphism, ReprTree, ReprTreeExt},
},
laddertypes::{
parser::ParseLadderType, sugar::SugaredTypeTerm, unparser::UnparseLadderType,
BimapTypeDict, Morphism, MorphismBase, MorphismType, TypeDict, TypeID, TypeTerm,
},
r3vi::{
buffer::singleton::*,
view::{singleton::*, OuterViewPort},
},
std::{
collections::HashMap,
@ -24,7 +30,7 @@ pub static TYPEID_vec : TypeID = TypeID::Fun(4);
#[derive(Clone)]
pub struct Context {
/// assigns a name to every type
pub type_dict: Arc<RwLock<TypeDict>>,
pub type_dict: Arc<RwLock<BimapTypeDict>>,
pub morphisms: laddertypes::morphism::MorphismBase< GenericReprTreeMorphism >,
@ -53,12 +59,12 @@ impl Context {
type_dict: match parent.as_ref() {
Some(p) => p.read().unwrap().type_dict.clone(),
None => {
let mut dict = TypeDict::new();
assert_eq!( TYPEID_edittree, dict.add_typename("EditTree".into()) );
assert_eq!( TYPEID_char, dict.add_typename("Char".into()) );
assert_eq!( TYPEID_u64, dict.add_typename("machine.UInt64".into()) );
assert_eq!( TYPEID_list, dict.add_typename("List".into()) );
assert_eq!( TYPEID_vec, dict.add_typename("Vec".into()) );
let mut dict = BimapTypeDict::new();
assert_eq!(TYPEID_edittree, dict.add_typename("EditTree".into()));
assert_eq!(TYPEID_char, dict.add_typename("Char".into()));
assert_eq!(TYPEID_u64, dict.add_typename("machine.UInt64".into()));
assert_eq!(TYPEID_list, dict.add_typename("List".into()));
assert_eq!(TYPEID_vec, dict.add_typename("Vec".into()));
Arc::new(RwLock::new(dict))
}