diff --git a/Cargo.toml b/Cargo.toml index 73f07fc..b3de67d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,5 +5,6 @@ members = [ "examples/tty-01-hello", "examples/tty-02-digit", "examples/tty-03-string", + "examples/tty-04-posint" ] diff --git a/examples/tty-04-posint/Cargo.toml b/examples/tty-04-posint/Cargo.toml new file mode 100644 index 0000000..0e4e285 --- /dev/null +++ b/examples/tty-04-posint/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "tty-04-posint" +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"] + diff --git a/examples/tty-04-posint/README.md b/examples/tty-04-posint/README.md new file mode 100644 index 0000000..1f85cdd --- /dev/null +++ b/examples/tty-04-posint/README.md @@ -0,0 +1,7 @@ +# tty-04-posint + +In the following example, a editor +as before is used, but its data is morphed into +representing a positional integer which is then +projected into different radices and displayed +in different views on screen diff --git a/examples/tty-04-posint/src/main.rs b/examples/tty-04-posint/src/main.rs new file mode 100644 index 0000000..687d345 --- /dev/null +++ b/examples/tty-04-posint/src/main.rs @@ -0,0 +1,208 @@ +//! In the following example, a editor +//! as before is used, but its data is morphed into +//! representing a positional integer which is then +//! projected into different radices and displayed +//! in different views on screen + +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} + }, + nested_tty::{ + DisplaySegment, TTYApplication, + TerminalCompositor, TerminalStyle, TerminalView, + TerminalAtom, TerminalEvent + }, + r3vi::{ + buffer::{singleton::*, vec::*}, + view::{port::UpdateTask, 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); + + /* Create a Representation-Tree of type > + */ + let mut rt_digitlist = ReprTree::new_arc( Context::parse(&ctx, ">") ); + let mut rt_digitseq = ReprTree::new_arc( Context::parse(&ctx, ">") ); + rt_digitseq.insert_branch( rt_digitlist ); + let mut rt_posint = ReprTree::new_arc(Context::parse(&ctx, "")); + rt_posint.insert_branch( rt_digitseq ); + let mut rt_int = ReprTree::new_arc( Context::parse(&ctx, "ℕ") ); + rt_int.insert_branch( rt_posint ); + + /* Setup an Editor for this ReprTree + * (this will add the representation >~EditTree to the ReprTree) + */ + let rt_edittree_list = ctx.read().unwrap() + .setup_edittree( + ReprTree::descend( + &rt_int, + Context::parse(&ctx, "~>") + ).expect("cant descend reprtree"), + SingletonBuffer::new(0).get_port() + ); + + ctx.read().unwrap().morphisms.apply_morphism( + ReprTree::descend(&rt_int, + Context::parse(&ctx, " + + ~> + ~> + ") + ).expect("cant descend repr tree"), + &Context::parse(&ctx, ">~EditTree"), + &Context::parse(&ctx, "~Char>") + ); + + /* + * map seq of chars to seq of u64 digits + */ + let mut chars_view = + ReprTree::descend( + &rt_int, + Context::parse(&ctx, "~>~~Char>") + ).expect("cant descend") + .read().unwrap() + .get_port::>() + .unwrap(); + + let mut digits_view = chars_view + .to_sequence() + .filter_map( + |digit_char| + + /* TODO: call morphism + */ + match digit_char.to_digit(16) { + Some(d) => Some(d as usize), + None => None + } + ); + + rt_int.write().unwrap().insert_leaf( + vec![ + Context::parse(&ctx, ""), + Context::parse(&ctx, ">"), + Context::parse(&ctx, ""), + Context::parse(&ctx, "") + ].into_iter(), + nested::repr_tree::ReprLeaf::from_view( digits_view.clone() ) + ); + // + // + + ctx.read().unwrap().morphisms.apply_morphism( + rt_int.clone(), + &Context::parse(&ctx, "ℕ ~ ~ ~ℤ_2^64~machine.UInt64>"), + &Context::parse(&ctx, "ℕ ~ ~ ~ℤ_2^64~machine.UInt64>") + ); + ctx.read().unwrap().morphisms.apply_morphism( + rt_int.clone(), + &Context::parse(&ctx, "ℕ ~ ~ ~ℤ_2^64~machine.UInt64>"), + &Context::parse(&ctx, "ℕ ~ ~ ~ℤ_2^64~machine.UInt64>") + ); + ctx.read().unwrap().morphisms.apply_morphism( + rt_int.clone(), + &Context::parse(&ctx, "ℕ ~ ~ ~ℤ_2^64~machine.UInt64>"), + &Context::parse(&ctx, "ℕ ~ ~ ~ℤ_2^64~machine.UInt64>") + ); + + let dec_digits_view = ReprTree::descend(&rt_int, + Context::parse(&ctx, " + + ~< Seq ~ℤ_2^64~machine.UInt64 > + ") + ).expect("cant descend repr tree") + .read().unwrap() + .get_port::>().unwrap() + .map( + /* TODO: call morphism + */ + |digit| { + TerminalAtom::from( + char::from_digit(*digit as u32, 10) + ) + } + ) + .to_grid_horizontal(); + + let hex_digits_view = + ReprTree::descend( + &rt_int, + Context::parse(&ctx, " + + ~ > + ~ + ~Char>") + ).expect("cant descend") + .read().unwrap() + .get_port::>().unwrap() + .to_sequence() + .to_grid_horizontal() + .map_item(|_pt,c| TerminalAtom::new(*c, TerminalStyle::fg_color((30,90,200)))); + + /* setup terminal + */ + let app = TTYApplication::new({ + let edittree_list = rt_edittree_list.clone(); + + /* event handler + */ + let ctx = ctx.clone(); + move |ev| { + edittree_list.get().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(); + + let label_str = ctx.read().unwrap().type_term_to_str(&rt_int.read().unwrap().get_type()); + comp.push( + nested_tty::make_label(&label_str) + .map_item(|_pt, atom| atom.add_style_front(TerminalStyle::fg_color((90,90,90)))) + .offset(Vector2::new(1,1))); + + comp.push(rt_edittree_list.get() + .display_view() + .offset(Vector2::new(3,2))); + + comp.push(dec_digits_view.offset(Vector2::new(3,4))); + comp.push(hex_digits_view.offset(Vector2::new(3,5))); + } + + /* write the changes in the view of `term_port` to the terminal + */ + app.show().await.expect("output error!"); +} diff --git a/lib-nested-core/src/editors/char/mod.rs b/lib-nested-core/src/editors/char/mod.rs index 079fa85..b4d0e51 100644 --- a/lib-nested-core/src/editors/char/mod.rs +++ b/lib-nested-core/src/editors/char/mod.rs @@ -36,6 +36,7 @@ pub fn init_ctx( ctx: Arc> ) { if let Some(buf) = rt.singleton_buffer::() { // buffer already exists } else { + // create char buffer rt.insert_leaf( vec![].into_iter(), ReprLeaf::from_singleton_buffer( diff --git a/lib-nested-core/src/editors/digit/ctx.rs b/lib-nested-core/src/editors/digit/ctx.rs index 8547552..d5822c2 100644 --- a/lib-nested-core/src/editors/digit/ctx.rs +++ b/lib-nested-core/src/editors/digit/ctx.rs @@ -80,7 +80,7 @@ pub fn init_ctx( ctx: Arc> ) { let morphtype = crate::repr_tree::MorphismType { src_type: Context::parse(&ctx, "~Char"), - dst_type: Context::parse(&ctx, "~ℤ_256~machine::UInt8") + dst_type: Context::parse(&ctx, "~ℤ_2^64~machine.UInt64") }; ctx.write().unwrap() @@ -124,7 +124,7 @@ pub fn init_ctx( ctx: Arc> ) { let morphtype = crate::repr_tree::MorphismType { - src_type: Context::parse(&ctx, "~ℤ_256~machine::UInt8"), + src_type: Context::parse(&ctx, "~ℤ_2^64~machine.UInt64"), dst_type: Context::parse(&ctx, "~Char") }; @@ -144,10 +144,10 @@ pub fn init_ctx( ctx: Arc> ) { /* insert projected view into ReprTree */ let char_view = - rt.descend(Context::parse(&ctx, "ℤ_256~machine::UInt8")) + rt.descend(Context::parse(&ctx, "ℤ_2^64~machine::UInt64")) .unwrap() - .view_u8() - .map(move |digit| char::from_digit(digit as u32, radix).unwrap_or('?')); + .view_usize() + .map(move |digit| char::from_digit((digit%radix as usize) as u32, radix).unwrap_or('?')); rt.write().unwrap().attach_leaf_to::>( Context::parse(&ctx, "Char").get_lnf_vec().into_iter(), diff --git a/lib-nested-core/src/editors/digit/editor.rs b/lib-nested-core/src/editors/digit/editor.rs index a73733b..125d2a3 100644 --- a/lib-nested-core/src/editors/digit/editor.rs +++ b/lib-nested-core/src/editors/digit/editor.rs @@ -73,6 +73,11 @@ impl DigitEditor { pub fn get_type(&self) -> TypeTerm { TypeTerm::TypeID(self.ctx.read().unwrap().get_typeid("Digit").unwrap()) } + + pub fn get_char(&self) -> char { + self.data.get() + } + /* pub fn get_data(&self) -> Arc> { ReprTree::ascend( diff --git a/lib-nested-core/src/editors/integer/ctx.rs b/lib-nested-core/src/editors/integer/ctx.rs index b8bfac2..23eeab6 100644 --- a/lib-nested-core/src/editors/integer/ctx.rs +++ b/lib-nested-core/src/editors/integer/ctx.rs @@ -5,8 +5,7 @@ use { }, laddertypes::{TypeTerm}, crate::{ - repr_tree::{Context}, - repr_tree::{MorphismType}, + repr_tree::{ReprTree, ReprLeaf, Context, MorphismType}, editors::{ list::*, integer::* @@ -16,97 +15,142 @@ use { }; pub fn init_ctx(ctx: Arc>) { - /* - ctx.add_list_typename("PosInt".into()); - let pattern = MorphismTypePattern { - src_tyid: ctx.get_typeid("List"), - dst_tyid: ctx.get_typeid("PosInt").unwrap() + // TODO: proper scoping + // ctx.write().unwrap().add_varname("Radix"); + ctx.write().unwrap().add_varname("SrcRadix"); + ctx.write().unwrap().add_varname("DstRadix"); + + let morphism_type = MorphismType { + src_type: Context::parse(&ctx, "ℕ ~ ~ ~ℤ_2^64~machine.UInt64>"), + dst_type: Context::parse(&ctx, "ℕ ~ ~ ~ℤ_2^64~machine.UInt64>") }; - ctx.add_morphism(pattern, - Arc::new( - |mut node, dst_type| { - // todo: check src_type parameter to be ( Digit radix ) - match dst_type { - TypeTerm::App(args) => { - if args.len() > 1 { - match args[1] { - TypeTerm::Num(_radix) => { - /* FIXME - PTYListController::for_node( - &mut node, - Some(','), - None, - ); + ctx.write().unwrap().morphisms.add_morphism( + morphism_type, + { + let ctx = ctx.clone(); + move |src_rt, σ| { + let src_digits = ReprTree::descend( + &src_rt, + Context::parse(&ctx, " + + ~~ℤ_2^64~machine.UInt64 > + ") + .apply_substitution(&|k|σ.get(k).cloned()).clone() + ).expect("cant descend") + .read().unwrap() + .view_seq::< usize >(); - PTYListStyle::for_node( - &mut node, - ("0d", "", "") - ); -*/ - Some(node) - }, - _ => None - } - } else { - None - } - } - _ => None - } + src_rt.write().unwrap().insert_leaf( + vec![ + Context::parse(&ctx, "") + .apply_substitution(&|k|σ.get(k).cloned()).clone(), + Context::parse(&ctx, ">") + .apply_substitution(&|k|σ.get(k).cloned()).clone(), + Context::parse(&ctx, ""), + Context::parse(&ctx, "") + ].into_iter(), + + ReprLeaf::from_view( src_digits.reverse() ) + ); } - ) + } ); - ctx.add_node_ctor( - "PosInt", Arc::new( - |ctx0: Arc>, dst_typ: TypeTerm, depth: OuterViewPort>| { - match dst_typ.clone() { - TypeTerm::App(args) => { - if args.len() > 1 { - match args[1] { - TypeTerm::Num(radix) => { - let ctx = ctx0.read().unwrap(); - let mut node = Context::make_node( - &ctx0, - TypeTerm::App(vec![ - TypeTerm::TypeID(ctx.get_typeid("List").unwrap()), - TypeTerm::TypeID( - ctx.get_typeid("Digit").unwrap() - ) - .num_arg(radix) - .clone() - .into() - ]), - depth.map(|d| d+1) - ).unwrap(); - node = node.morph(dst_typ); - Some(node) - } - _ => None - } - } else { - None - } - } - _ => None - } + + let morphism_type = MorphismType { + src_type: Context::parse(&ctx, "ℕ ~ ~ ~ℤ_2^64~machine.UInt64>"), + dst_type: Context::parse(&ctx, "ℕ ~ ~ ~ℤ_2^64~machine.UInt64>") + }; + + ctx.write().unwrap().morphisms.add_morphism( + morphism_type, + { + let ctx = ctx.clone(); + move |src_rt, σ| { + let src_digits = ReprTree::descend( + &src_rt, + Context::parse(&ctx, " + + ~~ℤ_2^64~machine.UInt64 > + ") + .apply_substitution(&|k|σ.get(k).cloned()).clone() + ).expect("cant descend") + .read().unwrap() + .view_seq::< usize >(); + + src_rt.write().unwrap().insert_leaf( + vec![ + Context::parse(&ctx, "") + .apply_substitution(&|k|σ.get(k).cloned()).clone(), + Context::parse(&ctx, ">") + .apply_substitution(&|k|σ.get(k).cloned()).clone(), + Context::parse(&ctx, ""), + Context::parse(&ctx, "") + ].into_iter(), + + ReprLeaf::from_view( src_digits.reverse() ) + ); } - ) + } + ); + + + + + let morphism_type = MorphismType { + src_type: Context::parse(&ctx, "ℕ ~ ~ ~ℤ_2^64~machine.UInt64>"), + dst_type: Context::parse(&ctx, "ℕ ~ ~ ~ℤ_2^64~machine.UInt64>") + }; + + ctx.write().unwrap().morphisms.add_morphism( + morphism_type, + { + let ctx = ctx.clone(); + move |src_rt, σ| { + let src_radix = match σ.get(&laddertypes::TypeID::Var( + ctx.read().unwrap().get_var_typeid("SrcRadix").unwrap() + )) { + Some(laddertypes::TypeTerm::Num(n)) => *n as usize, + _ => 0 + }; + + let dst_radix = match σ.get(&laddertypes::TypeID::Var( + ctx.read().unwrap().get_var_typeid("DstRadix").unwrap() + )) { + Some(laddertypes::TypeTerm::Num(n)) => *n as usize, + _ => 0 + }; + + let src_digits_rt = ReprTree::descend( + src_rt, + Context::parse(&ctx, " + + ~ ~ ℤ_2^64 ~ machine.UInt64 >" + ).apply_substitution(&|k|σ.get(k).cloned()).clone() + ).expect("cant descend repr tree"); + + let dst_digits_port = + src_digits_rt.read().unwrap() + .view_seq::() + .to_positional_uint( src_radix ) + .transform_radix( dst_radix ) + ; + + src_rt.write().unwrap() + .insert_leaf( + vec![ + Context::parse(&ctx, "").apply_substitution(&|k|σ.get(k).cloned()).clone(), + Context::parse(&ctx, ">").apply_substitution(&|k|σ.get(k).cloned()).clone(), + Context::parse(&ctx, ""), + Context::parse(&ctx, ""), + ].into_iter(), + ReprLeaf::from_view(dst_digits_port) + ); + } + } ); - */ - /* - ctx.add_typename("Date".into()); - ctx.add_typename("ISO-8601".into()); - ctx.add_typename("TimeSince".into()); - ctx.add_typename("UnixEpoch".into()); - ctx.add_typename("AnnoDomini".into()); - ctx.add_typename("Epoch".into()); - ctx.add_typename("Duration".into()); - ctx.add_typename("Seconds".into()); - ctx.add_typename("ℕ".into()); - */ } diff --git a/lib-nested-core/src/editors/integer/mod.rs b/lib-nested-core/src/editors/integer/mod.rs index 70b0759..e86a431 100644 --- a/lib-nested-core/src/editors/integer/mod.rs +++ b/lib-nested-core/src/editors/integer/mod.rs @@ -10,3 +10,139 @@ pub use { ctx::init_ctx }; +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + +use { + r3vi::{ + view::{ + View, ViewPort, OuterViewPort, + Observer, + ObserverBroadcast, + sequence::* + } + }, + crate::{ + editors::integer::radix::{ + PosIntProjections + } + }, + std::sync::{Arc, RwLock} +}; + +pub trait PositionalUInt : SequenceView { + fn get_radix(&self) -> usize; + fn get_value(&self) -> usize { + let mut val = 0; + let mut r = 1; + for i in 0..self.len().unwrap_or(0) { + val += r * self.get(&i).unwrap(); + r *= self.get_radix(); + } + + val + } +} + +impl PositionalUInt for RwLock { + fn get_radix(&self) -> usize { + self.read().unwrap().get_radix() + } +} + +struct PosUIntFromDigits { + radix: usize, + src_digits: Option>>, + cast: Arc>> +} + +impl View for PosUIntFromDigits { + type Msg = usize; +} + +impl SequenceView for PosUIntFromDigits { + type Item = usize; + + fn get(&self, idx: &usize) -> Option { + self.src_digits.get(idx) + } + + fn len(&self) -> Option { + self.src_digits.len() + } +} + +impl PositionalUInt for PosUIntFromDigits { + fn get_radix(&self) -> usize { + self.radix + } +} + +impl Observer> for PosUIntFromDigits { + fn reset(&mut self, new_src: Option>>) { + self.src_digits = new_src; +// self.cast.write().unwrap().notify(0); + } + + fn notify(&mut self, idx: &usize) { + self.cast.write().unwrap().notify(idx); + } +} + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + +pub trait DigitSeqProjection { + fn to_positional_uint(&self, radix: usize) -> OuterViewPort; +} + +impl DigitSeqProjection for OuterViewPort> { + fn to_positional_uint(&self, radix: usize) -> OuterViewPort { + let port = ViewPort::new(); + port.add_update_hook(Arc::new(self.0.clone())); + + let proj = Arc::new(RwLock::new(PosUIntFromDigits { + radix, + src_digits: None, + cast: port.inner().get_broadcast() + })); + + self.add_observer(proj.clone()); + port.set_view(Some(proj)); + port.into_outer() + } +} + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + +struct PosUIntToDigits { + src: Option>, + cast: Arc>>> +} + +impl View for PosUIntToDigits { + type Msg = usize; +} + +impl SequenceView for PosUIntToDigits { + type Item = usize; + + fn get(&self, idx: &usize) -> Option { + self.src.get(idx) + } + + fn len(&self) -> Option { + self.src.len() + } +} + +impl Observer for PosUIntToDigits { + fn reset(&mut self, view: Option>) { + self.src = view; +// self.cast.notify_all(); + } + + fn notify(&mut self, idx: &usize) { + self.cast.notify(idx); + } +} + + diff --git a/lib-nested-core/src/editors/integer/radix.rs b/lib-nested-core/src/editors/integer/radix.rs index bcc12da..db3506c 100644 --- a/lib-nested-core/src/editors/integer/radix.rs +++ b/lib-nested-core/src/editors/integer/radix.rs @@ -1,69 +1,127 @@ use { r3vi::{ view::{ + View, ViewPort, InnerViewPort, Observer, OuterViewPort, + ObserverBroadcast, sequence::*, + list::* }, buffer::{vec::*} }, + crate::{ + editors::integer::{ + PositionalUInt + }, + repr_tree::{ReprTree, ReprLeaf} + }, std::sync::{Arc, RwLock}, }; +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + +pub trait PosIntProjections { + fn transform_radix(&self, dst_radix: usize) -> OuterViewPort>; +// fn to_digits(&self) -> OuterViewPort>; +} + +impl PosIntProjections for OuterViewPort { + fn transform_radix(&self, dst_radix: usize) -> OuterViewPort> { + let port = ViewPort::>::new(); + port.add_update_hook(Arc::new(self.0.clone())); + +// let mut vec_port = ViewPort::new(); + let proj = Arc::new(RwLock::new(RadixProjection { + src: None, + dst_radix, + dst_digits: VecBuffer::new(), + cast: port.inner().get_broadcast() + })); + + self.add_observer(proj.clone()); + port.set_view(Some(proj as Arc>)); + port.into_outer() + } +/* + fn to_digits(&self) -> OuterViewPort> { + let port = ViewPort::new(); + port.add_update_hook(Arc::new(self.0.clone())); + let proj = Arc::new(RwLock::new(PosUIntToDigits { + src: None, + cast: port.inner().get_broadcast() + })); + self.add_observer(proj.clone()); + port.inner().set_view(Some(proj)); + port.into_outer() + } + */ +} + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + pub struct RadixProjection { - src_radix: usize, + src: Option>, dst_radix: usize, - src_digits: Option>>, - dst_digits: RwLock>, + dst_digits: VecBuffer, + cast: Arc>>> +} + +impl View for RadixProjection { + type Msg = usize; +} + +impl SequenceView for RadixProjection { + type Item = usize; + + fn get(&self, idx: &usize) -> Option { + if *idx < self.dst_digits.len() { + Some(self.dst_digits.get(*idx)) + } else { + None + } + } + + fn len(&self) -> Option { + Some(self.dst_digits.len()) + } +} + +impl PositionalUInt for RadixProjection { + fn get_radix(&self) -> usize { + self.dst_radix + } +} + +impl Observer< dyn PositionalUInt > for RadixProjection { + fn reset(&mut self, view: Option>) { + self.src = view; + self.update(); + } + + fn notify(&mut self, idx: &usize) { + self.update(); + // self.update_digit(idx) + } } impl RadixProjection { - pub fn new( - // static parameters - //--- - src_radix: usize, - dst_radix: usize, - //--- + /// recalculate everything + fn update(&mut self) { +// let mut dst = self.dst_digits; + let old_len = self.dst_digits.len(); + self.dst_digits.clear(); - // dynamic parameters - //--- - // input - src_digits: OuterViewPort>, - // output - dst_digits: InnerViewPort>>, - //--- - ) -> Arc> { - dst_digits.0.add_update_hook(Arc::new(src_digits.0.clone())); - let proj = Arc::new(RwLock::new(RadixProjection { - src_radix, - dst_radix, - src_digits: None, - dst_digits: RwLock::new(VecBuffer::with_port(dst_digits)), - })); - src_digits.add_observer(proj.clone()); - proj - } - - fn machine_int(&self) -> usize { - let mut val = 0; - let mut r = 1; - for i in 0..self.src_digits.len().unwrap_or(0) { - val += r * self.src_digits.get(&i).unwrap(); - r *= self.src_radix; + if let Some(src) = self.src.as_ref() { + let mut val = src.get_value(); + while val > 0 { + self.dst_digits.push(val % self.dst_radix); + val /= self.dst_radix; + } } - val - } - - // recalculate everything - fn update(&self) { - let mut dst = self.dst_digits.write().unwrap(); - dst.clear(); - - let mut val = self.machine_int(); - - while val > 0 { - dst.push(val % self.dst_radix); - val /= self.dst_radix; + let new_len = self.dst_digits.len(); + for i in 0 .. usize::max(old_len, new_len) { + self.cast.write().unwrap().notify(&i); } } @@ -84,18 +142,3 @@ impl RadixProjection { } } -impl Observer> for RadixProjection { - fn reset(&mut self, view: Option>>) { - self.src_digits = view; - } - - fn notify(&mut self, _idx: &usize) { - // todo: - // src digit i changed. - // which dst-digits does it affect? - // update dst-digit j: - - // ...but for now the easy way - self.update(); - } -} diff --git a/lib-nested-core/src/editors/list/ctx.rs b/lib-nested-core/src/editors/list/ctx.rs index 79943db..808e28c 100644 --- a/lib-nested-core/src/editors/list/ctx.rs +++ b/lib-nested-core/src/editors/list/ctx.rs @@ -92,6 +92,41 @@ pub fn init_ctx(ctx: Arc>) { } ); + let mt = crate::repr_tree::MorphismType { + src_type: Context::parse(&ctx, ">~EditTree"), + dst_type: Context::parse(&ctx, "~Char>") + }; + ctx.write().unwrap().morphisms.add_morphism( + mt, + { + let ctx = ctx.clone(); + move |src_rt, σ| { + let edittree = + src_rt + .descend(Context::parse(&ctx, "EditTree")).unwrap() + .singleton_buffer::(); + + let list_edit = edittree.get().get_edit::< ListEditor >().unwrap(); + let edittree_items = list_edit.read().unwrap().data.get_port().to_list(); + src_rt.write().unwrap().insert_leaf( + vec![ Context::parse(&ctx, "") ].into_iter(), + ReprLeaf::from_view( + edittree_items + .map( + |edittree_char| + edittree_char + .read().unwrap() + .get_edit::().unwrap() + .read().unwrap() + .get_char() + ) + ) + ); + } + } + ); + + let mt = crate::repr_tree::MorphismType { src_type: Context::parse(&ctx, ""), diff --git a/lib-nested-core/src/lib.rs b/lib-nested-core/src/lib.rs index bca12dc..b942062 100644 --- a/lib-nested-core/src/lib.rs +++ b/lib-nested-core/src/lib.rs @@ -1,4 +1,6 @@ +#![feature(trait_upcasting)] + pub mod repr_tree; pub mod edit_tree; pub mod editors; diff --git a/lib-nested-core/src/repr_tree/mod.rs b/lib-nested-core/src/repr_tree/mod.rs index 3b58eb8..a5c47a8 100644 --- a/lib-nested-core/src/repr_tree/mod.rs +++ b/lib-nested-core/src/repr_tree/mod.rs @@ -396,6 +396,10 @@ impl ReprTree { pub fn view_u64(&self) -> OuterViewPort> { self.get_port::>().expect("no u64-view available") } + + pub fn view_usize(&self) -> OuterViewPort> { + self.get_port::>().expect("no usize-view available") + } } @@ -412,6 +416,7 @@ pub trait ReprTreeExt { fn view_char(&self) -> OuterViewPort>; fn view_u8(&self) -> OuterViewPort>; fn view_u64(&self) -> OuterViewPort>; + fn view_usize(&self) -> OuterViewPort>; fn singleton_buffer(&self) -> SingletonBuffer; fn vec_buffer(&self) -> VecBuffer; @@ -446,6 +451,10 @@ impl ReprTreeExt for Arc> { self.read().unwrap().view_u64() } + fn view_usize(&self) -> OuterViewPort> { + self.read().unwrap().view_usize() + } + fn singleton_buffer(&self) -> SingletonBuffer { self.write().unwrap().singleton_buffer::().expect("") }