add dictionary example

This commit is contained in:
Michael Sippel 2024-10-28 21:32:38 +01:00
parent 50fe43df97
commit b2083aec4c
Signed by: senvas
GPG key ID: F96CF119C34B64A6
3 changed files with 319 additions and 0 deletions

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,299 @@
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 );
dict.write().unwrap().insert( "Fetch".into(), 13 );
dict.write().unwrap().insert( "Store".into(), 14 );
dict.write().unwrap().insert( "Accept".into(), 15 );
dict.write().unwrap().insert( "Emit".into(), 16 );
dict.write().unwrap().insert( "IntAdd".into(), 17 );
dict.write().unwrap().insert( "IntSub".into(), 18 );
dict.write().unwrap().insert( "IntMul".into(), 19 );
dict.write().unwrap().insert( "IntDiv".into(), 20 );
dict.write().unwrap().insert( "IntRem".into(), 21 );
dict.write().unwrap().insert( "FltAdd".into(), 22 );
dict.write().unwrap().insert( "FltSub".into(), 23 );
dict.write().unwrap().insert( "FltMul".into(), 24 );
dict.write().unwrap().insert( "FltDiv".into(), 25 );
dict.write().unwrap().insert( "FltRem".into(), 26 );
dict.write().unwrap().insert( "BitNeg".into(), 28 );
dict.write().unwrap().insert( "BitAnd".into(), 29 );
dict.write().unwrap().insert( "BitOr".into(), 30 );
dict.write().unwrap().insert( "BitXor".into(), 31 );
dict.write().unwrap().insert( "BitShl".into(), 32 );
dict.write().unwrap().insert( "BitShr".into(), 33 );
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!");
}