Compare commits
No commits in common. "6b2f8ee66f493a8501f255fb8420d4f279c589eb" and "3aec30e32abfbb4e2cef7aff1d1436e7e655f175" have entirely different histories.
6b2f8ee66f
...
3aec30e32a
29 changed files with 906 additions and 494 deletions
|
@ -5,12 +5,11 @@ name = "nested"
|
|||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
#r3vi = { git = "https://git.exobiont.de/senvas/lib-r3vi.git" }
|
||||
r3vi = { path = "../../lib-r3vi" }
|
||||
laddertypes = { path = "../../lib-laddertypes" }
|
||||
#r3vi = { git = "https://git.exobiont.de/senvas/r3vi.git" }
|
||||
r3vi = { path = "../../r3vi" }
|
||||
no_deadlocks = "*"
|
||||
cgmath = { version = "0.18.0", features = ["serde"] }
|
||||
termion = "2.0.1"
|
||||
termion = "1.5.5"
|
||||
vte = "0.10.1"
|
||||
ansi_colours = "1.0"
|
||||
signal-hook = "0.3.1"
|
||||
|
|
|
@ -6,9 +6,8 @@ use {
|
|||
},
|
||||
buffer::singleton::*
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context, ReprTree},
|
||||
type_system::{Context, ReprTree, TypeTerm},
|
||||
terminal::{TerminalAtom},
|
||||
tree::{NestedNode, TreeNavResult},
|
||||
commander::{ObjCommander}
|
||||
|
@ -20,8 +19,8 @@ use {
|
|||
pub fn init_ctx( ctx: &mut Context ) {
|
||||
ctx.add_node_ctor(
|
||||
"Char",
|
||||
Arc::new(|ctx: Arc<RwLock<Context>>, _ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| {
|
||||
Some(CharEditor::new_node(ctx, depth))
|
||||
Arc::new(|ctx: Arc<RwLock<Context>>, _ty: TypeTerm, _depth: usize| {
|
||||
Some(CharEditor::new_node(ctx))
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -35,7 +34,7 @@ impl ObjCommander for CharEditor {
|
|||
let cmd_obj = cmd_obj.read().unwrap();
|
||||
let cmd_type = cmd_obj.get_type().clone();
|
||||
|
||||
if cmd_type == Context::parse(&self.ctx, "Char") {
|
||||
if cmd_type == (&self.ctx, "( Char )").into() {
|
||||
if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() {
|
||||
let value = cmd_view.get();
|
||||
|
||||
|
@ -70,7 +69,7 @@ impl CharEditor {
|
|||
self.get_port().get_view().unwrap().get()
|
||||
}
|
||||
|
||||
pub fn new_node(ctx0: Arc<RwLock<Context>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode {
|
||||
pub fn new_node(ctx0: Arc<RwLock<Context>>) -> NestedNode {
|
||||
let data = SingletonBuffer::new('\0');
|
||||
let ctx = ctx0.clone();
|
||||
let editor = Arc::new(RwLock::new(CharEditor{ ctx, data: data.clone() }));
|
||||
|
@ -78,14 +77,14 @@ impl CharEditor {
|
|||
NestedNode::new(
|
||||
ctx0.clone(),
|
||||
ReprTree::new_leaf(
|
||||
ctx0.read().unwrap().type_term_from_str("Char").unwrap(),
|
||||
ctx0.read().unwrap().type_term_from_str("( Char )").unwrap(),
|
||||
data.get_port().into()
|
||||
),
|
||||
depth
|
||||
0 // fixme
|
||||
)
|
||||
.set_view(data
|
||||
.get_port()
|
||||
.map(move |c| TerminalAtom::from(if c == '\0' { ' ' } else { c }))
|
||||
.map(move |c| TerminalAtom::from(c))
|
||||
.to_grid()
|
||||
)
|
||||
.set_cmd( editor.clone() )
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
|
||||
use {
|
||||
r3vi::{
|
||||
view::{OuterViewPort, singleton::*}
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context},
|
||||
type_system::{Context, TypeTerm},
|
||||
editors::{
|
||||
list::*,
|
||||
integer::*
|
||||
|
@ -24,7 +19,7 @@ pub fn init_ctx(ctx: &mut Context) {
|
|||
|
||||
ctx.add_node_ctor(
|
||||
"Digit", Arc::new(
|
||||
|ctx: Arc<RwLock<Context>>, ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| {
|
||||
|ctx: Arc<RwLock<Context>>, ty: TypeTerm, depth: usize| {
|
||||
match ty {
|
||||
TypeTerm::App(args) => {
|
||||
if args.len() > 1 {
|
||||
|
@ -55,6 +50,9 @@ pub fn init_ctx(ctx: &mut Context) {
|
|||
ctx.add_morphism(pattern,
|
||||
Arc::new(
|
||||
|mut node, dst_type| {
|
||||
let _depth = node.depth.get();
|
||||
let _editor = node.editor.get().unwrap().downcast::<RwLock<ListEditor>>().unwrap();
|
||||
|
||||
// todo: check src_type parameter to be ( Digit radix )
|
||||
|
||||
match dst_type {
|
||||
|
@ -89,7 +87,7 @@ pub fn init_ctx(ctx: &mut Context) {
|
|||
|
||||
ctx.add_node_ctor(
|
||||
"PosInt", Arc::new(
|
||||
|ctx0: Arc<RwLock<Context>>, dst_typ: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| {
|
||||
|ctx0: Arc<RwLock<Context>>, dst_typ: TypeTerm, depth: usize| {
|
||||
match dst_typ.clone() {
|
||||
TypeTerm::App(args) => {
|
||||
if args.len() > 1 {
|
||||
|
@ -107,7 +105,7 @@ pub fn init_ctx(ctx: &mut Context) {
|
|||
.clone()
|
||||
.into()
|
||||
]),
|
||||
depth.map(|d| d+1)
|
||||
depth+1
|
||||
).unwrap();
|
||||
|
||||
node = node.morph(dst_typ);
|
||||
|
|
|
@ -10,9 +10,8 @@ use {
|
|||
index_hashmap::*
|
||||
}
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context, ReprTree},
|
||||
type_system::{Context, TypeTerm, ReprTree},
|
||||
editors::list::{ListCmd, PTYListController, PTYListStyle},
|
||||
terminal::{
|
||||
TerminalAtom, TerminalStyle, make_label
|
||||
|
@ -41,7 +40,7 @@ impl ObjCommander for DigitEditor {
|
|||
let cmd_obj = cmd_obj.read().unwrap();
|
||||
let cmd_type = cmd_obj.get_type().clone();
|
||||
|
||||
if cmd_type == Context::parse(&self.ctx, "Char") {
|
||||
if cmd_type == (&self.ctx, "( Char )").into() {
|
||||
if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() {
|
||||
let c = cmd_view.get();
|
||||
|
||||
|
@ -85,7 +84,7 @@ impl DigitEditor {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn into_node(self, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode {
|
||||
pub fn into_node(self, depth: usize) -> NestedNode {
|
||||
let data = self.get_data();
|
||||
let editor = Arc::new(RwLock::new(self));
|
||||
let ed = editor.write().unwrap();
|
||||
|
@ -100,7 +99,7 @@ impl DigitEditor {
|
|||
TerminalAtom::new(
|
||||
c.unwrap_or('?'),
|
||||
if c.unwrap_or('?').to_digit(r).is_some() {
|
||||
TerminalStyle::fg_color((90, 160, 90))
|
||||
TerminalStyle::fg_color((100, 140, 100))
|
||||
} else {
|
||||
//TerminalStyle::bg_color((90, 10, 10))
|
||||
TerminalStyle::fg_color((200, 40, 40))
|
||||
|
@ -126,7 +125,7 @@ impl DigitEditor {
|
|||
pub fn get_data(&self) -> Arc<RwLock<ReprTree>> {
|
||||
ReprTree::ascend(
|
||||
&ReprTree::new_leaf(
|
||||
self.ctx.read().unwrap().type_term_from_str("<Seq u32>").unwrap(),
|
||||
self.ctx.read().unwrap().type_term_from_str("( Seq u32 )").unwrap(),
|
||||
self.get_data_port().into()
|
||||
),
|
||||
self.get_type()
|
||||
|
@ -146,8 +145,8 @@ impl PosIntEditor {
|
|||
pub fn new(ctx: Arc<RwLock<Context>>, radix: u32) -> Self {
|
||||
let mut node = Context::make_node(
|
||||
&ctx,
|
||||
Context::parse(&ctx, format!("<List <Digit {}>>", radix).as_str()),
|
||||
r3vi::buffer::singleton::SingletonBuffer::new(0).get_port()
|
||||
(&ctx, format!("( List ( Digit {} ) )", radix).as_str()).into(),
|
||||
0
|
||||
).unwrap();
|
||||
|
||||
// Set Type
|
||||
|
|
|
@ -26,7 +26,7 @@ impl ListCmd {
|
|||
pub fn into_repr_tree(self, ctx: &Arc<RwLock<Context>>) -> Arc<RwLock<ReprTree>> {
|
||||
let buf = r3vi::buffer::singleton::SingletonBuffer::new(self);
|
||||
ReprTree::new_leaf(
|
||||
Context::parse(ctx, "ListCmd"),
|
||||
(ctx, "( ListCmd )"),
|
||||
buf.get_port().into()
|
||||
)
|
||||
}
|
||||
|
@ -58,8 +58,6 @@ impl ObjCommander for ListEditor {
|
|||
}
|
||||
|
||||
else if let Some(cmd) = cmd_repr.get_view::<dyn SingletonView<Item = ListCmd>>() {
|
||||
eprintln!("pty-list-editor some list cmmd");
|
||||
|
||||
let cur = self.cursor.get();
|
||||
drop(cmd_repr);
|
||||
|
||||
|
@ -73,53 +71,55 @@ impl ObjCommander for ListEditor {
|
|||
match cur.mode {
|
||||
ListCursorMode::Select => {
|
||||
if let Some(mut item) = self.get_item().clone() {
|
||||
let item_cur = item.get_cursor();
|
||||
|
||||
match cmd.get() {
|
||||
ListCmd::DeletePxev => {
|
||||
eprintln!("SELECT: delete pxev");
|
||||
if idx > 0
|
||||
&& item_cur.tree_addr.iter().fold(
|
||||
true,
|
||||
|is_zero, x| is_zero && (*x == 0)
|
||||
)
|
||||
{
|
||||
self.listlist_join_pxev(idx);
|
||||
if self.is_listlist() {
|
||||
let item_cur = item.get_cursor();
|
||||
|
||||
match cmd.get() {
|
||||
ListCmd::DeletePxev => {
|
||||
if idx > 0
|
||||
&& item_cur.tree_addr.iter().fold(
|
||||
true,
|
||||
|is_zero, x| is_zero && (*x == 0)
|
||||
)
|
||||
{
|
||||
self.listlist_join_pxev(idx);
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
item.send_cmd_obj(cmd_obj)
|
||||
}
|
||||
}
|
||||
|
||||
ListCmd::DeleteNexd => {
|
||||
let item_cur = item.get_cursor_warp();
|
||||
let next_idx = idx as usize + 1;
|
||||
|
||||
if next_idx < self.data.len()
|
||||
&& item_cur.tree_addr.iter().fold(
|
||||
true,
|
||||
|is_end, x| is_end && (*x == -1)
|
||||
)
|
||||
{
|
||||
self.listlist_join_nexd(idx as usize);
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
item.send_cmd_obj(cmd_obj)
|
||||
}
|
||||
}
|
||||
|
||||
ListCmd::Split => {
|
||||
self.listlist_split();
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
|
||||
_ => {
|
||||
item.send_cmd_obj(cmd_obj);
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
item.send_cmd_obj(cmd_obj)
|
||||
}
|
||||
}
|
||||
|
||||
ListCmd::DeleteNexd => {
|
||||
let item_cur = item.get_cursor_warp();
|
||||
let next_idx = idx as usize + 1;
|
||||
|
||||
if next_idx < self.data.len()
|
||||
&& item_cur.tree_addr.iter().fold(
|
||||
true,
|
||||
|is_end, x| is_end && (*x == -1)
|
||||
)
|
||||
{
|
||||
self.listlist_join_nexd(idx as usize);
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
item.send_cmd_obj(cmd_obj)
|
||||
}
|
||||
}
|
||||
|
||||
ListCmd::Split => {
|
||||
self.listlist_split();
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
|
||||
_ => {
|
||||
item.send_cmd_obj(cmd_obj);
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
} else {
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
} else {
|
||||
eprintln!("ptylist: no item");
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
},
|
||||
|
@ -127,7 +127,6 @@ impl ObjCommander for ListEditor {
|
|||
ListCursorMode::Insert => {
|
||||
match cmd.get() {
|
||||
ListCmd::DeletePxev => {
|
||||
eprintln!("INSERT: delete pxev");
|
||||
self.delete_pxev();
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
|
@ -150,19 +149,18 @@ impl ObjCommander for ListEditor {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
eprintln!("ptylist: cursor has no idx");
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if let Some(cur_item) = self.get_item_mut() {
|
||||
drop(cmd_repr);
|
||||
cur_item.write().unwrap().send_cmd_obj(cmd_obj);
|
||||
TreeNavResult::Continue
|
||||
cur_item.write().unwrap().send_cmd_obj(cmd_obj)
|
||||
} else {
|
||||
TreeNavResult::Exit
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use {
|
||||
r3vi::{view::{OuterViewPort, singleton::*}},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context},
|
||||
type_system::{Context, TypeTerm},
|
||||
editors::list::{ListEditor, PTYListController, PTYListStyle}
|
||||
},
|
||||
std::sync::{Arc, RwLock}
|
||||
|
@ -11,12 +9,12 @@ use {
|
|||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub fn init_ctx(ctx: &mut Context) {
|
||||
ctx.add_typename("ListCmd".into());
|
||||
ctx.add_list_typename("ListCmd".into());
|
||||
ctx.add_list_typename("List".into());
|
||||
|
||||
ctx.add_node_ctor(
|
||||
"List", Arc::new(
|
||||
|ctx: Arc<RwLock<Context>>, ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| {
|
||||
|ctx: Arc<RwLock<Context>>, ty: TypeTerm, depth: usize| {
|
||||
match ty {
|
||||
TypeTerm::App(args) => {
|
||||
if args.len() > 1 {
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{ViewPort, OuterViewPort, singleton::*, sequence::*},
|
||||
view::{OuterViewPort, singleton::*, sequence::*},
|
||||
buffer::{singleton::*, vec::*}
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context, ReprTree},
|
||||
type_system::{Context, TypeTerm, ReprTree},
|
||||
editors::list::{ListCursor, ListCursorMode, ListCmd},
|
||||
tree::{NestedNode, TreeNav, TreeCursor},
|
||||
diagnostics::Diagnostics,
|
||||
|
@ -23,12 +22,10 @@ pub struct ListEditor {
|
|||
pub data: VecBuffer< Arc<RwLock<NestedNode>> >,
|
||||
|
||||
pub spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>,
|
||||
|
||||
|
||||
pub(super) addr_port: OuterViewPort<dyn SequenceView<Item = isize>>,
|
||||
pub(super) mode_port: OuterViewPort<dyn SingletonView<Item = ListCursorMode>>,
|
||||
|
||||
depth: OuterViewPort<dyn SingletonView<Item = usize>>,
|
||||
|
||||
pub(crate) ctx: Arc<RwLock<Context>>,
|
||||
|
||||
/// item type
|
||||
|
@ -98,16 +95,13 @@ impl ListEditor {
|
|||
data,
|
||||
spillbuf: Arc::new(RwLock::new(Vec::new())),
|
||||
ctx,
|
||||
typ,
|
||||
depth: SingletonBuffer::new(0).get_port()
|
||||
typ
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_node(mut self, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode {
|
||||
pub fn into_node(self, depth: usize) -> NestedNode {
|
||||
let data = self.get_data();
|
||||
let ctx = self.ctx.clone();
|
||||
|
||||
self.depth = depth.clone();
|
||||
let editor = Arc::new(RwLock::new(self));
|
||||
|
||||
let e = editor.read().unwrap();
|
||||
|
@ -195,7 +189,6 @@ impl ListEditor {
|
|||
}
|
||||
}
|
||||
|
||||
/// is the element-type also a list-like editor (i.e. impls TreeNav)
|
||||
pub fn is_listlist(&self) -> bool {
|
||||
self.ctx.read().unwrap().is_list_type(&self.typ)
|
||||
}
|
||||
|
@ -234,12 +227,6 @@ impl ListEditor {
|
|||
|
||||
/// insert a new element
|
||||
pub fn insert(&mut self, item: Arc<RwLock<NestedNode>>) {
|
||||
eprintln!("list insert");
|
||||
|
||||
item.read().unwrap().depth.0.set_view(
|
||||
self.depth.map(|d| d+1).get_view()
|
||||
);
|
||||
|
||||
let mut cur = self.cursor.get();
|
||||
if let Some(idx) = cur.idx {
|
||||
match cur.mode {
|
||||
|
@ -248,9 +235,7 @@ impl ListEditor {
|
|||
if self.is_listlist() {
|
||||
cur.mode = ListCursorMode::Select;
|
||||
} else {
|
||||
eprintln!("list insert: is not a listlist ({:?})", self.typ);
|
||||
item.write().unwrap().goto(TreeCursor::none());
|
||||
cur.idx = Some(idx + 1);
|
||||
cur.idx = Some(idx + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,8 +254,7 @@ impl ListEditor {
|
|||
}
|
||||
|
||||
/// split the list off at the current cursor position and return the second half
|
||||
pub fn split(&mut self) {
|
||||
eprintln!("split");
|
||||
pub fn split(&mut self) {
|
||||
let cur = self.cursor.get();
|
||||
if let Some(idx) = cur.idx {
|
||||
let idx = idx as usize;
|
||||
|
@ -280,32 +264,10 @@ impl ListEditor {
|
|||
);
|
||||
self.data.remove(idx);
|
||||
}
|
||||
|
||||
/* in case the split leaves an empty item-list
|
||||
* as a last element, remove it
|
||||
*/
|
||||
/*
|
||||
if self.is_listlist() {
|
||||
if idx > 0 && idx < self.data.len()+1 {
|
||||
/* we are in insert mode,
|
||||
* get element before cursor
|
||||
*/
|
||||
let prev_idx = idx - 1;
|
||||
let prev_node = self.data.get(prev_idx);
|
||||
let prev_node = prev_node.read().unwrap();
|
||||
|
||||
if prev_node.get_data_view::<dyn SequenceView<Item = NestedNode>>(vec![].into_iter()).iter().count() == 0 {
|
||||
drop(prev_node);
|
||||
self.data.remove(prev_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
pub fn listlist_split(&mut self) {
|
||||
eprintln!("listlist split");
|
||||
let cur = self.get_cursor();
|
||||
|
||||
if let Some(mut item) = self.get_item().clone() {
|
||||
|
@ -318,15 +280,14 @@ impl ListEditor {
|
|||
self.nexd();
|
||||
|
||||
let mut b = item.spillbuf.write().unwrap();
|
||||
let mut tail_node = Context::make_node(&self.ctx, self.typ.clone(), self.depth.map(|d| d+1)).unwrap();
|
||||
let mut tail_node = Context::make_node(&self.ctx, self.typ.clone(), item.depth.get()).unwrap();
|
||||
tail_node.goto(TreeCursor::home());
|
||||
|
||||
for node in b.iter() {
|
||||
eprintln!("splid :send to tail node");
|
||||
tail_node
|
||||
.send_cmd_obj(
|
||||
ReprTree::new_leaf(
|
||||
Context::parse(&self.ctx, "NestedNode"),
|
||||
(&self.ctx, "( NestedNode )"),
|
||||
SingletonBuffer::<NestedNode>::new(
|
||||
node.read().unwrap().clone()
|
||||
).get_port().into()
|
||||
|
@ -338,7 +299,7 @@ impl ListEditor {
|
|||
drop(item);
|
||||
|
||||
tail_node.goto(TreeCursor::home());
|
||||
if cur.tree_addr.len() > 1 {
|
||||
if cur.tree_addr.len() > 2 {
|
||||
tail_node.dn();
|
||||
}
|
||||
|
||||
|
@ -380,7 +341,7 @@ impl ListEditor {
|
|||
for x in data.iter() {
|
||||
pxv_editor.send_cmd_obj(
|
||||
ReprTree::new_leaf(
|
||||
Context::parse(&self.ctx, "NestedNode"),
|
||||
(&self.ctx, "( NestedNode )"),
|
||||
SingletonBuffer::<NestedNode>::new(
|
||||
x.read().unwrap().clone()
|
||||
).get_port().into()
|
||||
|
@ -388,15 +349,13 @@ impl ListEditor {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
// fixme: is it oc0 or old_cur ??
|
||||
if oc0.tree_addr.len() > 1 {
|
||||
pxv_editor.goto(TreeCursor {
|
||||
tree_addr: vec![ old_cur.tree_addr[0], 0 ],
|
||||
leaf_mode: ListCursorMode::Insert
|
||||
});
|
||||
pxv_editor.send_cmd_obj(ListCmd::DeletePxev.into_repr_tree( &self.ctx ));
|
||||
} else if oc0.tree_addr.len() > 0 {
|
||||
} else {
|
||||
pxv_editor.goto(TreeCursor {
|
||||
tree_addr: vec![ old_cur.tree_addr[0] ],
|
||||
leaf_mode: ListCursorMode::Insert
|
||||
|
@ -439,7 +398,7 @@ impl ListEditor {
|
|||
for x in data.iter() {
|
||||
cur_editor.send_cmd_obj(
|
||||
ReprTree::new_leaf(
|
||||
Context::parse(&self.ctx, "NestedNode"),
|
||||
(&self.ctx, "( NestedNode )"),
|
||||
SingletonBuffer::<NestedNode>::new(
|
||||
x.read().unwrap().clone()
|
||||
).get_port().into()
|
||||
|
@ -447,20 +406,17 @@ impl ListEditor {
|
|||
);
|
||||
}
|
||||
|
||||
// fixme: is it oc0 or old_cur ??
|
||||
if oc0.tree_addr.len() > 1 {
|
||||
cur_editor.goto(TreeCursor {
|
||||
tree_addr: vec![ old_cur.tree_addr[0], -1 ],
|
||||
leaf_mode: ListCursorMode::Insert
|
||||
});
|
||||
cur_editor.send_cmd_obj(ListCmd::DeleteNexd.into_repr_tree( &self.ctx ));
|
||||
} else if oc0.tree_addr.len() > 0 {
|
||||
} else {
|
||||
cur_editor.goto(TreeCursor {
|
||||
tree_addr: vec![ old_cur.tree_addr[0] ],
|
||||
leaf_mode: ListCursorMode::Insert
|
||||
});
|
||||
} else {
|
||||
cur_editor.goto(TreeCursor::none());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -195,7 +195,6 @@ impl TreeNav for ListEditor {
|
|||
TreeNavResult::Exit
|
||||
} else if direction.y > 0 {
|
||||
// dn
|
||||
eprintln!("dn: data.len() = {}", self.data.len());
|
||||
self.cursor.set(ListCursor {
|
||||
mode: if self.data.len() > 0 { cur.leaf_mode } else { ListCursorMode::Insert },
|
||||
idx: Some(0)
|
||||
|
@ -211,7 +210,6 @@ impl TreeNav for ListEditor {
|
|||
1 => {
|
||||
if direction.y > 0 {
|
||||
// dn
|
||||
|
||||
if cur.tree_addr[0] < self.data.len() as isize {
|
||||
if self.data
|
||||
.get_mut(cur.tree_addr[0] as usize)
|
||||
|
@ -221,8 +219,7 @@ impl TreeNav for ListEditor {
|
|||
self.cursor.set(ListCursor {
|
||||
mode: ListCursorMode::Select,
|
||||
idx: Some(cur.tree_addr[0])
|
||||
});
|
||||
self.set_leaf_mode(cur.leaf_mode);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{ViewPort, OuterViewPort, sequence::*},
|
||||
view::{OuterViewPort, sequence::*},
|
||||
projection::decorate_sequence::*,
|
||||
},
|
||||
crate::{
|
||||
|
@ -18,20 +18,23 @@ use {
|
|||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub struct PTYListStyle {
|
||||
style: (String, String, String)
|
||||
style: (String, String, String),
|
||||
depth: usize
|
||||
}
|
||||
|
||||
impl PTYListStyle {
|
||||
pub fn new(style: (&str, &str, &str)) -> PTYListStyle {
|
||||
pub fn new(style: (&str, &str, &str), depth: usize) -> PTYListStyle {
|
||||
PTYListStyle {
|
||||
style: (style.0.into(), style.1.into(), style.2.into())
|
||||
style: (style.0.into(), style.1.into(), style.2.into()),
|
||||
depth
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_seg_seq_view(&self, editor: &ListEditor) -> OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>> {
|
||||
let seg_seq = ListSegmentSequence::new(
|
||||
editor.get_cursor_port(),
|
||||
editor.get_data_port()
|
||||
editor.get_data_port(),
|
||||
self.depth
|
||||
);
|
||||
let se = seg_seq.read().unwrap();
|
||||
se.get_view().map(move |segment| segment.pty_view())
|
||||
|
@ -40,7 +43,8 @@ impl PTYListStyle {
|
|||
pub fn pty_view(&self, editor: &ListEditor) -> OuterViewPort<dyn TerminalView> {
|
||||
let seg_seq = ListSegmentSequence::new(
|
||||
editor.get_cursor_port(),
|
||||
editor.get_data_port()
|
||||
editor.get_data_port(),
|
||||
self.depth
|
||||
);
|
||||
let seg_seq = seg_seq.read().unwrap();
|
||||
|
||||
|
@ -55,7 +59,7 @@ impl PTYListStyle {
|
|||
|
||||
pub fn for_node(node: &mut NestedNode, style: (&str, &str, &str)) {
|
||||
node.view = Some(
|
||||
Self::new(style)
|
||||
Self::new(style, node.depth.get())
|
||||
.pty_view(
|
||||
&node.get_edit::<ListEditor>().unwrap().read().unwrap()
|
||||
)
|
||||
|
@ -65,15 +69,13 @@ impl PTYListStyle {
|
|||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
// todo: rename to CharController
|
||||
|
||||
pub struct PTYListController {
|
||||
pub editor: Arc<RwLock<ListEditor>>,
|
||||
|
||||
split_char: Option<char>,
|
||||
close_char: Option<char>,
|
||||
|
||||
depth: OuterViewPort<dyn SingletonView<Item = usize>>
|
||||
depth: usize
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
@ -83,7 +85,7 @@ impl PTYListController {
|
|||
editor: Arc<RwLock<ListEditor>>,
|
||||
split_char: Option<char>,
|
||||
close_char: Option<char>,
|
||||
depth: OuterViewPort<dyn SingletonView<Item = usize>>
|
||||
depth: usize
|
||||
) -> Self {
|
||||
PTYListController {
|
||||
editor,
|
||||
|
@ -111,7 +113,7 @@ impl PTYListController {
|
|||
}
|
||||
|
||||
let editor = node.get_edit::<ListEditor>().unwrap();
|
||||
let controller = Arc::new(RwLock::new(PTYListController::from_editor( editor, split_char, close_char, node.depth.clone() )));
|
||||
let controller = Arc::new(RwLock::new(PTYListController::from_editor( editor, split_char, close_char, node.depth.get() )));
|
||||
|
||||
node.cmd.set(Some(controller.clone()));
|
||||
node.close_char.set(close_char);
|
||||
|
@ -129,6 +131,10 @@ impl PTYListController {
|
|||
self.editor.read().unwrap().get_item()
|
||||
}
|
||||
|
||||
pub fn set_depth(&mut self, depth: usize) {
|
||||
self.depth = depth;
|
||||
}
|
||||
|
||||
pub fn handle_term_event(&mut self, event: &TerminalEvent, _cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
|
||||
let mut e = self.editor.write().unwrap();
|
||||
match event {
|
||||
|
@ -149,7 +155,6 @@ impl PTYListController {
|
|||
// || Some(c) == child_close_char
|
||||
{
|
||||
e.listlist_split();
|
||||
eprintln!("done listlist split");
|
||||
TreeNavResult::Continue
|
||||
} else if Some(c) == child_close_char {
|
||||
e.goto(TreeCursor::none());
|
||||
|
@ -171,12 +176,12 @@ impl PTYListController {
|
|||
|
||||
match cur.mode {
|
||||
ListCursorMode::Insert => {
|
||||
let mut new_edit = Context::make_node(&e.ctx, e.typ.clone(), self.depth.map(|d| d+1)).unwrap();
|
||||
let mut new_edit = Context::make_node(&e.ctx, e.typ.clone(), self.depth+1).unwrap();
|
||||
new_edit.goto(TreeCursor::home());
|
||||
|
||||
match new_edit.send_cmd_obj(cmd_obj.clone()) {
|
||||
TreeNavResult::Continue => {
|
||||
e.insert(Arc::new(RwLock::new(new_edit.clone())));
|
||||
e.insert(Arc::new(RwLock::new(new_edit)));
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
TreeNavResult::Exit => {
|
||||
|
@ -189,12 +194,12 @@ impl PTYListController {
|
|||
let res = item.write().unwrap().send_cmd_obj(cmd_obj.clone());
|
||||
let child_close_char = item.read().unwrap().close_char.get();
|
||||
|
||||
match res {
|
||||
match res {
|
||||
TreeNavResult::Continue => TreeNavResult::Continue,
|
||||
TreeNavResult::Exit => {
|
||||
// child editor returned control, probably for meta-char handling..
|
||||
|
||||
if cmd_obj.read().unwrap().get_type().clone() == ctx.type_term_from_str("Char").unwrap() {
|
||||
if cmd_obj.read().unwrap().get_type().clone() == ctx.type_term_from_str("( Char )").unwrap() {
|
||||
let co = cmd_obj.read().unwrap();
|
||||
if let Some(cmd_view) = co.get_view::<dyn SingletonView<Item = char>>() {
|
||||
drop(co);
|
||||
|
@ -225,13 +230,13 @@ impl ObjCommander for PTYListController {
|
|||
let mut e = self.editor.write().unwrap();
|
||||
let cmd_type = cmd_obj.read().unwrap().get_type().clone();
|
||||
|
||||
if cmd_type == Context::parse(&e.ctx, "ListCmd").into()
|
||||
|| cmd_type == Context::parse(&e.ctx, "NestedNode").into()
|
||||
if cmd_type == (&e.ctx, "( ListCmd )").into()
|
||||
|| cmd_type == (&e.ctx, "( NestedNode )").into()
|
||||
{
|
||||
e.send_cmd_obj( cmd_obj )
|
||||
}
|
||||
|
||||
else if cmd_type == Context::parse(&e.ctx, "TerminalEvent").into() {
|
||||
else if cmd_type == (&e.ctx, "( TerminalEvent )").into() {
|
||||
let co = cmd_obj.read().unwrap();
|
||||
if let Some(view) = co.get_view::<dyn SingletonView<Item = TerminalEvent>>() {
|
||||
drop( co );
|
||||
|
|
|
@ -22,6 +22,7 @@ pub enum ListSegment {
|
|||
InsertCursor,
|
||||
Item {
|
||||
editor: NestedNode,
|
||||
depth: usize,
|
||||
cur_dist: isize,
|
||||
}
|
||||
}
|
||||
|
@ -36,8 +37,9 @@ impl PtySegment for ListSegment {
|
|||
.add_style_front(TerminalStyle::bold(true))
|
||||
})
|
||||
}
|
||||
ListSegment::Item{ editor, cur_dist } => {
|
||||
ListSegment::Item{ editor, depth, cur_dist } => {
|
||||
let e = editor.clone();
|
||||
let d = *depth;
|
||||
let cur_dist = *cur_dist;
|
||||
editor.get_view().map_item(move |_pt, atom| {
|
||||
let c = e.get_cursor();
|
||||
|
@ -48,11 +50,10 @@ impl PtySegment for ListSegment {
|
|||
} else {
|
||||
usize::MAX
|
||||
};
|
||||
|
||||
atom
|
||||
.add_style_back(bg_style_from_depth(select))
|
||||
.add_style_back(TerminalStyle::bold(select==1))
|
||||
.add_style_back(fg_style_from_depth(e.depth.get_view().get()))
|
||||
.add_style_back(fg_style_from_depth(d))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +64,7 @@ pub struct ListSegmentSequence {
|
|||
data: Arc<dyn SequenceView<Item = NestedNode>>,
|
||||
cursor: Arc<dyn SingletonView<Item = ListCursor>>,
|
||||
|
||||
depth: usize,
|
||||
cur_cursor: ListCursor,
|
||||
|
||||
port: ViewPort<dyn SequenceView<Item = ListSegment>>,
|
||||
|
@ -93,6 +95,7 @@ impl SequenceView for ListSegmentSequence {
|
|||
ListCursorMode::Select => {
|
||||
ListSegment::Item {
|
||||
editor: self.data.get(idx)?,
|
||||
depth: self.depth,
|
||||
cur_dist: cur - *idx as isize
|
||||
}
|
||||
}
|
||||
|
@ -100,6 +103,7 @@ impl SequenceView for ListSegmentSequence {
|
|||
if *idx < cur as usize {
|
||||
ListSegment::Item {
|
||||
editor: self.data.get(idx)?,
|
||||
depth: self.depth,
|
||||
cur_dist: cur - *idx as isize
|
||||
}
|
||||
} else if *idx == cur as usize {
|
||||
|
@ -107,6 +111,7 @@ impl SequenceView for ListSegmentSequence {
|
|||
} else {
|
||||
ListSegment::Item {
|
||||
editor: self.data.get(&(*idx - 1))?,
|
||||
depth: self.depth,
|
||||
cur_dist: cur - *idx as isize
|
||||
}
|
||||
}
|
||||
|
@ -115,6 +120,7 @@ impl SequenceView for ListSegmentSequence {
|
|||
} else {
|
||||
ListSegment::Item {
|
||||
editor: self.data.get(&idx)?,
|
||||
depth: self.depth,
|
||||
cur_dist: *idx as isize + 1
|
||||
}
|
||||
})
|
||||
|
@ -125,12 +131,14 @@ impl ListSegmentSequence {
|
|||
pub fn new(
|
||||
cursor_port: OuterViewPort<dyn SingletonView<Item = ListCursor>>,
|
||||
data_port: OuterViewPort<dyn SequenceView<Item = NestedNode>>,
|
||||
depth: usize
|
||||
) -> Arc<RwLock<Self>> {
|
||||
let out_port = ViewPort::new();
|
||||
let mut proj_helper = ProjectionHelper::new(out_port.update_hooks.clone());
|
||||
let proj = Arc::new(RwLock::new(ListSegmentSequence {
|
||||
cur_cursor: cursor_port.get_view().get(),
|
||||
port: out_port.clone(),
|
||||
depth,
|
||||
|
||||
cursor: proj_helper.new_singleton_arg(0, cursor_port, |s: &mut Self, _msg| {
|
||||
let _old_cursor = s.cur_cursor;
|
||||
|
|
|
@ -9,9 +9,8 @@ use {
|
|||
index_hashmap::*
|
||||
}
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context},
|
||||
type_system::{Context, TypeTerm},
|
||||
terminal::{
|
||||
TerminalEditor, TerminalEditorResult,
|
||||
TerminalEvent, TerminalView
|
||||
|
@ -203,7 +202,7 @@ impl ObjCommander for ProductEditor {
|
|||
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
|
||||
let co = cmd_obj.read().unwrap();
|
||||
let cmd_type = co.get_type().clone();
|
||||
let term_event_type = Context::parse(&self.ctx, "TerminalEvent").into();
|
||||
let term_event_type = (&self.ctx, "( TerminalEvent )").into();
|
||||
|
||||
if cmd_type == term_event_type {
|
||||
if let Some(te_view) = co.get_view::<dyn SingletonView<Item = TerminalEvent>>() {
|
||||
|
@ -239,7 +238,7 @@ impl ObjCommander for ProductEditor {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
let mut e = Context::make_node(&self.ctx, t.clone(), r3vi::buffer::singleton::SingletonBuffer::new(*ed_depth).get_port()).unwrap();
|
||||
let mut e = Context::make_node(&self.ctx, t.clone(), *ed_depth+1).unwrap();
|
||||
*editor = Some(e.clone());
|
||||
update_segment = true;
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ impl TreeNav for ProductEditor {
|
|||
e.goto(c.clone());
|
||||
} else if c.tree_addr.len() > 0 {
|
||||
// create editor
|
||||
let mut e = Context::make_node(&self.ctx, t.clone(), r3vi::buffer::singleton::SingletonBuffer::new(*ed_depth+1).get_port()).unwrap();
|
||||
let mut e = Context::make_node(&self.ctx, t.clone(), *ed_depth+1).unwrap();
|
||||
*editor = Some(e.clone());
|
||||
e.goto(c.clone());
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ impl TreeNav for ProductEditor {
|
|||
} else {
|
||||
// create editor
|
||||
|
||||
let mut e = Context::make_node(&self.ctx, t.clone(), r3vi::buffer::singleton::SingletonBuffer::new(*ed_depth+1).get_port()).unwrap();
|
||||
let mut e = Context::make_node(&self.ctx, t.clone(), *ed_depth+1).unwrap();
|
||||
*editor = Some(e.clone());
|
||||
e.goby(direction);
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ use {
|
|||
OuterViewPort
|
||||
}
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context},
|
||||
type_system::{Context, TypeTerm},
|
||||
terminal::{
|
||||
TerminalStyle, TerminalView,
|
||||
make_label
|
||||
|
|
|
@ -6,11 +6,10 @@ use {
|
|||
sequence::*,
|
||||
}
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
terminal::TerminalView,
|
||||
editors::list::ListCursorMode,
|
||||
type_system::{Context, ReprTree},
|
||||
type_system::{Context, TypeTerm, ReprTree},
|
||||
tree::{TreeNav, TreeCursor, TreeNavResult},
|
||||
diagnostics::{Diagnostics, Message},
|
||||
tree::NestedNode,
|
||||
|
@ -61,7 +60,7 @@ impl SumEditor {
|
|||
NestedNode::new(
|
||||
ctx.clone(),
|
||||
ReprTree::new_arc(TypeTerm::TypeID(ctx.read().unwrap().get_typeid("Sum").unwrap())),
|
||||
r3vi::buffer::singleton::SingletonBuffer::new(0).get_port()
|
||||
0
|
||||
)
|
||||
.set_view(view)
|
||||
.set_editor(editor.clone())
|
||||
|
|
|
@ -3,8 +3,8 @@ use {
|
|||
view::{singleton::*}
|
||||
},
|
||||
crate::{
|
||||
type_system::{Context, ReprTree},
|
||||
editors::{list::{ListEditor, ListCmd, ListCursorMode}},
|
||||
type_system::{ReprTree},
|
||||
editors::{list::{ListEditor, ListCmd}},
|
||||
tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor},
|
||||
commander::ObjCommander
|
||||
},
|
||||
|
@ -20,7 +20,7 @@ impl ObjCommander for TypeTermEditor {
|
|||
let cmd_obj = co.clone();
|
||||
let cmd_obj = cmd_obj.read().unwrap();
|
||||
|
||||
if cmd_obj.get_type().clone() == Context::parse(&self.ctx, "Char") {
|
||||
if cmd_obj.get_type().clone() == (&self.ctx, "( Char )").into() {
|
||||
if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() {
|
||||
let c = cmd_view.get();
|
||||
|
||||
|
@ -44,7 +44,7 @@ impl ObjCommander for TypeTermEditor {
|
|||
TreeNavResult::Exit
|
||||
}
|
||||
_ => {
|
||||
self.set_state( State::FunSymbol );
|
||||
self.set_state( State::AnySymbol );
|
||||
self.cur_node.get_mut().goto(TreeCursor::home());
|
||||
self.send_child_cmd( co )
|
||||
}
|
||||
|
@ -52,138 +52,71 @@ impl ObjCommander for TypeTermEditor {
|
|||
}
|
||||
|
||||
State::Char => {
|
||||
match self.send_child_cmd( co ) {
|
||||
TreeNavResult::Exit => {
|
||||
match c {
|
||||
'\'' => {
|
||||
self.cur_node.get_mut().goto(TreeCursor::none());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
match c {
|
||||
'\'' => {
|
||||
self.cur_node.get_mut().goto(TreeCursor::none());
|
||||
TreeNavResult::Exit
|
||||
},
|
||||
TreeNavResult::Continue => TreeNavResult::Continue
|
||||
}
|
||||
_ => {
|
||||
self.send_child_cmd( co )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
State::Ladder => {
|
||||
|
||||
match self.get_cursor().tree_addr.len() {
|
||||
|
||||
// entire term is selected
|
||||
0 => {
|
||||
match c {
|
||||
'<' => {
|
||||
self.morph_to_list(State::App);
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
_ => { TreeNavResult::Exit }
|
||||
}
|
||||
}
|
||||
|
||||
// entire item selected or insert mode
|
||||
1 => {
|
||||
let res = self.send_child_cmd( co.clone() );
|
||||
|
||||
match res {
|
||||
TreeNavResult::Continue => {
|
||||
match c {
|
||||
'~' => {
|
||||
// ignore '~' since we are already in a ladder
|
||||
// and cant split current item
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
_ => {
|
||||
self.send_child_cmd( co.clone() )
|
||||
self.normalize_nested_ladder();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
|
||||
// some subterm
|
||||
_ => {
|
||||
TreeNavResult::Exit => {
|
||||
match c {
|
||||
'~' => {
|
||||
let i0 = self.cur_node.get().get_edit::<ListEditor>().unwrap();
|
||||
let cur_it = i0.clone().read().unwrap().get_item().clone();
|
||||
if let Some(i) = cur_it {
|
||||
let cur_tte = i.get_edit::<TypeTermEditor>().unwrap();
|
||||
if cur_tte.read().unwrap().state == State::App || cur_tte.read().unwrap().get_cursor().tree_addr.len() > 1 {
|
||||
self.send_child_cmd( co.clone() )
|
||||
} else {
|
||||
drop(cur_tte);
|
||||
drop(i);
|
||||
|
||||
self.send_child_cmd(
|
||||
ListCmd::Split.into_repr_tree( &self.ctx )
|
||||
)
|
||||
}
|
||||
} else {
|
||||
self.send_child_cmd( co.clone() )
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
self.send_child_cmd( co.clone() )
|
||||
}
|
||||
'~' => TreeNavResult::Continue,
|
||||
_ => TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
State::App => {
|
||||
let res = self.send_child_cmd( co.clone() );
|
||||
|
||||
match self.get_cursor().tree_addr.len() {
|
||||
|
||||
// entire Term is selected
|
||||
0 => {
|
||||
|
||||
match res {
|
||||
TreeNavResult::Exit => {
|
||||
match c {
|
||||
'~' => {
|
||||
self.morph_to_list(State::Ladder);
|
||||
self.goto(TreeCursor {
|
||||
tree_addr: vec![ -1 ],
|
||||
leaf_mode: ListCursorMode::Insert
|
||||
});
|
||||
self.previous_item_into_ladder();
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
'<' => {
|
||||
self.morph_to_list(State::App);
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
_ => {
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
},
|
||||
_ => {TreeNavResult::Exit}
|
||||
}
|
||||
|
||||
},
|
||||
TreeNavResult::Continue => {
|
||||
match c {
|
||||
'>'|
|
||||
' ' => {
|
||||
let i = self.cur_node.get().get_edit::<ListEditor>().unwrap();
|
||||
let i = i.read().unwrap();
|
||||
if let Some(i) = i.get_item() {
|
||||
let tte = i.get_edit::<TypeTermEditor>().unwrap();
|
||||
let mut tte = tte.write().unwrap();
|
||||
|
||||
// some item is selected
|
||||
_ => {
|
||||
match self.send_child_cmd( co.clone() ) {
|
||||
TreeNavResult::Exit => {
|
||||
match c {
|
||||
'~' => {
|
||||
self.previous_item_into_ladder();
|
||||
TreeNavResult::Continue
|
||||
},
|
||||
_ => {TreeNavResult::Exit}
|
||||
if tte.state == State::Ladder {
|
||||
tte.normalize_singleton();
|
||||
}
|
||||
}
|
||||
},
|
||||
TreeNavResult::Continue => {
|
||||
match c {
|
||||
'>'|
|
||||
' ' => {
|
||||
let i = self.cur_node.get().get_edit::<ListEditor>().unwrap();
|
||||
let i = i.read().unwrap();
|
||||
if let Some(i) = i.get_item() {
|
||||
let tte = i.get_edit::<TypeTermEditor>().unwrap();
|
||||
let mut tte = tte.write().unwrap();
|
||||
|
||||
if tte.state == State::Ladder {
|
||||
tte.normalize_singleton();
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -195,19 +128,11 @@ impl ObjCommander for TypeTermEditor {
|
|||
match res {
|
||||
TreeNavResult::Exit => {
|
||||
match c {
|
||||
'<' => {
|
||||
self.goto(TreeCursor::none());
|
||||
self.morph_to_list(State::App);
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
'~' => {
|
||||
self.morph_to_list(State::Ladder);
|
||||
self.set_addr(0);
|
||||
self.dn();
|
||||
self.morph_to_ladder();
|
||||
self.send_cmd_obj(
|
||||
ListCmd::Split.into_repr_tree( &self.ctx )
|
||||
);
|
||||
TreeNavResult::Continue
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
TreeNavResult::Exit
|
||||
|
@ -231,11 +156,11 @@ impl ObjCommander for TypeTermEditor {
|
|||
match &self.state {
|
||||
State::Any => {
|
||||
let cmd_repr = co.read().unwrap();
|
||||
if cmd_repr.get_type().clone() == Context::parse(&self.ctx, "NestedNode") {
|
||||
if cmd_repr.get_type().clone() == (&self.ctx, "( NestedNode )").into() {
|
||||
if let Some(view) = cmd_repr.get_view::<dyn SingletonView<Item = NestedNode>>() {
|
||||
let node = view.get();
|
||||
|
||||
if node.data.read().unwrap().get_type().clone() == Context::parse(&self.ctx, "Char") {
|
||||
if node.data.read().unwrap().get_type().clone() == (&self.ctx, "( Char )").into() {
|
||||
self.set_state( State::AnySymbol );
|
||||
} else {
|
||||
self.set_state( State::Ladder );
|
||||
|
@ -259,6 +184,7 @@ impl ObjCommander for TypeTermEditor {
|
|||
let res = self.send_child_cmd( co.clone() );
|
||||
|
||||
self.normalize_empty();
|
||||
|
||||
if let Some(cmd) = co.read().unwrap().get_view::<dyn SingletonView<Item = ListCmd>>() {
|
||||
match cmd.get() {
|
||||
ListCmd::Split => {
|
||||
|
|
|
@ -1,16 +1,8 @@
|
|||
use {
|
||||
r3vi::{
|
||||
view::{OuterViewPort, singleton::*}
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context, MorphismTypePattern},
|
||||
type_system::{Context, TypeTerm, MorphismTypePattern},
|
||||
terminal::{TerminalStyle, TerminalProjections},
|
||||
editors::{
|
||||
list::{PTYListStyle, PTYListController, ListEditor, ListSegmentSequence},
|
||||
typeterm::{State, TypeTermEditor}
|
||||
},
|
||||
PtySegment
|
||||
editors::{list::{PTYListStyle, PTYListController}, typeterm::{State, TypeTermEditor}}
|
||||
},
|
||||
std::{sync::{Arc, RwLock}},
|
||||
cgmath::{Point2}
|
||||
|
@ -33,7 +25,7 @@ pub fn init_ctx(ctx: &mut Context) {
|
|||
let ctx : Arc<RwLock<Context>> = Arc::new(RwLock::new(Context::with_parent(Some(node.ctx.clone()))));
|
||||
ctx.write().unwrap().meta_chars.push('~');
|
||||
|
||||
let new_node = TypeTermEditor::with_node( ctx, node.clone(), State::Any );
|
||||
let new_node = TypeTermEditor::with_node( ctx, node.depth.get(), node.clone(), State::Any );
|
||||
Some(new_node)
|
||||
}));
|
||||
|
||||
|
@ -42,29 +34,14 @@ pub fn init_ctx(ctx: &mut Context) {
|
|||
Arc::new(|mut node, _dst_type: _| {
|
||||
PTYListController::for_node( &mut node, Some('~'), None );
|
||||
|
||||
let vertical_view = true;
|
||||
let vertical_view = false;
|
||||
if vertical_view {
|
||||
let editor = node.get_edit::<crate::editors::list::ListEditor>().unwrap();
|
||||
let mut e = editor.write().unwrap();
|
||||
let seg_view = PTYListStyle::new( ("","~","") ).get_seg_seq_view( &mut e );
|
||||
let seg_view = PTYListStyle::new( ("","~",""), node.depth.get() ).get_seg_seq_view( &mut e );
|
||||
|
||||
node = node.set_view(
|
||||
seg_view.to_grid_vertical()
|
||||
.map_item(
|
||||
|pt,x|
|
||||
if pt.y > 0 {
|
||||
r3vi::buffer::vec::VecBuffer::with_data(vec![
|
||||
crate::terminal::make_label("~"),
|
||||
x.clone()
|
||||
])
|
||||
.get_port()
|
||||
.to_sequence()
|
||||
.to_grid_horizontal()
|
||||
.flatten()
|
||||
} else {
|
||||
x.clone()
|
||||
}
|
||||
).flatten()
|
||||
seg_view.to_grid_vertical().flatten()
|
||||
);
|
||||
} else {
|
||||
PTYListStyle::for_node( &mut node, ("","~","") );
|
||||
|
@ -94,7 +71,6 @@ pub fn init_ctx(ctx: &mut Context) {
|
|||
Arc::new(|mut node, _dst_type:_| {
|
||||
PTYListController::for_node( &mut node, Some(' '), None );
|
||||
PTYListStyle::for_node( &mut node, ("","","") );
|
||||
|
||||
Some(node)
|
||||
}));
|
||||
|
||||
|
@ -104,6 +80,11 @@ pub fn init_ctx(ctx: &mut Context) {
|
|||
PTYListController::for_node( &mut node, Some(' '), None );
|
||||
PTYListStyle::for_node( &mut node, ("","","") );
|
||||
|
||||
// display variables blue color
|
||||
if let Some(v) = node.view {
|
||||
node.view = Some(
|
||||
v.map_item(|_i,p| p.add_style_front(TerminalStyle::fg_color((5, 120, 240)))));
|
||||
}
|
||||
Some(node)
|
||||
}));
|
||||
|
||||
|
@ -116,7 +97,6 @@ pub fn init_ctx(ctx: &mut Context) {
|
|||
ctx.add_morphism(
|
||||
MorphismTypePattern { src_tyid: ctx.get_typeid("Char"), dst_tyid: ctx.get_typeid("Type::Lit::Char").unwrap() },
|
||||
Arc::new(|mut node, _dst_type:_| {
|
||||
node.ctx.write().unwrap().meta_chars = vec![ '\'' ];
|
||||
let mut grid = r3vi::buffer::index_hashmap::IndexBuffer::new();
|
||||
|
||||
grid.insert_iter(
|
||||
|
@ -137,7 +117,7 @@ pub fn init_ctx(ctx: &mut Context) {
|
|||
}));
|
||||
|
||||
ctx.add_node_ctor("Type", Arc::new(
|
||||
|ctx: Arc<RwLock<Context>>, _ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| {
|
||||
|ctx: Arc<RwLock<Context>>, _ty: TypeTerm, depth: usize| {
|
||||
Some(TypeTermEditor::new_node(ctx, depth))
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -6,12 +6,10 @@ pub use ctx::init_ctx;
|
|||
|
||||
use {
|
||||
r3vi::{
|
||||
view::{OuterViewPort, singleton::*},
|
||||
buffer::{singleton::*}
|
||||
},
|
||||
laddertypes::{TypeID, TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context, ReprTree},
|
||||
type_system::{Context, TypeID, TypeTerm, ReprTree},
|
||||
editors::{list::{ListCursorMode, ListEditor, ListCmd}},
|
||||
tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor},
|
||||
commander::ObjCommander
|
||||
|
@ -38,9 +36,8 @@ pub struct TypeTermEditor {
|
|||
data: Arc<RwLock<ReprTree>>,
|
||||
close_char: SingletonBuffer<Option<char>>,
|
||||
spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>,
|
||||
depth: OuterViewPort<dyn SingletonView<Item = usize>>,
|
||||
|
||||
buf: SingletonBuffer< TypeTerm >,
|
||||
depth: usize,
|
||||
|
||||
// editing/parsing state
|
||||
state: State,
|
||||
|
@ -50,8 +47,8 @@ pub struct TypeTermEditor {
|
|||
}
|
||||
|
||||
impl TypeTermEditor {
|
||||
pub fn from_type_term(ctx: Arc<RwLock<Context>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>, term: &TypeTerm) -> NestedNode {
|
||||
let mut node = TypeTermEditor::new_node(ctx.clone(), depth.clone());
|
||||
pub fn from_type_term(ctx: Arc<RwLock<Context>>, depth: usize, term: &TypeTerm) -> NestedNode {
|
||||
let mut node = TypeTermEditor::new_node(ctx.clone(), depth);
|
||||
node.goto(TreeCursor::home());
|
||||
|
||||
match term {
|
||||
|
@ -77,11 +74,11 @@ impl TypeTermEditor {
|
|||
let parent_ctx = editor.read().unwrap().cur_node.get().ctx.clone();
|
||||
|
||||
for x in args.iter() {
|
||||
let arg_node = TypeTermEditor::from_type_term( parent_ctx.clone(), depth.map(|d| d+1), x );
|
||||
let arg_node = TypeTermEditor::from_type_term( parent_ctx.clone(), depth+1, x );
|
||||
|
||||
node.send_cmd_obj(
|
||||
ReprTree::new_leaf(
|
||||
Context::parse(&ctx, "NestedNode"),
|
||||
(&ctx, "( NestedNode )"),
|
||||
SingletonBuffer::new(arg_node).get_port().into()
|
||||
)
|
||||
);
|
||||
|
@ -95,11 +92,11 @@ impl TypeTermEditor {
|
|||
let parent_ctx = editor.read().unwrap().cur_node.get().ctx.clone();
|
||||
|
||||
for x in args.iter() {
|
||||
let arg_node = TypeTermEditor::from_type_term( parent_ctx.clone(), depth.map(|d| d+1), x );
|
||||
let arg_node = TypeTermEditor::from_type_term( parent_ctx.clone(), depth+1, x );
|
||||
|
||||
node.send_cmd_obj(
|
||||
ReprTree::new_leaf(
|
||||
Context::parse(&ctx, "NestedNode"),
|
||||
(&ctx, "( NestedNode )"),
|
||||
SingletonBuffer::new(arg_node).get_port().into()
|
||||
)
|
||||
);
|
||||
|
@ -125,7 +122,7 @@ impl TypeTermEditor {
|
|||
editor.send_cmd_obj(ReprTree::from_char(&ctx, *c));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
node.goto(TreeCursor::none());
|
||||
node
|
||||
}
|
||||
|
@ -133,37 +130,38 @@ impl TypeTermEditor {
|
|||
fn set_state(&mut self, new_state: State) {
|
||||
let mut node = match new_state {
|
||||
State::Any => {
|
||||
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Char>"), self.depth.map(|x| x) ).unwrap()
|
||||
.morph( Context::parse(&self.ctx, "Type::Sym") )
|
||||
Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth ).unwrap()
|
||||
.morph( (&self.ctx, "( Type::Sym )").into() )
|
||||
|
||||
}
|
||||
State::App => {
|
||||
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Type>"), self.depth.map(|x| x) ).unwrap()
|
||||
.morph( Context::parse(&self.ctx, "Type::App") )
|
||||
Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth ).unwrap()
|
||||
.morph( (&self.ctx, "( Type::App )").into() )
|
||||
}
|
||||
State::Ladder => {
|
||||
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Type>"), self.depth.map(|x| x) ).unwrap()
|
||||
.morph( Context::parse(&self.ctx, "Type::Ladder") )
|
||||
Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth ).unwrap()
|
||||
.morph( (&self.ctx, "( Type::Ladder )").into() )
|
||||
}
|
||||
State::AnySymbol => {
|
||||
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Char>"), self.depth.map(|x| x) ).unwrap()
|
||||
.morph( Context::parse(&self.ctx, "Type::Sym") )
|
||||
Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth ).unwrap()
|
||||
.morph( (&self.ctx, "( Type::Sym )").into() )
|
||||
},
|
||||
State::FunSymbol => {
|
||||
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Char>"), self.depth.map(|x| x) ).unwrap()
|
||||
.morph( Context::parse(&self.ctx, "Type::Sym::Fun") )
|
||||
Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth ).unwrap()
|
||||
.morph( (&self.ctx, "( Type::Sym::Fun )").into() )
|
||||
},
|
||||
State::VarSymbol => {
|
||||
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Char>"), self.depth.map(|x| x) ).unwrap()
|
||||
.morph( Context::parse(&self.ctx, "Type::Sym::Var") )
|
||||
Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth ).unwrap()
|
||||
.morph( (&self.ctx, "( Type::Sym::Var )").into() )
|
||||
}
|
||||
State::Num => {
|
||||
crate::editors::integer::PosIntEditor::new(self.ctx.clone(), 10)
|
||||
.into_node()
|
||||
.morph( Context::parse(&self.ctx, "Type::Lit::Num") )
|
||||
.morph( (&self.ctx, "( Type::Lit::Num )").into() )
|
||||
}
|
||||
State::Char => {
|
||||
Context::make_node( &self.ctx, Context::parse(&self.ctx, "Char"), self.depth.map(|x| x) ).unwrap()
|
||||
.morph( Context::parse(&self.ctx, "Type::Lit::Char") )
|
||||
Context::make_node( &self.ctx, (&self.ctx, "( Char )").into(), self.depth ).unwrap()
|
||||
.morph( (&self.ctx, "( Type::Lit::Char )").into() )
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -175,37 +173,36 @@ impl TypeTermEditor {
|
|||
self.state = new_state;
|
||||
}
|
||||
|
||||
pub fn new_node(ctx: Arc<RwLock<Context>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode {
|
||||
pub fn new_node(ctx: Arc<RwLock<Context>>, depth: usize) -> NestedNode {
|
||||
let ctx : Arc<RwLock<Context>> = Arc::new(RwLock::new(Context::with_parent(Some(ctx))));
|
||||
ctx.write().unwrap().meta_chars.push('~');
|
||||
ctx.write().unwrap().meta_chars.push('<');
|
||||
|
||||
let mut symb_node = Context::make_node( &ctx, Context::parse(&ctx, "<List Char>"), depth ).unwrap();
|
||||
symb_node = symb_node.morph( Context::parse(&ctx, "Type::Sym") );
|
||||
let mut symb_node = Context::make_node( &ctx, (&ctx, "( List Char )").into(), depth ).unwrap();
|
||||
symb_node = symb_node.morph( (&ctx, "( Type::Sym )").into() );
|
||||
|
||||
Self::with_node(
|
||||
ctx.clone(),
|
||||
depth,
|
||||
symb_node,
|
||||
State::Any
|
||||
)
|
||||
}
|
||||
|
||||
fn with_node(ctx: Arc<RwLock<Context>>, cur_node: NestedNode, state: State) -> NestedNode {
|
||||
let buf = SingletonBuffer::<TypeTerm>::new( TypeTerm::unit() );
|
||||
fn with_node(ctx: Arc<RwLock<Context>>, depth: usize, node: NestedNode, state: State) -> NestedNode {
|
||||
let _buffer = SingletonBuffer::<Option<TypeTerm>>::new( None );
|
||||
|
||||
let data = Arc::new(RwLock::new(ReprTree::new(
|
||||
Context::parse(&ctx, "Type")
|
||||
(&ctx, "( Type )")
|
||||
)));
|
||||
|
||||
let editor = TypeTermEditor {
|
||||
ctx: ctx.clone(),
|
||||
data: data.clone(),
|
||||
state,
|
||||
buf,
|
||||
cur_node: SingletonBuffer::new(cur_node.clone()),
|
||||
cur_node: SingletonBuffer::new(node),
|
||||
close_char: SingletonBuffer::new(None),
|
||||
spillbuf: Arc::new(RwLock::new(Vec::new())),
|
||||
depth: cur_node.depth.clone()
|
||||
depth
|
||||
};
|
||||
|
||||
let view = editor.cur_node
|
||||
|
@ -218,16 +215,16 @@ impl TypeTermEditor {
|
|||
let _cc = editor.cur_node.get().close_char;
|
||||
let editor = Arc::new(RwLock::new(editor));
|
||||
|
||||
let mut super_node = NestedNode::new(ctx, data, cur_node.depth)
|
||||
let mut node = NestedNode::new(ctx, data, depth)
|
||||
.set_view(view)
|
||||
.set_nav(editor.clone())
|
||||
.set_cmd(editor.clone())
|
||||
.set_editor(editor.clone());
|
||||
|
||||
editor.write().unwrap().close_char = super_node.close_char.clone();
|
||||
super_node.spillbuf = editor.read().unwrap().spillbuf.clone();
|
||||
|
||||
super_node
|
||||
editor.write().unwrap().close_char = node.close_char.clone();
|
||||
node.spillbuf = editor.read().unwrap().spillbuf.clone();
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
fn forward_spill(&mut self) {
|
||||
|
@ -291,34 +288,71 @@ impl TypeTermEditor {
|
|||
|
||||
let subladder_list_edit = subladder_list_edit.read().unwrap();
|
||||
if subladder_list_edit.data.len() == 0 {
|
||||
|
||||
self.set_state( State::Any );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* unwrap a ladder if it only contains one element
|
||||
*/
|
||||
pub fn normalize_singleton(&mut self) {
|
||||
eprintln!("normalize singleton");
|
||||
let subladder_list_node = self.cur_node.get().clone();
|
||||
let subladder_list_edit = subladder_list_node.get_edit::<ListEditor>().unwrap();
|
||||
|
||||
if self.state == State::Ladder {
|
||||
let subladder_list_node = self.cur_node.get().clone();
|
||||
let subladder_list_edit = subladder_list_node.get_edit::<ListEditor>().unwrap();
|
||||
let subladder_list_edit = subladder_list_edit.read().unwrap();
|
||||
if subladder_list_edit.data.len() == 1 {
|
||||
let it_node = subladder_list_edit.data.get(0);
|
||||
let it_node = it_node.read().unwrap();
|
||||
if it_node.get_type() == (&self.ctx, "( Type )").into() {
|
||||
let other_tt = it_node.get_edit::<TypeTermEditor>().unwrap();
|
||||
|
||||
let subladder_list_edit = subladder_list_edit.read().unwrap();
|
||||
if subladder_list_edit.data.len() == 1 {
|
||||
let it_node = subladder_list_edit.data.get(0);
|
||||
let it_node = it_node.read().unwrap();
|
||||
if it_node.get_type() == Context::parse(&self.ctx, "Type") {
|
||||
let other_tt = it_node.get_edit::<TypeTermEditor>().unwrap();
|
||||
let mut other_tt = other_tt.write().unwrap();
|
||||
|
||||
let mut other_tt = other_tt.write().unwrap();
|
||||
other_tt.normalize_singleton();
|
||||
|
||||
other_tt.normalize_singleton();
|
||||
other_tt.depth.0.set_view( self.depth.map(|x| x).get_view() );
|
||||
self.close_char.set(other_tt.close_char.get());
|
||||
self.cur_node.set(other_tt.cur_node.get());
|
||||
self.state = other_tt.state;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
self.close_char.set(other_tt.close_char.get());
|
||||
self.cur_node.set(other_tt.cur_node.get());
|
||||
self.state = other_tt.state;
|
||||
/* flatten ladder of ladders into one ladder editor
|
||||
*/
|
||||
pub fn normalize_nested_ladder(&mut self) {
|
||||
let mut subladder_list_node = self.cur_node.get().clone();
|
||||
let subladder_list_edit = subladder_list_node.get_edit::<ListEditor>().unwrap();
|
||||
|
||||
let item = subladder_list_edit.write().unwrap().get_item().clone();
|
||||
|
||||
if let Some(it_node) = item {
|
||||
if it_node.get_type() == (&self.ctx, "( Type )").into() {
|
||||
let other_tt = it_node.get_edit::<TypeTermEditor>().unwrap();
|
||||
|
||||
if other_tt.write().unwrap().state == State::Ladder {
|
||||
let other = other_tt.read().unwrap().cur_node.get().get_edit::<ListEditor>().unwrap();
|
||||
let buf = other.read().unwrap().data.clone();
|
||||
|
||||
subladder_list_edit.write().unwrap().up();
|
||||
subladder_list_edit.write().unwrap().up();
|
||||
subladder_list_node.send_cmd_obj(
|
||||
ListCmd::DeleteNexd.into_repr_tree( &self.ctx )
|
||||
);
|
||||
|
||||
if subladder_list_edit.read().unwrap().get_cursor_warp().tree_addr.len() > 0 {
|
||||
if subladder_list_edit.read().unwrap().get_cursor_warp().tree_addr[0] == -1 {
|
||||
subladder_list_edit.write().unwrap().delete_nexd();
|
||||
}
|
||||
}
|
||||
|
||||
let l = buf.len();
|
||||
for i in 0..l {
|
||||
subladder_list_edit.write().unwrap().insert( buf.get(i) );
|
||||
}
|
||||
subladder_list_node.dn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -337,58 +371,96 @@ impl TypeTermEditor {
|
|||
app_edit.delete_nexd();
|
||||
}
|
||||
|
||||
// select previous element
|
||||
app_edit.goto(TreeCursor{
|
||||
tree_addr: vec![ cur.tree_addr[0]-1 ],
|
||||
leaf_mode: ListCursorMode::Select
|
||||
});
|
||||
|
||||
// get selected element
|
||||
if let Some(item_node) = app_edit.get_item() {
|
||||
|
||||
if let Some(item_node) = app_edit.get_item() {
|
||||
let item_typterm = item_node.get_edit::<TypeTermEditor>().expect("typetermedit");
|
||||
let mut item_typterm = item_typterm.write().unwrap();
|
||||
if item_typterm.state != State::Ladder {
|
||||
item_typterm.morph_to_list( State::Ladder );
|
||||
}
|
||||
match item_typterm.state {
|
||||
|
||||
item_typterm.goto(TreeCursor {
|
||||
tree_addr: vec![ -1 ],
|
||||
leaf_mode: ListCursorMode::Insert
|
||||
});
|
||||
// if item at cursor is Ladder
|
||||
State::Ladder => {
|
||||
drop(item_typterm);
|
||||
|
||||
app_edit.dn();
|
||||
app_edit.qnexd();
|
||||
}
|
||||
_ => {
|
||||
item_typterm.goto(TreeCursor::none());
|
||||
drop(item_typterm);
|
||||
|
||||
// else create new ladder
|
||||
let mut list_node = Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth ).unwrap();
|
||||
list_node = list_node.morph( (&self.ctx, "( Type::Ladder )").into() );
|
||||
|
||||
let mut new_node = TypeTermEditor::with_node(
|
||||
self.ctx.clone(),
|
||||
self.depth,
|
||||
list_node,
|
||||
State::Ladder
|
||||
);
|
||||
|
||||
// insert old node and split
|
||||
new_node.goto(TreeCursor::home());
|
||||
|
||||
new_node.send_cmd_obj(
|
||||
ReprTree::new_leaf(
|
||||
(&self.ctx, "( NestedNode )"),
|
||||
SingletonBuffer::<NestedNode>::new( item_node ).get_port().into()
|
||||
)
|
||||
);
|
||||
|
||||
*app_edit.get_item_mut().unwrap().write().unwrap() = new_node;
|
||||
app_edit.dn();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* replace with new list-node (ladder/app) with self as first element
|
||||
|
||||
/* replace with new ladder node with self as first element
|
||||
*/
|
||||
pub(super) fn morph_to_list(&mut self, state: State) {
|
||||
pub fn morph_to_ladder(&mut self) {
|
||||
eprintln!("morph into ladder");
|
||||
let old_node = self.cur_node.get().clone();
|
||||
|
||||
let mut old_node = self.cur_node.get().clone();
|
||||
|
||||
/* reconfigure current node to display new_node list-editor
|
||||
*/
|
||||
self.set_state( state );
|
||||
*old_node.depth.get_mut() += 1;
|
||||
|
||||
/* create a new NestedNode with TerminaltypeEditor,
|
||||
* that has same state & child-node as current node.
|
||||
*/
|
||||
let old_edit_node = TypeTermEditor::new_node( self.ctx.clone(), SingletonBuffer::new(0).get_port() );
|
||||
old_node.depth.0.set_view( old_edit_node.depth.map(|x|x).get_view() );
|
||||
|
||||
let old_edit_node = TypeTermEditor::new_node( self.ctx.clone(), self.depth );
|
||||
let old_edit_clone = old_edit_node.get_edit::<TypeTermEditor>().unwrap();
|
||||
old_edit_clone.write().unwrap().set_state( self.state );
|
||||
old_edit_clone.write().unwrap().close_char.set( old_node.close_char.get() );
|
||||
old_edit_clone.write().unwrap().cur_node.set( old_node );
|
||||
|
||||
/* create new list-edit node for the ladder
|
||||
*/
|
||||
let mut new_node = Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth ).unwrap();
|
||||
new_node = new_node.morph( (&self.ctx, "( Type::Ladder )").into() );
|
||||
|
||||
/* reconfigure current node to display new_node list-editor
|
||||
*/
|
||||
self.close_char.set(new_node.close_char.get());
|
||||
self.cur_node.set(new_node);
|
||||
self.state = State::Ladder;
|
||||
|
||||
/* insert old node and split
|
||||
*/
|
||||
self.goto(TreeCursor::home());
|
||||
self.send_child_cmd(
|
||||
self.send_cmd_obj(
|
||||
ReprTree::new_leaf(
|
||||
Context::parse(&self.ctx, "NestedNode"),
|
||||
(&self.ctx, "( NestedNode )"),
|
||||
SingletonBuffer::new( old_edit_node ).get_port().into()
|
||||
)
|
||||
);
|
||||
|
||||
self.set_addr(0);
|
||||
self.dn();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,3 +42,4 @@ impl TreeNav for TypeTermEditor {
|
|||
self.cur_node.get_mut().goto(new_cur)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,17 +24,6 @@ impl TreeCursor {
|
|||
tree_addr: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_subcursor(&self, depth: usize) -> TreeCursor {
|
||||
TreeCursor {
|
||||
leaf_mode: self.leaf_mode,
|
||||
tree_addr: if depth < self.tree_addr.len() {
|
||||
self.tree_addr[ depth.. ].iter().cloned().collect()
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TreeCursor {
|
||||
|
|
|
@ -21,10 +21,10 @@ use {
|
|||
cgmath::Vector2,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
pub enum TreeNavResult { Continue, Exit }
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
pub enum TreeHeightOp { P, Q, Max }
|
||||
|
||||
pub trait TreeNav {
|
||||
|
@ -181,4 +181,3 @@ pub trait TreeNav {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,9 +5,8 @@ use {
|
|||
view::{View, ViewPort, OuterViewPort, AnyOuterViewPort, singleton::*, sequence::*},
|
||||
buffer::{singleton::*}
|
||||
},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
type_system::{ReprTree, Context},
|
||||
type_system::{ReprTree, Context, TypeTerm},
|
||||
terminal::{TerminalView, TerminalEvent, TerminalEditor, TerminalEditorResult, TerminalAtom},
|
||||
diagnostics::{Diagnostics, Message},
|
||||
tree::{TreeNav, TreeCursor, TreeNavResult, TreeHeightOp},
|
||||
|
@ -33,15 +32,18 @@ struct NestedNodeEdit {
|
|||
/// abstract editor
|
||||
pub editor: SingletonBuffer<
|
||||
Option< Arc<dyn Any + Send + Sync> >
|
||||
>,
|
||||
>,
|
||||
|
||||
pub spillbuf: VecBuffer< NestedNode >,
|
||||
pub input_buf:: VecBuffer< NestedNode >,
|
||||
pub output_buf: VecBuffer< NestedNode >,
|
||||
|
||||
/// commander & navigation
|
||||
pub cmd: SingletonBuffer<
|
||||
Option< Arc<RwLock<dyn ObjCommander + Send + Sync>> >
|
||||
>,
|
||||
pub close_char: SingletonBuffer< Option< char > >,
|
||||
pub close_char: SingletonBuffer<
|
||||
Option< char >
|
||||
>,
|
||||
|
||||
// could be replaced by cmd when TreeNav -CmdObjects are used
|
||||
pub tree_nav: SingletonBuffer<
|
||||
|
@ -80,13 +82,16 @@ pub struct NestedNode {
|
|||
pub diag: Option< OuterViewPort<dyn SequenceView<Item = Message>> >,
|
||||
|
||||
/// depth
|
||||
pub depth: OuterViewPort< dyn SingletonView<Item = usize> >,
|
||||
pub depth: SingletonBuffer< usize >,
|
||||
|
||||
/// abstract editor
|
||||
pub editor: SingletonBuffer<
|
||||
Option< Arc<dyn Any + Send + Sync> >
|
||||
>,
|
||||
|
||||
/* TODO:
|
||||
* - spill buffer (contains overflowing elements as well as 'split-off' parts)
|
||||
*/
|
||||
pub spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>,
|
||||
|
||||
/// commander & navigation
|
||||
|
@ -102,13 +107,13 @@ pub struct NestedNode {
|
|||
}
|
||||
|
||||
impl NestedNode {
|
||||
pub fn new(ctx: Arc<RwLock<Context>>, data: Arc<RwLock<ReprTree>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> Self {
|
||||
pub fn new(ctx: Arc<RwLock<Context>>, data: Arc<RwLock<ReprTree>>, depth: usize) -> Self {
|
||||
NestedNode {
|
||||
ctx,
|
||||
data,
|
||||
view: None,
|
||||
diag: None,
|
||||
depth,
|
||||
depth: SingletonBuffer::new(depth),
|
||||
editor: SingletonBuffer::new(None),
|
||||
spillbuf: Arc::new(RwLock::new(Vec::new())),
|
||||
cmd: SingletonBuffer::new(None),
|
||||
|
@ -125,10 +130,10 @@ impl NestedNode {
|
|||
NestedNode::new(
|
||||
ctx.clone(),
|
||||
ReprTree::new_leaf(
|
||||
Context::parse(&ctx, "Char"),
|
||||
(&ctx, "( Char )"),
|
||||
buf.get_port().into()
|
||||
),
|
||||
SingletonBuffer::new(0).get_port()
|
||||
0
|
||||
)
|
||||
.set_view(buf.get_port()
|
||||
.map(|c| TerminalAtom::from(c))
|
||||
|
@ -195,7 +200,7 @@ impl NestedNode {
|
|||
pub fn get_data_port<'a, V: View + ?Sized + 'static>(&'a self, type_str: impl Iterator<Item = &'a str>) -> Option<OuterViewPort<V>>
|
||||
where V::Msg: Clone {
|
||||
let ctx = self.ctx.clone();
|
||||
let type_ladder = type_str.map(|s| Context::parse(&ctx, s));
|
||||
let type_ladder = type_str.map(|s| ((&ctx, s)).into());
|
||||
|
||||
let repr_tree = ReprTree::descend_ladder(&self.data, type_ladder)?;
|
||||
repr_tree.clone().read().unwrap()
|
||||
|
@ -257,7 +262,7 @@ impl TerminalEditor for NestedNode {
|
|||
if let Some(cmd) = self.cmd.get() {
|
||||
cmd.write().unwrap().send_cmd_obj(
|
||||
ReprTree::new_leaf(
|
||||
self.ctx.read().unwrap().type_term_from_str("TerminalEvent").unwrap(),
|
||||
self.ctx.read().unwrap().type_term_from_str("( TerminalEvent )").unwrap(),
|
||||
AnyOuterViewPort::from(buf.get_port())
|
||||
));
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
|
||||
use {
|
||||
laddertypes::{TypeTerm, TypeID},
|
||||
crate::{
|
||||
type_system::{TypeTerm, TypeID},
|
||||
tree::{TreeAddr}
|
||||
}
|
||||
};
|
||||
|
||||
pub trait TreeType {
|
||||
fn get_type(&self, addr: &TreeAddr) -> Vec<TypeTerm> {
|
||||
vec![]
|
||||
fn get_type(&self, _addr: &TreeAddr) -> TypeTerm {
|
||||
TypeTerm::new(TypeID::Var(0))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use {
|
||||
r3vi::{view::{OuterViewPort, singleton::*}, buffer::{singleton::*}},
|
||||
laddertypes::{TypeDict, TypeTerm, TypeID},
|
||||
crate::{
|
||||
type_system::{ReprTree},
|
||||
type_system::{TypeDict, TypeTerm, TypeID, ReprTree},
|
||||
tree::NestedNode
|
||||
},
|
||||
std::{
|
||||
|
@ -136,6 +134,12 @@ impl Default for Context {
|
|||
}
|
||||
}
|
||||
|
||||
impl Into<TypeTerm> for (&Arc<RwLock<Context>>, &str) {
|
||||
fn into(self) -> TypeTerm {
|
||||
self.0.read().unwrap().type_term_from_str(self.1).expect("could not parse type term")
|
||||
}
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn with_parent(parent: Option<Arc<RwLock<Context>>>) -> Self {
|
||||
Context {
|
||||
|
@ -169,10 +173,6 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse(ctx: &Arc<RwLock<Self>>, s: &str) -> TypeTerm {
|
||||
ctx.read().unwrap().type_term_from_str(s).expect("could not parse type term")
|
||||
}
|
||||
|
||||
pub fn add_typename(&mut self, tn: &str) -> TypeID {
|
||||
self.type_dict.write().unwrap().add_typename(tn.to_string())
|
||||
}
|
||||
|
@ -195,18 +195,6 @@ impl Context {
|
|||
TypeTerm::TypeID(id) => {
|
||||
self.list_types.contains(id)
|
||||
}
|
||||
TypeTerm::Ladder(args) |
|
||||
TypeTerm::App(args) => {
|
||||
if args.len() > 0 {
|
||||
if self.is_list_type(&args[0]) {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
@ -233,15 +221,15 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn type_term_from_str(&self, tn: &str) -> Result<TypeTerm, laddertypes::parser::ParseError> {
|
||||
self.type_dict.write().unwrap().parse(&tn)
|
||||
pub fn type_term_from_str(&self, tn: &str) -> Option<TypeTerm> {
|
||||
self.type_dict.read().unwrap().type_term_from_str(&tn)
|
||||
}
|
||||
|
||||
pub fn type_term_to_str(&self, t: &TypeTerm) -> String {
|
||||
self.type_dict.read().unwrap().unparse(&t)
|
||||
self.type_dict.read().unwrap().type_term_to_str(&t)
|
||||
}
|
||||
|
||||
pub fn add_node_ctor(&mut self, tn: &str, mk_editor: Arc<dyn Fn(Arc<RwLock<Self>>, TypeTerm, OuterViewPort<dyn SingletonView<Item = usize>>) -> Option<NestedNode> + Send + Sync>) {
|
||||
pub fn add_node_ctor(&mut self, tn: &str, mk_editor: Arc<dyn Fn(Arc<RwLock<Self>>, TypeTerm, usize) -> Option<NestedNode> + Send + Sync>) {
|
||||
let dict = self.type_dict.clone();
|
||||
let mut dict = dict.write().unwrap();
|
||||
|
||||
|
@ -260,7 +248,7 @@ impl Context {
|
|||
drop(dict);
|
||||
|
||||
self.add_morphism(morphism_pattern, Arc::new(move |node, dst_type| {
|
||||
mk_editor(node.ctx.clone(), dst_type, node.depth)
|
||||
mk_editor(node.ctx.clone(), dst_type, node.depth.get())
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -287,7 +275,7 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn make_node(ctx: &Arc<RwLock<Self>>, type_term: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> Option<NestedNode> {
|
||||
pub fn make_node(ctx: &Arc<RwLock<Self>>, type_term: TypeTerm, depth: usize) -> Option<NestedNode> {
|
||||
let mk_node = ctx.read().unwrap().get_morphism(MorphismType {
|
||||
src_type: None,
|
||||
dst_type: type_term.clone()
|
||||
|
@ -296,6 +284,7 @@ impl Context {
|
|||
/* create new context per node ?? too heavy.. whats the reason? TODO */
|
||||
|
||||
let new_ctx = Arc::new(RwLock::new(Context::with_parent(Some(ctx.clone()))));
|
||||
let _new_depth = depth;
|
||||
|
||||
mk_node(
|
||||
NestedNode::new(new_ctx, ReprTree::new_arc(type_term.clone()), depth),
|
||||
|
@ -331,10 +320,10 @@ impl Context {
|
|||
/// adds an object without any representations
|
||||
pub fn add_obj(ctx: Arc<RwLock<Context>>, name: String, typename: &str) {
|
||||
let type_tag = ctx.read().unwrap()
|
||||
.type_dict.write().unwrap()
|
||||
.parse(typename).unwrap();
|
||||
.type_dict.read().unwrap()
|
||||
.type_term_from_str(typename).unwrap();
|
||||
|
||||
if let Some(node) = Context::make_node(&ctx, type_tag, SingletonBuffer::new(0).get_port()) {
|
||||
if let Some(node) = Context::make_node(&ctx, type_tag, 0) {
|
||||
ctx.write().unwrap().nodes.insert(name, node);
|
||||
}
|
||||
}
|
||||
|
|
73
nested/src/type_system/dict.rs
Normal file
73
nested/src/type_system/dict.rs
Normal file
|
@ -0,0 +1,73 @@
|
|||
use {
|
||||
crate::{
|
||||
utils::Bimap,
|
||||
type_system::{TypeTerm}
|
||||
}
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Clone, Debug)]
|
||||
pub enum TypeID {
|
||||
Fun(u64),
|
||||
Var(u64)
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub struct TypeDict {
|
||||
typenames: Bimap<String, TypeID>,
|
||||
type_lit_counter: u64,
|
||||
type_var_counter: u64,
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
impl TypeDict {
|
||||
pub fn new() -> Self {
|
||||
TypeDict {
|
||||
typenames: Bimap::new(),
|
||||
type_lit_counter: 0,
|
||||
type_var_counter: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_varname(&mut self, tn: String) -> TypeID {
|
||||
let tyid = TypeID::Var(self.type_var_counter);
|
||||
self.type_var_counter += 1;
|
||||
self.typenames.insert(tn, tyid.clone());
|
||||
tyid
|
||||
}
|
||||
|
||||
pub fn add_typename(&mut self, tn: String) -> TypeID {
|
||||
let tyid = TypeID::Fun(self.type_lit_counter);
|
||||
self.type_lit_counter += 1;
|
||||
self.typenames.insert(tn, tyid.clone());
|
||||
tyid
|
||||
}
|
||||
|
||||
pub fn add_synonym(&mut self, new: String, old: String) {
|
||||
if let Some(tyid) = self.get_typeid(&old) {
|
||||
self.typenames.insert(new, tyid);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_typename(&self, tid: &TypeID) -> Option<String> {
|
||||
self.typenames.my.get(tid).cloned()
|
||||
}
|
||||
|
||||
pub fn get_typeid(&self, tn: &String) -> Option<TypeID> {
|
||||
self.typenames.mλ.get(tn).cloned()
|
||||
}
|
||||
|
||||
pub fn type_term_from_str(&self, typename: &str) -> Option<TypeTerm> {
|
||||
TypeTerm::from_str(typename, &self.typenames.mλ)
|
||||
}
|
||||
|
||||
pub fn type_term_to_str(&self, term: &TypeTerm) -> String {
|
||||
term.to_str(&self.typenames.my)
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
71
nested/src/type_system/ladder.rs
Normal file
71
nested/src/type_system/ladder.rs
Normal file
|
@ -0,0 +1,71 @@
|
|||
use {
|
||||
crate::type_system::{TypeTerm, TypeID},
|
||||
std::collections::HashMap
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct TypeLadder(pub Vec<TypeTerm>);
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
impl From<Vec<TypeTerm>> for TypeLadder {
|
||||
fn from(l: Vec<TypeTerm>) -> Self {
|
||||
TypeLadder(l)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TypeTerm> for TypeLadder {
|
||||
fn from(l: TypeTerm) -> Self {
|
||||
TypeLadder(vec![ l ])
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeLadder {
|
||||
/// if compatible, returns the number of descents neccesary
|
||||
pub fn is_compatible_with(&self, other: &TypeLadder) -> Option<usize> {
|
||||
if let Some(other_top_type) = other.0.first() {
|
||||
for (i, t) in self.0.iter().enumerate() {
|
||||
if t == other_top_type {
|
||||
return Some(i);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_matching_repr(&self, other: &TypeLadder) -> Result<usize, Option<(usize, usize)>> {
|
||||
if let Some(start) = self.is_compatible_with(other) {
|
||||
for (i, (t1, t2)) in self.0.iter().skip(start).zip(other.0.iter()).enumerate() {
|
||||
if t1 != t2 {
|
||||
return Err(Some((start, i)));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(start)
|
||||
} else {
|
||||
Err(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_str1(&self, names: &HashMap<TypeID, String>) -> String {
|
||||
let mut s = String::new();
|
||||
let mut first = true;
|
||||
|
||||
for t in self.0.iter() {
|
||||
if !first {
|
||||
s = s + "~";
|
||||
}
|
||||
first = false;
|
||||
s = s + &t.to_str(names);
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
|
@ -1,8 +1,15 @@
|
|||
pub mod context;
|
||||
|
||||
pub mod dict;
|
||||
pub mod term;
|
||||
//pub mod ladder;
|
||||
pub mod repr_tree;
|
||||
|
||||
pub use {
|
||||
context::{Context, MorphismMode, MorphismType, MorphismTypePattern},
|
||||
repr_tree::ReprTree
|
||||
dict::*,
|
||||
// ladder::*,
|
||||
repr_tree::*,
|
||||
term::*,
|
||||
context::{Context, MorphismMode, MorphismType, MorphismTypePattern}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use {
|
||||
r3vi::view::{AnyOuterViewPort, OuterViewPort, View},
|
||||
laddertypes::{TypeTerm},
|
||||
crate::{
|
||||
type_system::{Context}
|
||||
type_system::{TypeTerm, Context}
|
||||
},
|
||||
std::{
|
||||
collections::HashMap,
|
||||
|
@ -51,7 +50,7 @@ impl ReprTree {
|
|||
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"),
|
||||
(ctx, "( Char )"),
|
||||
buf.get_port().into()
|
||||
)
|
||||
}
|
||||
|
|
351
nested/src/type_system/term.rs
Normal file
351
nested/src/type_system/term.rs
Normal file
|
@ -0,0 +1,351 @@
|
|||
use {
|
||||
crate::{type_system::{TypeID}},
|
||||
std::collections::HashMap
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum TypeTerm {
|
||||
|
||||
/* Atomic Terms */
|
||||
|
||||
// Base types from dictionary
|
||||
TypeID(TypeID),
|
||||
|
||||
// Literals
|
||||
Num(i64),
|
||||
Char(char),
|
||||
|
||||
|
||||
|
||||
/* Complex Terms */
|
||||
|
||||
// Type Parameters
|
||||
// avoid currying to save space & indirection
|
||||
App(Vec< TypeTerm >),
|
||||
|
||||
// Type Ladders
|
||||
Ladder(Vec< TypeTerm >),
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
impl TypeTerm {
|
||||
pub fn new(id: TypeID) -> Self {
|
||||
TypeTerm::TypeID(id)
|
||||
}
|
||||
|
||||
pub fn arg(&mut self, t: impl Into<TypeTerm>) -> &mut Self {
|
||||
match self {
|
||||
TypeTerm::App(args) => {
|
||||
args.push(t.into());
|
||||
}
|
||||
|
||||
_ => {
|
||||
*self = TypeTerm::App(vec![
|
||||
self.clone(),
|
||||
t.into()
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn num_arg(&mut self, v: i64) -> &mut Self {
|
||||
self.arg(TypeTerm::Num(v))
|
||||
}
|
||||
|
||||
pub fn char_arg(&mut self, c: char) -> &mut Self {
|
||||
self.arg(TypeTerm::Char(c))
|
||||
}
|
||||
|
||||
/// transform term to have at max 2 entries in Application list
|
||||
pub fn curry(&self) -> Self {
|
||||
match self {
|
||||
TypeTerm::App(head) => {
|
||||
let mut head = head.clone();
|
||||
if head.len() > 2 {
|
||||
let mut tail = head.split_off(2);
|
||||
|
||||
TypeTerm::App(vec![
|
||||
TypeTerm::App(head),
|
||||
if tail.len() > 1 {
|
||||
TypeTerm::App(tail).curry()
|
||||
} else {
|
||||
tail.remove(0)
|
||||
}
|
||||
])
|
||||
} else {
|
||||
TypeTerm::App(head)
|
||||
}
|
||||
}
|
||||
|
||||
TypeTerm::Ladder(l) => {
|
||||
TypeTerm::Ladder( l.iter().map(|x| x.curry()).collect() )
|
||||
}
|
||||
|
||||
atom => { atom.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
/// summarize all curried applications into one vec
|
||||
pub fn decurry(&mut self) -> &mut Self {
|
||||
match self {
|
||||
TypeTerm::App(args) => {
|
||||
if args.len() > 0 {
|
||||
let mut a0 = args.remove(0);
|
||||
a0.decurry();
|
||||
match a0 {
|
||||
TypeTerm::App(sub_args) => {
|
||||
for (i,x) in sub_args.into_iter().enumerate() {
|
||||
args.insert(i, x);
|
||||
}
|
||||
}
|
||||
other => { args.insert(0, other); }
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeTerm::Ladder(args) => {
|
||||
for x in args.iter_mut() {
|
||||
x.decurry();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// does the type contain ladders (false) or is it 'flat' (true) ?
|
||||
pub fn is_flat(&self) -> bool {
|
||||
match self {
|
||||
TypeTerm::TypeID(_) => true,
|
||||
TypeTerm::Num(_) => true,
|
||||
TypeTerm::Char(_) => true,
|
||||
TypeTerm::App(args) => args.iter().fold(true, |s,x| s && x.is_flat()),
|
||||
TypeTerm::Ladder(_) => false
|
||||
}
|
||||
}
|
||||
|
||||
/// transmute self into Ladder-Normal-Form
|
||||
///
|
||||
/// Example:
|
||||
/// <Seq <Digit 10>~Char> ⇒ <Seq <Digit 10>>~<Seq Char>
|
||||
pub fn normalize(self) -> Self {
|
||||
let mut new_ladder = Vec::<TypeTerm>::new();
|
||||
|
||||
match self {
|
||||
TypeTerm::Ladder(args) => {
|
||||
for x in args.into_iter() {
|
||||
new_ladder.push(x.normalize());
|
||||
}
|
||||
}
|
||||
|
||||
TypeTerm::App(args) => {
|
||||
let mut args_iter = args.into_iter();
|
||||
if let Some(head) = args_iter.next() {
|
||||
|
||||
let mut stage1_args = vec![ head.clone() ];
|
||||
let mut stage2_args = vec![ head.clone() ];
|
||||
|
||||
let mut done = false;
|
||||
|
||||
for x in args_iter {
|
||||
match x.normalize() {
|
||||
TypeTerm::Ladder(mut ladder) => {
|
||||
// normalize this ladder
|
||||
|
||||
if !done {
|
||||
if ladder.len() > 2 {
|
||||
stage1_args.push( ladder.remove(0) );
|
||||
stage2_args.push( TypeTerm::Ladder(ladder.to_vec()) );
|
||||
done = true;
|
||||
} else if ladder.len() == 1 {
|
||||
stage1_args.push( ladder[0].clone() );
|
||||
stage2_args.push( ladder[0].clone() );
|
||||
} else {
|
||||
// empty type ?
|
||||
}
|
||||
|
||||
} else {
|
||||
stage1_args.push( TypeTerm::Ladder(ladder.clone()) );
|
||||
stage2_args.push( TypeTerm::Ladder(ladder.clone()) );
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
unreachable!("x is in LNF");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new_ladder.push(TypeTerm::Ladder(stage1_args));
|
||||
new_ladder.push(TypeTerm::Ladder(stage2_args));
|
||||
}
|
||||
}
|
||||
|
||||
atom => {
|
||||
new_ladder.push(atom);
|
||||
}
|
||||
}
|
||||
|
||||
TypeTerm::Ladder( new_ladder )
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn is_supertype_of(&self, t: &TypeTerm) -> bool {
|
||||
t.is_semantic_subtype_of(self)
|
||||
}
|
||||
*/
|
||||
|
||||
// returns provided syntax-type,
|
||||
pub fn is_semantic_subtype_of(&self, expected_type: &TypeTerm) -> Option< TypeTerm > {
|
||||
let provided_lnf = self.clone();
|
||||
let expected_lnf = expected_type.clone();
|
||||
|
||||
match
|
||||
(provided_lnf.normalize(),
|
||||
expected_lnf.normalize())
|
||||
{
|
||||
( TypeTerm::Ladder( provided_ladder ),
|
||||
TypeTerm::Ladder( expected_ladder )
|
||||
) => {
|
||||
|
||||
for i in 0..provided_ladder.len() {
|
||||
if provided_ladder[i] == expected_ladder[0] {
|
||||
return Some(TypeTerm::Ladder(
|
||||
provided_ladder[i..].into_iter().cloned().collect()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
},
|
||||
|
||||
_ => {
|
||||
// both are in LNF!
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_syntactic_subtype_of(&self, expected_type: &TypeTerm) -> bool {
|
||||
if let Some(provided_type) = self.is_semantic_subtype_of( expected_type ) {
|
||||
&provided_type == expected_type
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/* this function is deprecated and only partially working,
|
||||
wontfix, will be replaced by TypeTerm-Editor
|
||||
*/
|
||||
pub fn from_str(s: &str, names: &HashMap<String, TypeID>) -> Option<Self> {
|
||||
let mut term_stack = Vec::<Option<TypeTerm>>::new();
|
||||
|
||||
for token in s.split_whitespace() {
|
||||
match token {
|
||||
"(" => {
|
||||
term_stack.push(None);
|
||||
}
|
||||
")" => {
|
||||
let t = term_stack.pop().unwrap();
|
||||
if term_stack.len() > 0 {
|
||||
let f = term_stack.last_mut().unwrap();
|
||||
if let Some(f) = f {
|
||||
f.arg(t.unwrap());
|
||||
} else {
|
||||
//error
|
||||
}
|
||||
} else {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
atom => {
|
||||
if let Some(f) = term_stack.last_mut() {
|
||||
match f {
|
||||
Some(f) => {
|
||||
let mut chars = atom.chars();
|
||||
let first = chars.next().unwrap();
|
||||
|
||||
if first.is_numeric() {
|
||||
f.num_arg(i64::from_str_radix(atom, 10).unwrap());
|
||||
} else if first == '\'' {
|
||||
if let Some(mut c) = chars.next() {
|
||||
if c == '\\' {
|
||||
if let Some('n') = chars.next() {
|
||||
c = '\n';
|
||||
}
|
||||
}
|
||||
f.char_arg(c);
|
||||
}
|
||||
} else {
|
||||
f.arg(TypeTerm::new(
|
||||
names.get(atom)
|
||||
.expect(&format!("invalid atom {}", atom)).clone()
|
||||
));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
*f = Some(TypeTerm::new(
|
||||
names.get(atom).expect(&format!("invalid atom {}", atom)).clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn to_str(&self, names: &HashMap<TypeID, String>) -> String {
|
||||
match self {
|
||||
TypeTerm::App(args) => {
|
||||
let mut out = String::new();
|
||||
|
||||
out.push_str(&"<");
|
||||
|
||||
let mut first = true;
|
||||
for x in args.iter() {
|
||||
if !first {
|
||||
out.push_str(&" ");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
|
||||
out.push_str(&x.to_str(names));
|
||||
}
|
||||
|
||||
out.push_str(&">");
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
TypeTerm::Ladder(l) => {
|
||||
let mut out = String::new();
|
||||
|
||||
let mut first = true;
|
||||
for x in l.iter() {
|
||||
if !first {
|
||||
out.push_str(&"~");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
|
||||
out.push_str(&x.to_str(names));
|
||||
}
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
TypeTerm::Num(n) => format!("{}", n),
|
||||
TypeTerm::Char('\n') => format!("'\\n'"),
|
||||
TypeTerm::Char(c) => format!("'{}'", c),
|
||||
TypeTerm::TypeID(id) => format!("{}", names[id]),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,27 +5,23 @@ use {
|
|||
pub fn bg_style_from_depth(depth: usize) -> TerminalStyle {
|
||||
match depth {
|
||||
0 => TerminalStyle::bg_color((150,80,230)),
|
||||
1 => TerminalStyle::bg_color((66,66,66)),
|
||||
2 => TerminalStyle::bg_color((44,44,44)),
|
||||
3 => TerminalStyle::bg_color((33,33,33)),
|
||||
4 => TerminalStyle::bg_color((28,28,28)),
|
||||
5 => TerminalStyle::bg_color((21,21,21)),
|
||||
1 => TerminalStyle::bg_color((75,75,75)),
|
||||
2 => TerminalStyle::bg_color((40,40,40)),
|
||||
3 => TerminalStyle::bg_color((30,30,30)),
|
||||
4 => TerminalStyle::bg_color((25,25,25)),
|
||||
5 => TerminalStyle::bg_color((20,20,20)),
|
||||
_ => TerminalStyle::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fg_style_from_depth(depth: usize) -> TerminalStyle {
|
||||
if depth == 0 {
|
||||
TerminalStyle::fg_color((200, 200, 200))
|
||||
} else {
|
||||
match depth % 5 {
|
||||
0 => TerminalStyle::fg_color((128, 106, 97)),
|
||||
1 => TerminalStyle::fg_color((100, 120, 232)),
|
||||
2 => TerminalStyle::fg_color((180, 100, 96)),
|
||||
3 => TerminalStyle::fg_color((188, 155, 18)),
|
||||
4 => TerminalStyle::fg_color((135, 182, 134)),
|
||||
_ => TerminalStyle::default()
|
||||
}
|
||||
}
|
||||
match depth % 6 {
|
||||
0 => TerminalStyle::fg_color((120, 120, 0)),
|
||||
1 => TerminalStyle::fg_color((250, 165, 40)),
|
||||
2 => TerminalStyle::fg_color((80, 180, 180)),
|
||||
3 => TerminalStyle::fg_color((180, 240, 85)),
|
||||
4 => TerminalStyle::fg_color((200, 190, 70)),
|
||||
_ => TerminalStyle::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue