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"
|
version = "0.1.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
#r3vi = { git = "https://git.exobiont.de/senvas/lib-r3vi.git" }
|
#r3vi = { git = "https://git.exobiont.de/senvas/r3vi.git" }
|
||||||
r3vi = { path = "../../lib-r3vi" }
|
r3vi = { path = "../../r3vi" }
|
||||||
laddertypes = { path = "../../lib-laddertypes" }
|
|
||||||
no_deadlocks = "*"
|
no_deadlocks = "*"
|
||||||
cgmath = { version = "0.18.0", features = ["serde"] }
|
cgmath = { version = "0.18.0", features = ["serde"] }
|
||||||
termion = "2.0.1"
|
termion = "1.5.5"
|
||||||
vte = "0.10.1"
|
vte = "0.10.1"
|
||||||
ansi_colours = "1.0"
|
ansi_colours = "1.0"
|
||||||
signal-hook = "0.3.1"
|
signal-hook = "0.3.1"
|
||||||
|
|
|
@ -6,9 +6,8 @@ use {
|
||||||
},
|
},
|
||||||
buffer::singleton::*
|
buffer::singleton::*
|
||||||
},
|
},
|
||||||
laddertypes::{TypeTerm},
|
|
||||||
crate::{
|
crate::{
|
||||||
type_system::{Context, ReprTree},
|
type_system::{Context, ReprTree, TypeTerm},
|
||||||
terminal::{TerminalAtom},
|
terminal::{TerminalAtom},
|
||||||
tree::{NestedNode, TreeNavResult},
|
tree::{NestedNode, TreeNavResult},
|
||||||
commander::{ObjCommander}
|
commander::{ObjCommander}
|
||||||
|
@ -20,8 +19,8 @@ use {
|
||||||
pub fn init_ctx( ctx: &mut Context ) {
|
pub fn init_ctx( ctx: &mut Context ) {
|
||||||
ctx.add_node_ctor(
|
ctx.add_node_ctor(
|
||||||
"Char",
|
"Char",
|
||||||
Arc::new(|ctx: Arc<RwLock<Context>>, _ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| {
|
Arc::new(|ctx: Arc<RwLock<Context>>, _ty: TypeTerm, _depth: usize| {
|
||||||
Some(CharEditor::new_node(ctx, depth))
|
Some(CharEditor::new_node(ctx))
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +34,7 @@ impl ObjCommander for CharEditor {
|
||||||
let cmd_obj = cmd_obj.read().unwrap();
|
let cmd_obj = cmd_obj.read().unwrap();
|
||||||
let cmd_type = cmd_obj.get_type().clone();
|
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>>() {
|
if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() {
|
||||||
let value = cmd_view.get();
|
let value = cmd_view.get();
|
||||||
|
|
||||||
|
@ -70,7 +69,7 @@ impl CharEditor {
|
||||||
self.get_port().get_view().unwrap().get()
|
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 data = SingletonBuffer::new('\0');
|
||||||
let ctx = ctx0.clone();
|
let ctx = ctx0.clone();
|
||||||
let editor = Arc::new(RwLock::new(CharEditor{ ctx, data: data.clone() }));
|
let editor = Arc::new(RwLock::new(CharEditor{ ctx, data: data.clone() }));
|
||||||
|
@ -78,14 +77,14 @@ impl CharEditor {
|
||||||
NestedNode::new(
|
NestedNode::new(
|
||||||
ctx0.clone(),
|
ctx0.clone(),
|
||||||
ReprTree::new_leaf(
|
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()
|
data.get_port().into()
|
||||||
),
|
),
|
||||||
depth
|
0 // fixme
|
||||||
)
|
)
|
||||||
.set_view(data
|
.set_view(data
|
||||||
.get_port()
|
.get_port()
|
||||||
.map(move |c| TerminalAtom::from(if c == '\0' { ' ' } else { c }))
|
.map(move |c| TerminalAtom::from(c))
|
||||||
.to_grid()
|
.to_grid()
|
||||||
)
|
)
|
||||||
.set_cmd( editor.clone() )
|
.set_cmd( editor.clone() )
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
|
|
||||||
use {
|
use {
|
||||||
r3vi::{
|
|
||||||
view::{OuterViewPort, singleton::*}
|
|
||||||
},
|
|
||||||
laddertypes::{TypeTerm},
|
|
||||||
crate::{
|
crate::{
|
||||||
type_system::{Context},
|
type_system::{Context, TypeTerm},
|
||||||
editors::{
|
editors::{
|
||||||
list::*,
|
list::*,
|
||||||
integer::*
|
integer::*
|
||||||
|
@ -24,7 +19,7 @@ pub fn init_ctx(ctx: &mut Context) {
|
||||||
|
|
||||||
ctx.add_node_ctor(
|
ctx.add_node_ctor(
|
||||||
"Digit", Arc::new(
|
"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 {
|
match ty {
|
||||||
TypeTerm::App(args) => {
|
TypeTerm::App(args) => {
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
|
@ -55,6 +50,9 @@ pub fn init_ctx(ctx: &mut Context) {
|
||||||
ctx.add_morphism(pattern,
|
ctx.add_morphism(pattern,
|
||||||
Arc::new(
|
Arc::new(
|
||||||
|mut node, dst_type| {
|
|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 )
|
// todo: check src_type parameter to be ( Digit radix )
|
||||||
|
|
||||||
match dst_type {
|
match dst_type {
|
||||||
|
@ -89,7 +87,7 @@ pub fn init_ctx(ctx: &mut Context) {
|
||||||
|
|
||||||
ctx.add_node_ctor(
|
ctx.add_node_ctor(
|
||||||
"PosInt", Arc::new(
|
"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() {
|
match dst_typ.clone() {
|
||||||
TypeTerm::App(args) => {
|
TypeTerm::App(args) => {
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
|
@ -107,7 +105,7 @@ pub fn init_ctx(ctx: &mut Context) {
|
||||||
.clone()
|
.clone()
|
||||||
.into()
|
.into()
|
||||||
]),
|
]),
|
||||||
depth.map(|d| d+1)
|
depth+1
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
node = node.morph(dst_typ);
|
node = node.morph(dst_typ);
|
||||||
|
|
|
@ -10,9 +10,8 @@ use {
|
||||||
index_hashmap::*
|
index_hashmap::*
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
laddertypes::{TypeTerm},
|
|
||||||
crate::{
|
crate::{
|
||||||
type_system::{Context, ReprTree},
|
type_system::{Context, TypeTerm, ReprTree},
|
||||||
editors::list::{ListCmd, PTYListController, PTYListStyle},
|
editors::list::{ListCmd, PTYListController, PTYListStyle},
|
||||||
terminal::{
|
terminal::{
|
||||||
TerminalAtom, TerminalStyle, make_label
|
TerminalAtom, TerminalStyle, make_label
|
||||||
|
@ -41,7 +40,7 @@ impl ObjCommander for DigitEditor {
|
||||||
let cmd_obj = cmd_obj.read().unwrap();
|
let cmd_obj = cmd_obj.read().unwrap();
|
||||||
let cmd_type = cmd_obj.get_type().clone();
|
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>>() {
|
if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() {
|
||||||
let c = cmd_view.get();
|
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 data = self.get_data();
|
||||||
let editor = Arc::new(RwLock::new(self));
|
let editor = Arc::new(RwLock::new(self));
|
||||||
let ed = editor.write().unwrap();
|
let ed = editor.write().unwrap();
|
||||||
|
@ -100,7 +99,7 @@ impl DigitEditor {
|
||||||
TerminalAtom::new(
|
TerminalAtom::new(
|
||||||
c.unwrap_or('?'),
|
c.unwrap_or('?'),
|
||||||
if c.unwrap_or('?').to_digit(r).is_some() {
|
if c.unwrap_or('?').to_digit(r).is_some() {
|
||||||
TerminalStyle::fg_color((90, 160, 90))
|
TerminalStyle::fg_color((100, 140, 100))
|
||||||
} else {
|
} else {
|
||||||
//TerminalStyle::bg_color((90, 10, 10))
|
//TerminalStyle::bg_color((90, 10, 10))
|
||||||
TerminalStyle::fg_color((200, 40, 40))
|
TerminalStyle::fg_color((200, 40, 40))
|
||||||
|
@ -126,7 +125,7 @@ impl DigitEditor {
|
||||||
pub fn get_data(&self) -> Arc<RwLock<ReprTree>> {
|
pub fn get_data(&self) -> Arc<RwLock<ReprTree>> {
|
||||||
ReprTree::ascend(
|
ReprTree::ascend(
|
||||||
&ReprTree::new_leaf(
|
&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_data_port().into()
|
||||||
),
|
),
|
||||||
self.get_type()
|
self.get_type()
|
||||||
|
@ -146,8 +145,8 @@ impl PosIntEditor {
|
||||||
pub fn new(ctx: Arc<RwLock<Context>>, radix: u32) -> Self {
|
pub fn new(ctx: Arc<RwLock<Context>>, radix: u32) -> Self {
|
||||||
let mut node = Context::make_node(
|
let mut node = Context::make_node(
|
||||||
&ctx,
|
&ctx,
|
||||||
Context::parse(&ctx, format!("<List <Digit {}>>", radix).as_str()),
|
(&ctx, format!("( List ( Digit {} ) )", radix).as_str()).into(),
|
||||||
r3vi::buffer::singleton::SingletonBuffer::new(0).get_port()
|
0
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
// Set Type
|
// Set Type
|
||||||
|
|
|
@ -26,7 +26,7 @@ impl ListCmd {
|
||||||
pub fn into_repr_tree(self, ctx: &Arc<RwLock<Context>>) -> Arc<RwLock<ReprTree>> {
|
pub fn into_repr_tree(self, ctx: &Arc<RwLock<Context>>) -> Arc<RwLock<ReprTree>> {
|
||||||
let buf = r3vi::buffer::singleton::SingletonBuffer::new(self);
|
let buf = r3vi::buffer::singleton::SingletonBuffer::new(self);
|
||||||
ReprTree::new_leaf(
|
ReprTree::new_leaf(
|
||||||
Context::parse(ctx, "ListCmd"),
|
(ctx, "( ListCmd )"),
|
||||||
buf.get_port().into()
|
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>>() {
|
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();
|
let cur = self.cursor.get();
|
||||||
drop(cmd_repr);
|
drop(cmd_repr);
|
||||||
|
|
||||||
|
@ -73,11 +71,11 @@ impl ObjCommander for ListEditor {
|
||||||
match cur.mode {
|
match cur.mode {
|
||||||
ListCursorMode::Select => {
|
ListCursorMode::Select => {
|
||||||
if let Some(mut item) = self.get_item().clone() {
|
if let Some(mut item) = self.get_item().clone() {
|
||||||
|
if self.is_listlist() {
|
||||||
let item_cur = item.get_cursor();
|
let item_cur = item.get_cursor();
|
||||||
|
|
||||||
match cmd.get() {
|
match cmd.get() {
|
||||||
ListCmd::DeletePxev => {
|
ListCmd::DeletePxev => {
|
||||||
eprintln!("SELECT: delete pxev");
|
|
||||||
if idx > 0
|
if idx > 0
|
||||||
&& item_cur.tree_addr.iter().fold(
|
&& item_cur.tree_addr.iter().fold(
|
||||||
true,
|
true,
|
||||||
|
@ -119,7 +117,9 @@ impl ObjCommander for ListEditor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
eprintln!("ptylist: no item");
|
TreeNavResult::Exit
|
||||||
|
}
|
||||||
|
} else {
|
||||||
TreeNavResult::Exit
|
TreeNavResult::Exit
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -127,7 +127,6 @@ impl ObjCommander for ListEditor {
|
||||||
ListCursorMode::Insert => {
|
ListCursorMode::Insert => {
|
||||||
match cmd.get() {
|
match cmd.get() {
|
||||||
ListCmd::DeletePxev => {
|
ListCmd::DeletePxev => {
|
||||||
eprintln!("INSERT: delete pxev");
|
|
||||||
self.delete_pxev();
|
self.delete_pxev();
|
||||||
TreeNavResult::Continue
|
TreeNavResult::Continue
|
||||||
}
|
}
|
||||||
|
@ -150,19 +149,18 @@ impl ObjCommander for ListEditor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
eprintln!("ptylist: cursor has no idx");
|
|
||||||
TreeNavResult::Exit
|
TreeNavResult::Exit
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if let Some(cur_item) = self.get_item_mut() {
|
if let Some(cur_item) = self.get_item_mut() {
|
||||||
drop(cmd_repr);
|
drop(cmd_repr);
|
||||||
cur_item.write().unwrap().send_cmd_obj(cmd_obj);
|
cur_item.write().unwrap().send_cmd_obj(cmd_obj)
|
||||||
TreeNavResult::Continue
|
|
||||||
} else {
|
} else {
|
||||||
TreeNavResult::Exit
|
TreeNavResult::Continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
use {
|
use {
|
||||||
r3vi::{view::{OuterViewPort, singleton::*}},
|
|
||||||
laddertypes::{TypeTerm},
|
|
||||||
crate::{
|
crate::{
|
||||||
type_system::{Context},
|
type_system::{Context, TypeTerm},
|
||||||
editors::list::{ListEditor, PTYListController, PTYListStyle}
|
editors::list::{ListEditor, PTYListController, PTYListStyle}
|
||||||
},
|
},
|
||||||
std::sync::{Arc, RwLock}
|
std::sync::{Arc, RwLock}
|
||||||
|
@ -11,12 +9,12 @@ use {
|
||||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
pub fn init_ctx(ctx: &mut Context) {
|
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_list_typename("List".into());
|
||||||
|
|
||||||
ctx.add_node_ctor(
|
ctx.add_node_ctor(
|
||||||
"List", Arc::new(
|
"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 {
|
match ty {
|
||||||
TypeTerm::App(args) => {
|
TypeTerm::App(args) => {
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
use {
|
use {
|
||||||
r3vi::{
|
r3vi::{
|
||||||
view::{ViewPort, OuterViewPort, singleton::*, sequence::*},
|
view::{OuterViewPort, singleton::*, sequence::*},
|
||||||
buffer::{singleton::*, vec::*}
|
buffer::{singleton::*, vec::*}
|
||||||
},
|
},
|
||||||
laddertypes::{TypeTerm},
|
|
||||||
crate::{
|
crate::{
|
||||||
type_system::{Context, ReprTree},
|
type_system::{Context, TypeTerm, ReprTree},
|
||||||
editors::list::{ListCursor, ListCursorMode, ListCmd},
|
editors::list::{ListCursor, ListCursorMode, ListCmd},
|
||||||
tree::{NestedNode, TreeNav, TreeCursor},
|
tree::{NestedNode, TreeNav, TreeCursor},
|
||||||
diagnostics::Diagnostics,
|
diagnostics::Diagnostics,
|
||||||
|
@ -27,8 +26,6 @@ pub struct ListEditor {
|
||||||
pub(super) addr_port: OuterViewPort<dyn SequenceView<Item = isize>>,
|
pub(super) addr_port: OuterViewPort<dyn SequenceView<Item = isize>>,
|
||||||
pub(super) mode_port: OuterViewPort<dyn SingletonView<Item = ListCursorMode>>,
|
pub(super) mode_port: OuterViewPort<dyn SingletonView<Item = ListCursorMode>>,
|
||||||
|
|
||||||
depth: OuterViewPort<dyn SingletonView<Item = usize>>,
|
|
||||||
|
|
||||||
pub(crate) ctx: Arc<RwLock<Context>>,
|
pub(crate) ctx: Arc<RwLock<Context>>,
|
||||||
|
|
||||||
/// item type
|
/// item type
|
||||||
|
@ -98,16 +95,13 @@ impl ListEditor {
|
||||||
data,
|
data,
|
||||||
spillbuf: Arc::new(RwLock::new(Vec::new())),
|
spillbuf: Arc::new(RwLock::new(Vec::new())),
|
||||||
ctx,
|
ctx,
|
||||||
typ,
|
typ
|
||||||
depth: SingletonBuffer::new(0).get_port()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 data = self.get_data();
|
||||||
let ctx = self.ctx.clone();
|
let ctx = self.ctx.clone();
|
||||||
|
|
||||||
self.depth = depth.clone();
|
|
||||||
let editor = Arc::new(RwLock::new(self));
|
let editor = Arc::new(RwLock::new(self));
|
||||||
|
|
||||||
let e = editor.read().unwrap();
|
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 {
|
pub fn is_listlist(&self) -> bool {
|
||||||
self.ctx.read().unwrap().is_list_type(&self.typ)
|
self.ctx.read().unwrap().is_list_type(&self.typ)
|
||||||
}
|
}
|
||||||
|
@ -234,12 +227,6 @@ impl ListEditor {
|
||||||
|
|
||||||
/// insert a new element
|
/// insert a new element
|
||||||
pub fn insert(&mut self, item: Arc<RwLock<NestedNode>>) {
|
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();
|
let mut cur = self.cursor.get();
|
||||||
if let Some(idx) = cur.idx {
|
if let Some(idx) = cur.idx {
|
||||||
match cur.mode {
|
match cur.mode {
|
||||||
|
@ -248,8 +235,6 @@ impl ListEditor {
|
||||||
if self.is_listlist() {
|
if self.is_listlist() {
|
||||||
cur.mode = ListCursorMode::Select;
|
cur.mode = ListCursorMode::Select;
|
||||||
} else {
|
} 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,7 +255,6 @@ impl ListEditor {
|
||||||
|
|
||||||
/// split the list off at the current cursor position and return the second half
|
/// split the list off at the current cursor position and return the second half
|
||||||
pub fn split(&mut self) {
|
pub fn split(&mut self) {
|
||||||
eprintln!("split");
|
|
||||||
let cur = self.cursor.get();
|
let cur = self.cursor.get();
|
||||||
if let Some(idx) = cur.idx {
|
if let Some(idx) = cur.idx {
|
||||||
let idx = idx as usize;
|
let idx = idx as usize;
|
||||||
|
@ -280,32 +264,10 @@ impl ListEditor {
|
||||||
);
|
);
|
||||||
self.data.remove(idx);
|
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) {
|
pub fn listlist_split(&mut self) {
|
||||||
eprintln!("listlist split");
|
|
||||||
let cur = self.get_cursor();
|
let cur = self.get_cursor();
|
||||||
|
|
||||||
if let Some(mut item) = self.get_item().clone() {
|
if let Some(mut item) = self.get_item().clone() {
|
||||||
|
@ -318,15 +280,14 @@ impl ListEditor {
|
||||||
self.nexd();
|
self.nexd();
|
||||||
|
|
||||||
let mut b = item.spillbuf.write().unwrap();
|
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());
|
tail_node.goto(TreeCursor::home());
|
||||||
|
|
||||||
for node in b.iter() {
|
for node in b.iter() {
|
||||||
eprintln!("splid :send to tail node");
|
|
||||||
tail_node
|
tail_node
|
||||||
.send_cmd_obj(
|
.send_cmd_obj(
|
||||||
ReprTree::new_leaf(
|
ReprTree::new_leaf(
|
||||||
Context::parse(&self.ctx, "NestedNode"),
|
(&self.ctx, "( NestedNode )"),
|
||||||
SingletonBuffer::<NestedNode>::new(
|
SingletonBuffer::<NestedNode>::new(
|
||||||
node.read().unwrap().clone()
|
node.read().unwrap().clone()
|
||||||
).get_port().into()
|
).get_port().into()
|
||||||
|
@ -338,7 +299,7 @@ impl ListEditor {
|
||||||
drop(item);
|
drop(item);
|
||||||
|
|
||||||
tail_node.goto(TreeCursor::home());
|
tail_node.goto(TreeCursor::home());
|
||||||
if cur.tree_addr.len() > 1 {
|
if cur.tree_addr.len() > 2 {
|
||||||
tail_node.dn();
|
tail_node.dn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,7 +341,7 @@ impl ListEditor {
|
||||||
for x in data.iter() {
|
for x in data.iter() {
|
||||||
pxv_editor.send_cmd_obj(
|
pxv_editor.send_cmd_obj(
|
||||||
ReprTree::new_leaf(
|
ReprTree::new_leaf(
|
||||||
Context::parse(&self.ctx, "NestedNode"),
|
(&self.ctx, "( NestedNode )"),
|
||||||
SingletonBuffer::<NestedNode>::new(
|
SingletonBuffer::<NestedNode>::new(
|
||||||
x.read().unwrap().clone()
|
x.read().unwrap().clone()
|
||||||
).get_port().into()
|
).get_port().into()
|
||||||
|
@ -388,15 +349,13 @@ impl ListEditor {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// fixme: is it oc0 or old_cur ??
|
|
||||||
if oc0.tree_addr.len() > 1 {
|
if oc0.tree_addr.len() > 1 {
|
||||||
pxv_editor.goto(TreeCursor {
|
pxv_editor.goto(TreeCursor {
|
||||||
tree_addr: vec![ old_cur.tree_addr[0], 0 ],
|
tree_addr: vec![ old_cur.tree_addr[0], 0 ],
|
||||||
leaf_mode: ListCursorMode::Insert
|
leaf_mode: ListCursorMode::Insert
|
||||||
});
|
});
|
||||||
pxv_editor.send_cmd_obj(ListCmd::DeletePxev.into_repr_tree( &self.ctx ));
|
pxv_editor.send_cmd_obj(ListCmd::DeletePxev.into_repr_tree( &self.ctx ));
|
||||||
} else if oc0.tree_addr.len() > 0 {
|
} else {
|
||||||
pxv_editor.goto(TreeCursor {
|
pxv_editor.goto(TreeCursor {
|
||||||
tree_addr: vec![ old_cur.tree_addr[0] ],
|
tree_addr: vec![ old_cur.tree_addr[0] ],
|
||||||
leaf_mode: ListCursorMode::Insert
|
leaf_mode: ListCursorMode::Insert
|
||||||
|
@ -439,7 +398,7 @@ impl ListEditor {
|
||||||
for x in data.iter() {
|
for x in data.iter() {
|
||||||
cur_editor.send_cmd_obj(
|
cur_editor.send_cmd_obj(
|
||||||
ReprTree::new_leaf(
|
ReprTree::new_leaf(
|
||||||
Context::parse(&self.ctx, "NestedNode"),
|
(&self.ctx, "( NestedNode )"),
|
||||||
SingletonBuffer::<NestedNode>::new(
|
SingletonBuffer::<NestedNode>::new(
|
||||||
x.read().unwrap().clone()
|
x.read().unwrap().clone()
|
||||||
).get_port().into()
|
).get_port().into()
|
||||||
|
@ -447,20 +406,17 @@ impl ListEditor {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fixme: is it oc0 or old_cur ??
|
|
||||||
if oc0.tree_addr.len() > 1 {
|
if oc0.tree_addr.len() > 1 {
|
||||||
cur_editor.goto(TreeCursor {
|
cur_editor.goto(TreeCursor {
|
||||||
tree_addr: vec![ old_cur.tree_addr[0], -1 ],
|
tree_addr: vec![ old_cur.tree_addr[0], -1 ],
|
||||||
leaf_mode: ListCursorMode::Insert
|
leaf_mode: ListCursorMode::Insert
|
||||||
});
|
});
|
||||||
cur_editor.send_cmd_obj(ListCmd::DeleteNexd.into_repr_tree( &self.ctx ));
|
cur_editor.send_cmd_obj(ListCmd::DeleteNexd.into_repr_tree( &self.ctx ));
|
||||||
} else if oc0.tree_addr.len() > 0 {
|
} else {
|
||||||
cur_editor.goto(TreeCursor {
|
cur_editor.goto(TreeCursor {
|
||||||
tree_addr: vec![ old_cur.tree_addr[0] ],
|
tree_addr: vec![ old_cur.tree_addr[0] ],
|
||||||
leaf_mode: ListCursorMode::Insert
|
leaf_mode: ListCursorMode::Insert
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
cur_editor.goto(TreeCursor::none());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -195,7 +195,6 @@ impl TreeNav for ListEditor {
|
||||||
TreeNavResult::Exit
|
TreeNavResult::Exit
|
||||||
} else if direction.y > 0 {
|
} else if direction.y > 0 {
|
||||||
// dn
|
// dn
|
||||||
eprintln!("dn: data.len() = {}", self.data.len());
|
|
||||||
self.cursor.set(ListCursor {
|
self.cursor.set(ListCursor {
|
||||||
mode: if self.data.len() > 0 { cur.leaf_mode } else { ListCursorMode::Insert },
|
mode: if self.data.len() > 0 { cur.leaf_mode } else { ListCursorMode::Insert },
|
||||||
idx: Some(0)
|
idx: Some(0)
|
||||||
|
@ -211,7 +210,6 @@ impl TreeNav for ListEditor {
|
||||||
1 => {
|
1 => {
|
||||||
if direction.y > 0 {
|
if direction.y > 0 {
|
||||||
// dn
|
// dn
|
||||||
|
|
||||||
if cur.tree_addr[0] < self.data.len() as isize {
|
if cur.tree_addr[0] < self.data.len() as isize {
|
||||||
if self.data
|
if self.data
|
||||||
.get_mut(cur.tree_addr[0] as usize)
|
.get_mut(cur.tree_addr[0] as usize)
|
||||||
|
@ -221,8 +219,7 @@ impl TreeNav for ListEditor {
|
||||||
self.cursor.set(ListCursor {
|
self.cursor.set(ListCursor {
|
||||||
mode: ListCursorMode::Select,
|
mode: ListCursorMode::Select,
|
||||||
idx: Some(cur.tree_addr[0])
|
idx: Some(cur.tree_addr[0])
|
||||||
});
|
})
|
||||||
self.set_leaf_mode(cur.leaf_mode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use {
|
use {
|
||||||
r3vi::{
|
r3vi::{
|
||||||
view::{ViewPort, OuterViewPort, sequence::*},
|
view::{OuterViewPort, sequence::*},
|
||||||
projection::decorate_sequence::*,
|
projection::decorate_sequence::*,
|
||||||
},
|
},
|
||||||
crate::{
|
crate::{
|
||||||
|
@ -18,20 +18,23 @@ use {
|
||||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
pub struct PTYListStyle {
|
pub struct PTYListStyle {
|
||||||
style: (String, String, String)
|
style: (String, String, String),
|
||||||
|
depth: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PTYListStyle {
|
impl PTYListStyle {
|
||||||
pub fn new(style: (&str, &str, &str)) -> PTYListStyle {
|
pub fn new(style: (&str, &str, &str), depth: usize) -> PTYListStyle {
|
||||||
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>>> {
|
pub fn get_seg_seq_view(&self, editor: &ListEditor) -> OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>> {
|
||||||
let seg_seq = ListSegmentSequence::new(
|
let seg_seq = ListSegmentSequence::new(
|
||||||
editor.get_cursor_port(),
|
editor.get_cursor_port(),
|
||||||
editor.get_data_port()
|
editor.get_data_port(),
|
||||||
|
self.depth
|
||||||
);
|
);
|
||||||
let se = seg_seq.read().unwrap();
|
let se = seg_seq.read().unwrap();
|
||||||
se.get_view().map(move |segment| segment.pty_view())
|
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> {
|
pub fn pty_view(&self, editor: &ListEditor) -> OuterViewPort<dyn TerminalView> {
|
||||||
let seg_seq = ListSegmentSequence::new(
|
let seg_seq = ListSegmentSequence::new(
|
||||||
editor.get_cursor_port(),
|
editor.get_cursor_port(),
|
||||||
editor.get_data_port()
|
editor.get_data_port(),
|
||||||
|
self.depth
|
||||||
);
|
);
|
||||||
let seg_seq = seg_seq.read().unwrap();
|
let seg_seq = seg_seq.read().unwrap();
|
||||||
|
|
||||||
|
@ -55,7 +59,7 @@ impl PTYListStyle {
|
||||||
|
|
||||||
pub fn for_node(node: &mut NestedNode, style: (&str, &str, &str)) {
|
pub fn for_node(node: &mut NestedNode, style: (&str, &str, &str)) {
|
||||||
node.view = Some(
|
node.view = Some(
|
||||||
Self::new(style)
|
Self::new(style, node.depth.get())
|
||||||
.pty_view(
|
.pty_view(
|
||||||
&node.get_edit::<ListEditor>().unwrap().read().unwrap()
|
&node.get_edit::<ListEditor>().unwrap().read().unwrap()
|
||||||
)
|
)
|
||||||
|
@ -65,15 +69,13 @@ impl PTYListStyle {
|
||||||
|
|
||||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
// todo: rename to CharController
|
|
||||||
|
|
||||||
pub struct PTYListController {
|
pub struct PTYListController {
|
||||||
pub editor: Arc<RwLock<ListEditor>>,
|
pub editor: Arc<RwLock<ListEditor>>,
|
||||||
|
|
||||||
split_char: Option<char>,
|
split_char: Option<char>,
|
||||||
close_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>>,
|
editor: Arc<RwLock<ListEditor>>,
|
||||||
split_char: Option<char>,
|
split_char: Option<char>,
|
||||||
close_char: Option<char>,
|
close_char: Option<char>,
|
||||||
depth: OuterViewPort<dyn SingletonView<Item = usize>>
|
depth: usize
|
||||||
) -> Self {
|
) -> Self {
|
||||||
PTYListController {
|
PTYListController {
|
||||||
editor,
|
editor,
|
||||||
|
@ -111,7 +113,7 @@ impl PTYListController {
|
||||||
}
|
}
|
||||||
|
|
||||||
let editor = node.get_edit::<ListEditor>().unwrap();
|
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.cmd.set(Some(controller.clone()));
|
||||||
node.close_char.set(close_char);
|
node.close_char.set(close_char);
|
||||||
|
@ -129,6 +131,10 @@ impl PTYListController {
|
||||||
self.editor.read().unwrap().get_item()
|
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 {
|
pub fn handle_term_event(&mut self, event: &TerminalEvent, _cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
|
||||||
let mut e = self.editor.write().unwrap();
|
let mut e = self.editor.write().unwrap();
|
||||||
match event {
|
match event {
|
||||||
|
@ -149,7 +155,6 @@ impl PTYListController {
|
||||||
// || Some(c) == child_close_char
|
// || Some(c) == child_close_char
|
||||||
{
|
{
|
||||||
e.listlist_split();
|
e.listlist_split();
|
||||||
eprintln!("done listlist split");
|
|
||||||
TreeNavResult::Continue
|
TreeNavResult::Continue
|
||||||
} else if Some(c) == child_close_char {
|
} else if Some(c) == child_close_char {
|
||||||
e.goto(TreeCursor::none());
|
e.goto(TreeCursor::none());
|
||||||
|
@ -171,12 +176,12 @@ impl PTYListController {
|
||||||
|
|
||||||
match cur.mode {
|
match cur.mode {
|
||||||
ListCursorMode::Insert => {
|
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());
|
new_edit.goto(TreeCursor::home());
|
||||||
|
|
||||||
match new_edit.send_cmd_obj(cmd_obj.clone()) {
|
match new_edit.send_cmd_obj(cmd_obj.clone()) {
|
||||||
TreeNavResult::Continue => {
|
TreeNavResult::Continue => {
|
||||||
e.insert(Arc::new(RwLock::new(new_edit.clone())));
|
e.insert(Arc::new(RwLock::new(new_edit)));
|
||||||
TreeNavResult::Continue
|
TreeNavResult::Continue
|
||||||
}
|
}
|
||||||
TreeNavResult::Exit => {
|
TreeNavResult::Exit => {
|
||||||
|
@ -194,7 +199,7 @@ impl PTYListController {
|
||||||
TreeNavResult::Exit => {
|
TreeNavResult::Exit => {
|
||||||
// child editor returned control, probably for meta-char handling..
|
// 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();
|
let co = cmd_obj.read().unwrap();
|
||||||
if let Some(cmd_view) = co.get_view::<dyn SingletonView<Item = char>>() {
|
if let Some(cmd_view) = co.get_view::<dyn SingletonView<Item = char>>() {
|
||||||
drop(co);
|
drop(co);
|
||||||
|
@ -225,13 +230,13 @@ impl ObjCommander for PTYListController {
|
||||||
let mut e = self.editor.write().unwrap();
|
let mut e = self.editor.write().unwrap();
|
||||||
let cmd_type = cmd_obj.read().unwrap().get_type().clone();
|
let cmd_type = cmd_obj.read().unwrap().get_type().clone();
|
||||||
|
|
||||||
if cmd_type == Context::parse(&e.ctx, "ListCmd").into()
|
if cmd_type == (&e.ctx, "( ListCmd )").into()
|
||||||
|| cmd_type == Context::parse(&e.ctx, "NestedNode").into()
|
|| cmd_type == (&e.ctx, "( NestedNode )").into()
|
||||||
{
|
{
|
||||||
e.send_cmd_obj( cmd_obj )
|
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();
|
let co = cmd_obj.read().unwrap();
|
||||||
if let Some(view) = co.get_view::<dyn SingletonView<Item = TerminalEvent>>() {
|
if let Some(view) = co.get_view::<dyn SingletonView<Item = TerminalEvent>>() {
|
||||||
drop( co );
|
drop( co );
|
||||||
|
|
|
@ -22,6 +22,7 @@ pub enum ListSegment {
|
||||||
InsertCursor,
|
InsertCursor,
|
||||||
Item {
|
Item {
|
||||||
editor: NestedNode,
|
editor: NestedNode,
|
||||||
|
depth: usize,
|
||||||
cur_dist: isize,
|
cur_dist: isize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,8 +37,9 @@ impl PtySegment for ListSegment {
|
||||||
.add_style_front(TerminalStyle::bold(true))
|
.add_style_front(TerminalStyle::bold(true))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ListSegment::Item{ editor, cur_dist } => {
|
ListSegment::Item{ editor, depth, cur_dist } => {
|
||||||
let e = editor.clone();
|
let e = editor.clone();
|
||||||
|
let d = *depth;
|
||||||
let cur_dist = *cur_dist;
|
let cur_dist = *cur_dist;
|
||||||
editor.get_view().map_item(move |_pt, atom| {
|
editor.get_view().map_item(move |_pt, atom| {
|
||||||
let c = e.get_cursor();
|
let c = e.get_cursor();
|
||||||
|
@ -48,11 +50,10 @@ impl PtySegment for ListSegment {
|
||||||
} else {
|
} else {
|
||||||
usize::MAX
|
usize::MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
atom
|
atom
|
||||||
.add_style_back(bg_style_from_depth(select))
|
.add_style_back(bg_style_from_depth(select))
|
||||||
.add_style_back(TerminalStyle::bold(select==1))
|
.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>>,
|
data: Arc<dyn SequenceView<Item = NestedNode>>,
|
||||||
cursor: Arc<dyn SingletonView<Item = ListCursor>>,
|
cursor: Arc<dyn SingletonView<Item = ListCursor>>,
|
||||||
|
|
||||||
|
depth: usize,
|
||||||
cur_cursor: ListCursor,
|
cur_cursor: ListCursor,
|
||||||
|
|
||||||
port: ViewPort<dyn SequenceView<Item = ListSegment>>,
|
port: ViewPort<dyn SequenceView<Item = ListSegment>>,
|
||||||
|
@ -93,6 +95,7 @@ impl SequenceView for ListSegmentSequence {
|
||||||
ListCursorMode::Select => {
|
ListCursorMode::Select => {
|
||||||
ListSegment::Item {
|
ListSegment::Item {
|
||||||
editor: self.data.get(idx)?,
|
editor: self.data.get(idx)?,
|
||||||
|
depth: self.depth,
|
||||||
cur_dist: cur - *idx as isize
|
cur_dist: cur - *idx as isize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,6 +103,7 @@ impl SequenceView for ListSegmentSequence {
|
||||||
if *idx < cur as usize {
|
if *idx < cur as usize {
|
||||||
ListSegment::Item {
|
ListSegment::Item {
|
||||||
editor: self.data.get(idx)?,
|
editor: self.data.get(idx)?,
|
||||||
|
depth: self.depth,
|
||||||
cur_dist: cur - *idx as isize
|
cur_dist: cur - *idx as isize
|
||||||
}
|
}
|
||||||
} else if *idx == cur as usize {
|
} else if *idx == cur as usize {
|
||||||
|
@ -107,6 +111,7 @@ impl SequenceView for ListSegmentSequence {
|
||||||
} else {
|
} else {
|
||||||
ListSegment::Item {
|
ListSegment::Item {
|
||||||
editor: self.data.get(&(*idx - 1))?,
|
editor: self.data.get(&(*idx - 1))?,
|
||||||
|
depth: self.depth,
|
||||||
cur_dist: cur - *idx as isize
|
cur_dist: cur - *idx as isize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,6 +120,7 @@ impl SequenceView for ListSegmentSequence {
|
||||||
} else {
|
} else {
|
||||||
ListSegment::Item {
|
ListSegment::Item {
|
||||||
editor: self.data.get(&idx)?,
|
editor: self.data.get(&idx)?,
|
||||||
|
depth: self.depth,
|
||||||
cur_dist: *idx as isize + 1
|
cur_dist: *idx as isize + 1
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -125,12 +131,14 @@ impl ListSegmentSequence {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
cursor_port: OuterViewPort<dyn SingletonView<Item = ListCursor>>,
|
cursor_port: OuterViewPort<dyn SingletonView<Item = ListCursor>>,
|
||||||
data_port: OuterViewPort<dyn SequenceView<Item = NestedNode>>,
|
data_port: OuterViewPort<dyn SequenceView<Item = NestedNode>>,
|
||||||
|
depth: usize
|
||||||
) -> Arc<RwLock<Self>> {
|
) -> Arc<RwLock<Self>> {
|
||||||
let out_port = ViewPort::new();
|
let out_port = ViewPort::new();
|
||||||
let mut proj_helper = ProjectionHelper::new(out_port.update_hooks.clone());
|
let mut proj_helper = ProjectionHelper::new(out_port.update_hooks.clone());
|
||||||
let proj = Arc::new(RwLock::new(ListSegmentSequence {
|
let proj = Arc::new(RwLock::new(ListSegmentSequence {
|
||||||
cur_cursor: cursor_port.get_view().get(),
|
cur_cursor: cursor_port.get_view().get(),
|
||||||
port: out_port.clone(),
|
port: out_port.clone(),
|
||||||
|
depth,
|
||||||
|
|
||||||
cursor: proj_helper.new_singleton_arg(0, cursor_port, |s: &mut Self, _msg| {
|
cursor: proj_helper.new_singleton_arg(0, cursor_port, |s: &mut Self, _msg| {
|
||||||
let _old_cursor = s.cur_cursor;
|
let _old_cursor = s.cur_cursor;
|
||||||
|
|
|
@ -9,9 +9,8 @@ use {
|
||||||
index_hashmap::*
|
index_hashmap::*
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
laddertypes::{TypeTerm},
|
|
||||||
crate::{
|
crate::{
|
||||||
type_system::{Context},
|
type_system::{Context, TypeTerm},
|
||||||
terminal::{
|
terminal::{
|
||||||
TerminalEditor, TerminalEditorResult,
|
TerminalEditor, TerminalEditorResult,
|
||||||
TerminalEvent, TerminalView
|
TerminalEvent, TerminalView
|
||||||
|
@ -203,7 +202,7 @@ impl ObjCommander for ProductEditor {
|
||||||
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
|
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
|
||||||
let co = cmd_obj.read().unwrap();
|
let co = cmd_obj.read().unwrap();
|
||||||
let cmd_type = co.get_type().clone();
|
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 cmd_type == term_event_type {
|
||||||
if let Some(te_view) = co.get_view::<dyn SingletonView<Item = TerminalEvent>>() {
|
if let Some(te_view) = co.get_view::<dyn SingletonView<Item = TerminalEvent>>() {
|
||||||
|
@ -239,7 +238,7 @@ impl ObjCommander for ProductEditor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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());
|
*editor = Some(e.clone());
|
||||||
update_segment = true;
|
update_segment = true;
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ impl TreeNav for ProductEditor {
|
||||||
e.goto(c.clone());
|
e.goto(c.clone());
|
||||||
} else if c.tree_addr.len() > 0 {
|
} else if c.tree_addr.len() > 0 {
|
||||||
// create editor
|
// 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());
|
*editor = Some(e.clone());
|
||||||
e.goto(c.clone());
|
e.goto(c.clone());
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ impl TreeNav for ProductEditor {
|
||||||
} else {
|
} else {
|
||||||
// create editor
|
// 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());
|
*editor = Some(e.clone());
|
||||||
e.goby(direction);
|
e.goby(direction);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,8 @@ use {
|
||||||
OuterViewPort
|
OuterViewPort
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
laddertypes::{TypeTerm},
|
|
||||||
crate::{
|
crate::{
|
||||||
type_system::{Context},
|
type_system::{Context, TypeTerm},
|
||||||
terminal::{
|
terminal::{
|
||||||
TerminalStyle, TerminalView,
|
TerminalStyle, TerminalView,
|
||||||
make_label
|
make_label
|
||||||
|
|
|
@ -6,11 +6,10 @@ use {
|
||||||
sequence::*,
|
sequence::*,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
laddertypes::{TypeTerm},
|
|
||||||
crate::{
|
crate::{
|
||||||
terminal::TerminalView,
|
terminal::TerminalView,
|
||||||
editors::list::ListCursorMode,
|
editors::list::ListCursorMode,
|
||||||
type_system::{Context, ReprTree},
|
type_system::{Context, TypeTerm, ReprTree},
|
||||||
tree::{TreeNav, TreeCursor, TreeNavResult},
|
tree::{TreeNav, TreeCursor, TreeNavResult},
|
||||||
diagnostics::{Diagnostics, Message},
|
diagnostics::{Diagnostics, Message},
|
||||||
tree::NestedNode,
|
tree::NestedNode,
|
||||||
|
@ -61,7 +60,7 @@ impl SumEditor {
|
||||||
NestedNode::new(
|
NestedNode::new(
|
||||||
ctx.clone(),
|
ctx.clone(),
|
||||||
ReprTree::new_arc(TypeTerm::TypeID(ctx.read().unwrap().get_typeid("Sum").unwrap())),
|
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_view(view)
|
||||||
.set_editor(editor.clone())
|
.set_editor(editor.clone())
|
||||||
|
|
|
@ -3,8 +3,8 @@ use {
|
||||||
view::{singleton::*}
|
view::{singleton::*}
|
||||||
},
|
},
|
||||||
crate::{
|
crate::{
|
||||||
type_system::{Context, ReprTree},
|
type_system::{ReprTree},
|
||||||
editors::{list::{ListEditor, ListCmd, ListCursorMode}},
|
editors::{list::{ListEditor, ListCmd}},
|
||||||
tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor},
|
tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor},
|
||||||
commander::ObjCommander
|
commander::ObjCommander
|
||||||
},
|
},
|
||||||
|
@ -20,7 +20,7 @@ impl ObjCommander for TypeTermEditor {
|
||||||
let cmd_obj = co.clone();
|
let cmd_obj = co.clone();
|
||||||
let cmd_obj = cmd_obj.read().unwrap();
|
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>>() {
|
if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() {
|
||||||
let c = cmd_view.get();
|
let c = cmd_view.get();
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ impl ObjCommander for TypeTermEditor {
|
||||||
TreeNavResult::Exit
|
TreeNavResult::Exit
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.set_state( State::FunSymbol );
|
self.set_state( State::AnySymbol );
|
||||||
self.cur_node.get_mut().goto(TreeCursor::home());
|
self.cur_node.get_mut().goto(TreeCursor::home());
|
||||||
self.send_child_cmd( co )
|
self.send_child_cmd( co )
|
||||||
}
|
}
|
||||||
|
@ -52,109 +52,43 @@ impl ObjCommander for TypeTermEditor {
|
||||||
}
|
}
|
||||||
|
|
||||||
State::Char => {
|
State::Char => {
|
||||||
match self.send_child_cmd( co ) {
|
|
||||||
TreeNavResult::Exit => {
|
|
||||||
match c {
|
match c {
|
||||||
'\'' => {
|
'\'' => {
|
||||||
self.cur_node.get_mut().goto(TreeCursor::none());
|
self.cur_node.get_mut().goto(TreeCursor::none());
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
TreeNavResult::Exit
|
TreeNavResult::Exit
|
||||||
},
|
}
|
||||||
TreeNavResult::Continue => TreeNavResult::Continue
|
_ => {
|
||||||
|
self.send_child_cmd( co )
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
State::Ladder => {
|
State::Ladder => {
|
||||||
|
let res = self.send_child_cmd( co.clone() );
|
||||||
|
|
||||||
match self.get_cursor().tree_addr.len() {
|
match res {
|
||||||
|
TreeNavResult::Continue => {
|
||||||
// entire term is selected
|
|
||||||
0 => {
|
|
||||||
match c {
|
|
||||||
'<' => {
|
|
||||||
self.morph_to_list(State::App);
|
|
||||||
TreeNavResult::Continue
|
|
||||||
}
|
|
||||||
_ => { TreeNavResult::Exit }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// entire item selected or insert mode
|
|
||||||
1 => {
|
|
||||||
match c {
|
match c {
|
||||||
'~' => {
|
'~' => {
|
||||||
// ignore '~' since we are already in a ladder
|
self.normalize_nested_ladder();
|
||||||
// and cant split current item
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
TreeNavResult::Continue
|
TreeNavResult::Continue
|
||||||
}
|
}
|
||||||
_ => {
|
TreeNavResult::Exit => {
|
||||||
self.send_child_cmd( co.clone() )
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// some subterm
|
|
||||||
_ => {
|
|
||||||
match c {
|
match c {
|
||||||
'~' => {
|
'~' => TreeNavResult::Continue,
|
||||||
let i0 = self.cur_node.get().get_edit::<ListEditor>().unwrap();
|
_ => TreeNavResult::Exit
|
||||||
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() )
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
State::App => {
|
State::App => {
|
||||||
|
let res = self.send_child_cmd( co.clone() );
|
||||||
|
|
||||||
match self.get_cursor().tree_addr.len() {
|
match res {
|
||||||
|
|
||||||
// entire Term is selected
|
|
||||||
0 => {
|
|
||||||
|
|
||||||
match c {
|
|
||||||
'~' => {
|
|
||||||
self.morph_to_list(State::Ladder);
|
|
||||||
self.goto(TreeCursor {
|
|
||||||
tree_addr: vec![ -1 ],
|
|
||||||
leaf_mode: ListCursorMode::Insert
|
|
||||||
});
|
|
||||||
TreeNavResult::Continue
|
|
||||||
}
|
|
||||||
'<' => {
|
|
||||||
self.morph_to_list(State::App);
|
|
||||||
TreeNavResult::Continue
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
TreeNavResult::Exit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
// some item is selected
|
|
||||||
_ => {
|
|
||||||
match self.send_child_cmd( co.clone() ) {
|
|
||||||
TreeNavResult::Exit => {
|
TreeNavResult::Exit => {
|
||||||
match c {
|
match c {
|
||||||
'~' => {
|
'~' => {
|
||||||
|
@ -181,12 +115,11 @@ impl ObjCommander for TypeTermEditor {
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeNavResult::Continue
|
TreeNavResult::Continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
State::AnySymbol |
|
State::AnySymbol |
|
||||||
State::FunSymbol |
|
State::FunSymbol |
|
||||||
|
@ -195,19 +128,11 @@ impl ObjCommander for TypeTermEditor {
|
||||||
match res {
|
match res {
|
||||||
TreeNavResult::Exit => {
|
TreeNavResult::Exit => {
|
||||||
match c {
|
match c {
|
||||||
'<' => {
|
|
||||||
self.goto(TreeCursor::none());
|
|
||||||
self.morph_to_list(State::App);
|
|
||||||
TreeNavResult::Continue
|
|
||||||
}
|
|
||||||
'~' => {
|
'~' => {
|
||||||
self.morph_to_list(State::Ladder);
|
self.morph_to_ladder();
|
||||||
self.set_addr(0);
|
|
||||||
self.dn();
|
|
||||||
self.send_cmd_obj(
|
self.send_cmd_obj(
|
||||||
ListCmd::Split.into_repr_tree( &self.ctx )
|
ListCmd::Split.into_repr_tree( &self.ctx )
|
||||||
);
|
)
|
||||||
TreeNavResult::Continue
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
TreeNavResult::Exit
|
TreeNavResult::Exit
|
||||||
|
@ -231,11 +156,11 @@ impl ObjCommander for TypeTermEditor {
|
||||||
match &self.state {
|
match &self.state {
|
||||||
State::Any => {
|
State::Any => {
|
||||||
let cmd_repr = co.read().unwrap();
|
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>>() {
|
if let Some(view) = cmd_repr.get_view::<dyn SingletonView<Item = NestedNode>>() {
|
||||||
let node = view.get();
|
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 );
|
self.set_state( State::AnySymbol );
|
||||||
} else {
|
} else {
|
||||||
self.set_state( State::Ladder );
|
self.set_state( State::Ladder );
|
||||||
|
@ -259,6 +184,7 @@ impl ObjCommander for TypeTermEditor {
|
||||||
let res = self.send_child_cmd( co.clone() );
|
let res = self.send_child_cmd( co.clone() );
|
||||||
|
|
||||||
self.normalize_empty();
|
self.normalize_empty();
|
||||||
|
|
||||||
if let Some(cmd) = co.read().unwrap().get_view::<dyn SingletonView<Item = ListCmd>>() {
|
if let Some(cmd) = co.read().unwrap().get_view::<dyn SingletonView<Item = ListCmd>>() {
|
||||||
match cmd.get() {
|
match cmd.get() {
|
||||||
ListCmd::Split => {
|
ListCmd::Split => {
|
||||||
|
|
|
@ -1,16 +1,8 @@
|
||||||
use {
|
use {
|
||||||
r3vi::{
|
|
||||||
view::{OuterViewPort, singleton::*}
|
|
||||||
},
|
|
||||||
laddertypes::{TypeTerm},
|
|
||||||
crate::{
|
crate::{
|
||||||
type_system::{Context, MorphismTypePattern},
|
type_system::{Context, TypeTerm, MorphismTypePattern},
|
||||||
terminal::{TerminalStyle, TerminalProjections},
|
terminal::{TerminalStyle, TerminalProjections},
|
||||||
editors::{
|
editors::{list::{PTYListStyle, PTYListController}, typeterm::{State, TypeTermEditor}}
|
||||||
list::{PTYListStyle, PTYListController, ListEditor, ListSegmentSequence},
|
|
||||||
typeterm::{State, TypeTermEditor}
|
|
||||||
},
|
|
||||||
PtySegment
|
|
||||||
},
|
},
|
||||||
std::{sync::{Arc, RwLock}},
|
std::{sync::{Arc, RwLock}},
|
||||||
cgmath::{Point2}
|
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()))));
|
let ctx : Arc<RwLock<Context>> = Arc::new(RwLock::new(Context::with_parent(Some(node.ctx.clone()))));
|
||||||
ctx.write().unwrap().meta_chars.push('~');
|
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)
|
Some(new_node)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -42,29 +34,14 @@ pub fn init_ctx(ctx: &mut Context) {
|
||||||
Arc::new(|mut node, _dst_type: _| {
|
Arc::new(|mut node, _dst_type: _| {
|
||||||
PTYListController::for_node( &mut node, Some('~'), None );
|
PTYListController::for_node( &mut node, Some('~'), None );
|
||||||
|
|
||||||
let vertical_view = true;
|
let vertical_view = false;
|
||||||
if vertical_view {
|
if vertical_view {
|
||||||
let editor = node.get_edit::<crate::editors::list::ListEditor>().unwrap();
|
let editor = node.get_edit::<crate::editors::list::ListEditor>().unwrap();
|
||||||
let mut e = editor.write().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(
|
node = node.set_view(
|
||||||
seg_view.to_grid_vertical()
|
seg_view.to_grid_vertical().flatten()
|
||||||
.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()
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
PTYListStyle::for_node( &mut node, ("","~","") );
|
PTYListStyle::for_node( &mut node, ("","~","") );
|
||||||
|
@ -94,7 +71,6 @@ pub fn init_ctx(ctx: &mut Context) {
|
||||||
Arc::new(|mut node, _dst_type:_| {
|
Arc::new(|mut node, _dst_type:_| {
|
||||||
PTYListController::for_node( &mut node, Some(' '), None );
|
PTYListController::for_node( &mut node, Some(' '), None );
|
||||||
PTYListStyle::for_node( &mut node, ("","","") );
|
PTYListStyle::for_node( &mut node, ("","","") );
|
||||||
|
|
||||||
Some(node)
|
Some(node)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -104,6 +80,11 @@ pub fn init_ctx(ctx: &mut Context) {
|
||||||
PTYListController::for_node( &mut node, Some(' '), None );
|
PTYListController::for_node( &mut node, Some(' '), None );
|
||||||
PTYListStyle::for_node( &mut node, ("","","") );
|
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)
|
Some(node)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -116,7 +97,6 @@ pub fn init_ctx(ctx: &mut Context) {
|
||||||
ctx.add_morphism(
|
ctx.add_morphism(
|
||||||
MorphismTypePattern { src_tyid: ctx.get_typeid("Char"), dst_tyid: ctx.get_typeid("Type::Lit::Char").unwrap() },
|
MorphismTypePattern { src_tyid: ctx.get_typeid("Char"), dst_tyid: ctx.get_typeid("Type::Lit::Char").unwrap() },
|
||||||
Arc::new(|mut node, _dst_type:_| {
|
Arc::new(|mut node, _dst_type:_| {
|
||||||
node.ctx.write().unwrap().meta_chars = vec![ '\'' ];
|
|
||||||
let mut grid = r3vi::buffer::index_hashmap::IndexBuffer::new();
|
let mut grid = r3vi::buffer::index_hashmap::IndexBuffer::new();
|
||||||
|
|
||||||
grid.insert_iter(
|
grid.insert_iter(
|
||||||
|
@ -137,7 +117,7 @@ pub fn init_ctx(ctx: &mut Context) {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
ctx.add_node_ctor("Type", Arc::new(
|
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))
|
Some(TypeTermEditor::new_node(ctx, depth))
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,10 @@ pub use ctx::init_ctx;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
r3vi::{
|
r3vi::{
|
||||||
view::{OuterViewPort, singleton::*},
|
|
||||||
buffer::{singleton::*}
|
buffer::{singleton::*}
|
||||||
},
|
},
|
||||||
laddertypes::{TypeID, TypeTerm},
|
|
||||||
crate::{
|
crate::{
|
||||||
type_system::{Context, ReprTree},
|
type_system::{Context, TypeID, TypeTerm, ReprTree},
|
||||||
editors::{list::{ListCursorMode, ListEditor, ListCmd}},
|
editors::{list::{ListCursorMode, ListEditor, ListCmd}},
|
||||||
tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor},
|
tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor},
|
||||||
commander::ObjCommander
|
commander::ObjCommander
|
||||||
|
@ -38,9 +36,8 @@ pub struct TypeTermEditor {
|
||||||
data: Arc<RwLock<ReprTree>>,
|
data: Arc<RwLock<ReprTree>>,
|
||||||
close_char: SingletonBuffer<Option<char>>,
|
close_char: SingletonBuffer<Option<char>>,
|
||||||
spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>,
|
spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>,
|
||||||
depth: OuterViewPort<dyn SingletonView<Item = usize>>,
|
|
||||||
|
|
||||||
buf: SingletonBuffer< TypeTerm >,
|
depth: usize,
|
||||||
|
|
||||||
// editing/parsing state
|
// editing/parsing state
|
||||||
state: State,
|
state: State,
|
||||||
|
@ -50,8 +47,8 @@ pub struct TypeTermEditor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeTermEditor {
|
impl TypeTermEditor {
|
||||||
pub fn from_type_term(ctx: Arc<RwLock<Context>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>, term: &TypeTerm) -> NestedNode {
|
pub fn from_type_term(ctx: Arc<RwLock<Context>>, depth: usize, term: &TypeTerm) -> NestedNode {
|
||||||
let mut node = TypeTermEditor::new_node(ctx.clone(), depth.clone());
|
let mut node = TypeTermEditor::new_node(ctx.clone(), depth);
|
||||||
node.goto(TreeCursor::home());
|
node.goto(TreeCursor::home());
|
||||||
|
|
||||||
match term {
|
match term {
|
||||||
|
@ -77,11 +74,11 @@ impl TypeTermEditor {
|
||||||
let parent_ctx = editor.read().unwrap().cur_node.get().ctx.clone();
|
let parent_ctx = editor.read().unwrap().cur_node.get().ctx.clone();
|
||||||
|
|
||||||
for x in args.iter() {
|
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(
|
node.send_cmd_obj(
|
||||||
ReprTree::new_leaf(
|
ReprTree::new_leaf(
|
||||||
Context::parse(&ctx, "NestedNode"),
|
(&ctx, "( NestedNode )"),
|
||||||
SingletonBuffer::new(arg_node).get_port().into()
|
SingletonBuffer::new(arg_node).get_port().into()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -95,11 +92,11 @@ impl TypeTermEditor {
|
||||||
let parent_ctx = editor.read().unwrap().cur_node.get().ctx.clone();
|
let parent_ctx = editor.read().unwrap().cur_node.get().ctx.clone();
|
||||||
|
|
||||||
for x in args.iter() {
|
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(
|
node.send_cmd_obj(
|
||||||
ReprTree::new_leaf(
|
ReprTree::new_leaf(
|
||||||
Context::parse(&ctx, "NestedNode"),
|
(&ctx, "( NestedNode )"),
|
||||||
SingletonBuffer::new(arg_node).get_port().into()
|
SingletonBuffer::new(arg_node).get_port().into()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -133,37 +130,38 @@ impl TypeTermEditor {
|
||||||
fn set_state(&mut self, new_state: State) {
|
fn set_state(&mut self, new_state: State) {
|
||||||
let mut node = match new_state {
|
let mut node = match new_state {
|
||||||
State::Any => {
|
State::Any => {
|
||||||
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Char>"), self.depth.map(|x| x) ).unwrap()
|
Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth ).unwrap()
|
||||||
.morph( Context::parse(&self.ctx, "Type::Sym") )
|
.morph( (&self.ctx, "( Type::Sym )").into() )
|
||||||
|
|
||||||
}
|
}
|
||||||
State::App => {
|
State::App => {
|
||||||
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Type>"), self.depth.map(|x| x) ).unwrap()
|
Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth ).unwrap()
|
||||||
.morph( Context::parse(&self.ctx, "Type::App") )
|
.morph( (&self.ctx, "( Type::App )").into() )
|
||||||
}
|
}
|
||||||
State::Ladder => {
|
State::Ladder => {
|
||||||
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Type>"), self.depth.map(|x| x) ).unwrap()
|
Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth ).unwrap()
|
||||||
.morph( Context::parse(&self.ctx, "Type::Ladder") )
|
.morph( (&self.ctx, "( Type::Ladder )").into() )
|
||||||
}
|
}
|
||||||
State::AnySymbol => {
|
State::AnySymbol => {
|
||||||
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Char>"), self.depth.map(|x| x) ).unwrap()
|
Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth ).unwrap()
|
||||||
.morph( Context::parse(&self.ctx, "Type::Sym") )
|
.morph( (&self.ctx, "( Type::Sym )").into() )
|
||||||
},
|
},
|
||||||
State::FunSymbol => {
|
State::FunSymbol => {
|
||||||
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Char>"), self.depth.map(|x| x) ).unwrap()
|
Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth ).unwrap()
|
||||||
.morph( Context::parse(&self.ctx, "Type::Sym::Fun") )
|
.morph( (&self.ctx, "( Type::Sym::Fun )").into() )
|
||||||
},
|
},
|
||||||
State::VarSymbol => {
|
State::VarSymbol => {
|
||||||
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Char>"), self.depth.map(|x| x) ).unwrap()
|
Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth ).unwrap()
|
||||||
.morph( Context::parse(&self.ctx, "Type::Sym::Var") )
|
.morph( (&self.ctx, "( Type::Sym::Var )").into() )
|
||||||
}
|
}
|
||||||
State::Num => {
|
State::Num => {
|
||||||
crate::editors::integer::PosIntEditor::new(self.ctx.clone(), 10)
|
crate::editors::integer::PosIntEditor::new(self.ctx.clone(), 10)
|
||||||
.into_node()
|
.into_node()
|
||||||
.morph( Context::parse(&self.ctx, "Type::Lit::Num") )
|
.morph( (&self.ctx, "( Type::Lit::Num )").into() )
|
||||||
}
|
}
|
||||||
State::Char => {
|
State::Char => {
|
||||||
Context::make_node( &self.ctx, Context::parse(&self.ctx, "Char"), self.depth.map(|x| x) ).unwrap()
|
Context::make_node( &self.ctx, (&self.ctx, "( Char )").into(), self.depth ).unwrap()
|
||||||
.morph( Context::parse(&self.ctx, "Type::Lit::Char") )
|
.morph( (&self.ctx, "( Type::Lit::Char )").into() )
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -175,37 +173,36 @@ impl TypeTermEditor {
|
||||||
self.state = new_state;
|
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))));
|
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('~');
|
||||||
ctx.write().unwrap().meta_chars.push('<');
|
|
||||||
|
|
||||||
let mut symb_node = Context::make_node( &ctx, Context::parse(&ctx, "<List Char>"), depth ).unwrap();
|
let mut symb_node = Context::make_node( &ctx, (&ctx, "( List Char )").into(), depth ).unwrap();
|
||||||
symb_node = symb_node.morph( Context::parse(&ctx, "Type::Sym") );
|
symb_node = symb_node.morph( (&ctx, "( Type::Sym )").into() );
|
||||||
|
|
||||||
Self::with_node(
|
Self::with_node(
|
||||||
ctx.clone(),
|
ctx.clone(),
|
||||||
|
depth,
|
||||||
symb_node,
|
symb_node,
|
||||||
State::Any
|
State::Any
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_node(ctx: Arc<RwLock<Context>>, cur_node: NestedNode, state: State) -> NestedNode {
|
fn with_node(ctx: Arc<RwLock<Context>>, depth: usize, node: NestedNode, state: State) -> NestedNode {
|
||||||
let buf = SingletonBuffer::<TypeTerm>::new( TypeTerm::unit() );
|
let _buffer = SingletonBuffer::<Option<TypeTerm>>::new( None );
|
||||||
|
|
||||||
let data = Arc::new(RwLock::new(ReprTree::new(
|
let data = Arc::new(RwLock::new(ReprTree::new(
|
||||||
Context::parse(&ctx, "Type")
|
(&ctx, "( Type )")
|
||||||
)));
|
)));
|
||||||
|
|
||||||
let editor = TypeTermEditor {
|
let editor = TypeTermEditor {
|
||||||
ctx: ctx.clone(),
|
ctx: ctx.clone(),
|
||||||
data: data.clone(),
|
data: data.clone(),
|
||||||
state,
|
state,
|
||||||
buf,
|
cur_node: SingletonBuffer::new(node),
|
||||||
cur_node: SingletonBuffer::new(cur_node.clone()),
|
|
||||||
close_char: SingletonBuffer::new(None),
|
close_char: SingletonBuffer::new(None),
|
||||||
spillbuf: Arc::new(RwLock::new(Vec::new())),
|
spillbuf: Arc::new(RwLock::new(Vec::new())),
|
||||||
depth: cur_node.depth.clone()
|
depth
|
||||||
};
|
};
|
||||||
|
|
||||||
let view = editor.cur_node
|
let view = editor.cur_node
|
||||||
|
@ -218,16 +215,16 @@ impl TypeTermEditor {
|
||||||
let _cc = editor.cur_node.get().close_char;
|
let _cc = editor.cur_node.get().close_char;
|
||||||
let editor = Arc::new(RwLock::new(editor));
|
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_view(view)
|
||||||
.set_nav(editor.clone())
|
.set_nav(editor.clone())
|
||||||
.set_cmd(editor.clone())
|
.set_cmd(editor.clone())
|
||||||
.set_editor(editor.clone());
|
.set_editor(editor.clone());
|
||||||
|
|
||||||
editor.write().unwrap().close_char = super_node.close_char.clone();
|
editor.write().unwrap().close_char = node.close_char.clone();
|
||||||
super_node.spillbuf = editor.read().unwrap().spillbuf.clone();
|
node.spillbuf = editor.read().unwrap().spillbuf.clone();
|
||||||
|
|
||||||
super_node
|
node
|
||||||
}
|
}
|
||||||
|
|
||||||
fn forward_spill(&mut self) {
|
fn forward_spill(&mut self) {
|
||||||
|
@ -291,16 +288,16 @@ impl TypeTermEditor {
|
||||||
|
|
||||||
let subladder_list_edit = subladder_list_edit.read().unwrap();
|
let subladder_list_edit = subladder_list_edit.read().unwrap();
|
||||||
if subladder_list_edit.data.len() == 0 {
|
if subladder_list_edit.data.len() == 0 {
|
||||||
|
|
||||||
self.set_state( State::Any );
|
self.set_state( State::Any );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* unwrap a ladder if it only contains one element
|
/* unwrap a ladder if it only contains one element
|
||||||
*/
|
*/
|
||||||
pub fn normalize_singleton(&mut self) {
|
pub fn normalize_singleton(&mut self) {
|
||||||
eprintln!("normalize singleton");
|
eprintln!("normalize singleton");
|
||||||
|
|
||||||
if self.state == State::Ladder {
|
|
||||||
let subladder_list_node = self.cur_node.get().clone();
|
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_node.get_edit::<ListEditor>().unwrap();
|
||||||
|
|
||||||
|
@ -308,18 +305,55 @@ impl TypeTermEditor {
|
||||||
if subladder_list_edit.data.len() == 1 {
|
if subladder_list_edit.data.len() == 1 {
|
||||||
let it_node = subladder_list_edit.data.get(0);
|
let it_node = subladder_list_edit.data.get(0);
|
||||||
let it_node = it_node.read().unwrap();
|
let it_node = it_node.read().unwrap();
|
||||||
if it_node.get_type() == Context::parse(&self.ctx, "Type") {
|
if it_node.get_type() == (&self.ctx, "( Type )").into() {
|
||||||
let other_tt = it_node.get_edit::<TypeTermEditor>().unwrap();
|
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.close_char.set(other_tt.close_char.get());
|
||||||
self.cur_node.set(other_tt.cur_node.get());
|
self.cur_node.set(other_tt.cur_node.get());
|
||||||
self.state = other_tt.state;
|
self.state = other_tt.state;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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();
|
app_edit.delete_nexd();
|
||||||
}
|
}
|
||||||
|
|
||||||
// select previous element
|
|
||||||
app_edit.goto(TreeCursor{
|
app_edit.goto(TreeCursor{
|
||||||
tree_addr: vec![ cur.tree_addr[0]-1 ],
|
tree_addr: vec![ cur.tree_addr[0]-1 ],
|
||||||
leaf_mode: ListCursorMode::Select
|
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 item_typterm = item_node.get_edit::<TypeTermEditor>().expect("typetermedit");
|
||||||
let mut item_typterm = item_typterm.write().unwrap();
|
let mut item_typterm = item_typterm.write().unwrap();
|
||||||
if item_typterm.state != State::Ladder {
|
match item_typterm.state {
|
||||||
item_typterm.morph_to_list( State::Ladder );
|
|
||||||
}
|
|
||||||
|
|
||||||
item_typterm.goto(TreeCursor {
|
// if item at cursor is Ladder
|
||||||
tree_addr: vec![ -1 ],
|
State::Ladder => {
|
||||||
leaf_mode: ListCursorMode::Insert
|
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");
|
eprintln!("morph into ladder");
|
||||||
|
let old_node = self.cur_node.get().clone();
|
||||||
|
|
||||||
let mut old_node = self.cur_node.get().clone();
|
*old_node.depth.get_mut() += 1;
|
||||||
|
|
||||||
/* reconfigure current node to display new_node list-editor
|
|
||||||
*/
|
|
||||||
self.set_state( state );
|
|
||||||
|
|
||||||
/* create a new NestedNode with TerminaltypeEditor,
|
/* create a new NestedNode with TerminaltypeEditor,
|
||||||
* that has same state & child-node as current node.
|
* that has same state & child-node as current node.
|
||||||
*/
|
*/
|
||||||
let old_edit_node = TypeTermEditor::new_node( self.ctx.clone(), SingletonBuffer::new(0).get_port() );
|
let old_edit_node = TypeTermEditor::new_node( self.ctx.clone(), self.depth );
|
||||||
old_node.depth.0.set_view( old_edit_node.depth.map(|x|x).get_view() );
|
|
||||||
|
|
||||||
let old_edit_clone = old_edit_node.get_edit::<TypeTermEditor>().unwrap();
|
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().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 );
|
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
|
/* insert old node and split
|
||||||
*/
|
*/
|
||||||
self.goto(TreeCursor::home());
|
self.goto(TreeCursor::home());
|
||||||
self.send_child_cmd(
|
self.send_cmd_obj(
|
||||||
ReprTree::new_leaf(
|
ReprTree::new_leaf(
|
||||||
Context::parse(&self.ctx, "NestedNode"),
|
(&self.ctx, "( NestedNode )"),
|
||||||
SingletonBuffer::new( old_edit_node ).get_port().into()
|
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)
|
self.cur_node.get_mut().goto(new_cur)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,17 +24,6 @@ impl TreeCursor {
|
||||||
tree_addr: vec![],
|
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 {
|
impl Default for TreeCursor {
|
||||||
|
|
|
@ -21,10 +21,10 @@ use {
|
||||||
cgmath::Vector2,
|
cgmath::Vector2,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||||
pub enum TreeNavResult { Continue, Exit }
|
pub enum TreeNavResult { Continue, Exit }
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||||
pub enum TreeHeightOp { P, Q, Max }
|
pub enum TreeHeightOp { P, Q, Max }
|
||||||
|
|
||||||
pub trait TreeNav {
|
pub trait TreeNav {
|
||||||
|
@ -181,4 +181,3 @@ pub trait TreeNav {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,8 @@ use {
|
||||||
view::{View, ViewPort, OuterViewPort, AnyOuterViewPort, singleton::*, sequence::*},
|
view::{View, ViewPort, OuterViewPort, AnyOuterViewPort, singleton::*, sequence::*},
|
||||||
buffer::{singleton::*}
|
buffer::{singleton::*}
|
||||||
},
|
},
|
||||||
laddertypes::{TypeTerm},
|
|
||||||
crate::{
|
crate::{
|
||||||
type_system::{ReprTree, Context},
|
type_system::{ReprTree, Context, TypeTerm},
|
||||||
terminal::{TerminalView, TerminalEvent, TerminalEditor, TerminalEditorResult, TerminalAtom},
|
terminal::{TerminalView, TerminalEvent, TerminalEditor, TerminalEditorResult, TerminalAtom},
|
||||||
diagnostics::{Diagnostics, Message},
|
diagnostics::{Diagnostics, Message},
|
||||||
tree::{TreeNav, TreeCursor, TreeNavResult, TreeHeightOp},
|
tree::{TreeNav, TreeCursor, TreeNavResult, TreeHeightOp},
|
||||||
|
@ -35,13 +34,16 @@ struct NestedNodeEdit {
|
||||||
Option< Arc<dyn Any + Send + Sync> >
|
Option< Arc<dyn Any + Send + Sync> >
|
||||||
>,
|
>,
|
||||||
|
|
||||||
pub spillbuf: VecBuffer< NestedNode >,
|
pub input_buf:: VecBuffer< NestedNode >,
|
||||||
|
pub output_buf: VecBuffer< NestedNode >,
|
||||||
|
|
||||||
/// commander & navigation
|
/// commander & navigation
|
||||||
pub cmd: SingletonBuffer<
|
pub cmd: SingletonBuffer<
|
||||||
Option< Arc<RwLock<dyn ObjCommander + Send + Sync>> >
|
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
|
// could be replaced by cmd when TreeNav -CmdObjects are used
|
||||||
pub tree_nav: SingletonBuffer<
|
pub tree_nav: SingletonBuffer<
|
||||||
|
@ -80,13 +82,16 @@ pub struct NestedNode {
|
||||||
pub diag: Option< OuterViewPort<dyn SequenceView<Item = Message>> >,
|
pub diag: Option< OuterViewPort<dyn SequenceView<Item = Message>> >,
|
||||||
|
|
||||||
/// depth
|
/// depth
|
||||||
pub depth: OuterViewPort< dyn SingletonView<Item = usize> >,
|
pub depth: SingletonBuffer< usize >,
|
||||||
|
|
||||||
/// abstract editor
|
/// abstract editor
|
||||||
pub editor: SingletonBuffer<
|
pub editor: SingletonBuffer<
|
||||||
Option< Arc<dyn Any + Send + Sync> >
|
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>>>>>,
|
pub spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>,
|
||||||
|
|
||||||
/// commander & navigation
|
/// commander & navigation
|
||||||
|
@ -102,13 +107,13 @@ pub struct NestedNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
NestedNode {
|
||||||
ctx,
|
ctx,
|
||||||
data,
|
data,
|
||||||
view: None,
|
view: None,
|
||||||
diag: None,
|
diag: None,
|
||||||
depth,
|
depth: SingletonBuffer::new(depth),
|
||||||
editor: SingletonBuffer::new(None),
|
editor: SingletonBuffer::new(None),
|
||||||
spillbuf: Arc::new(RwLock::new(Vec::new())),
|
spillbuf: Arc::new(RwLock::new(Vec::new())),
|
||||||
cmd: SingletonBuffer::new(None),
|
cmd: SingletonBuffer::new(None),
|
||||||
|
@ -125,10 +130,10 @@ impl NestedNode {
|
||||||
NestedNode::new(
|
NestedNode::new(
|
||||||
ctx.clone(),
|
ctx.clone(),
|
||||||
ReprTree::new_leaf(
|
ReprTree::new_leaf(
|
||||||
Context::parse(&ctx, "Char"),
|
(&ctx, "( Char )"),
|
||||||
buf.get_port().into()
|
buf.get_port().into()
|
||||||
),
|
),
|
||||||
SingletonBuffer::new(0).get_port()
|
0
|
||||||
)
|
)
|
||||||
.set_view(buf.get_port()
|
.set_view(buf.get_port()
|
||||||
.map(|c| TerminalAtom::from(c))
|
.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>>
|
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 {
|
where V::Msg: Clone {
|
||||||
let ctx = self.ctx.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)?;
|
let repr_tree = ReprTree::descend_ladder(&self.data, type_ladder)?;
|
||||||
repr_tree.clone().read().unwrap()
|
repr_tree.clone().read().unwrap()
|
||||||
|
@ -257,7 +262,7 @@ impl TerminalEditor for NestedNode {
|
||||||
if let Some(cmd) = self.cmd.get() {
|
if let Some(cmd) = self.cmd.get() {
|
||||||
cmd.write().unwrap().send_cmd_obj(
|
cmd.write().unwrap().send_cmd_obj(
|
||||||
ReprTree::new_leaf(
|
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())
|
AnyOuterViewPort::from(buf.get_port())
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
|
|
||||||
use {
|
use {
|
||||||
laddertypes::{TypeTerm, TypeID},
|
|
||||||
crate::{
|
crate::{
|
||||||
|
type_system::{TypeTerm, TypeID},
|
||||||
tree::{TreeAddr}
|
tree::{TreeAddr}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait TreeType {
|
pub trait TreeType {
|
||||||
fn get_type(&self, addr: &TreeAddr) -> Vec<TypeTerm> {
|
fn get_type(&self, _addr: &TreeAddr) -> TypeTerm {
|
||||||
vec![]
|
TypeTerm::new(TypeID::Var(0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
use {
|
use {
|
||||||
r3vi::{view::{OuterViewPort, singleton::*}, buffer::{singleton::*}},
|
|
||||||
laddertypes::{TypeDict, TypeTerm, TypeID},
|
|
||||||
crate::{
|
crate::{
|
||||||
type_system::{ReprTree},
|
type_system::{TypeDict, TypeTerm, TypeID, ReprTree},
|
||||||
tree::NestedNode
|
tree::NestedNode
|
||||||
},
|
},
|
||||||
std::{
|
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 {
|
impl Context {
|
||||||
pub fn with_parent(parent: Option<Arc<RwLock<Context>>>) -> Self {
|
pub fn with_parent(parent: Option<Arc<RwLock<Context>>>) -> Self {
|
||||||
Context {
|
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 {
|
pub fn add_typename(&mut self, tn: &str) -> TypeID {
|
||||||
self.type_dict.write().unwrap().add_typename(tn.to_string())
|
self.type_dict.write().unwrap().add_typename(tn.to_string())
|
||||||
}
|
}
|
||||||
|
@ -195,18 +195,6 @@ impl Context {
|
||||||
TypeTerm::TypeID(id) => {
|
TypeTerm::TypeID(id) => {
|
||||||
self.list_types.contains(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
|
_ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -233,15 +221,15 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_term_from_str(&self, tn: &str) -> Result<TypeTerm, laddertypes::parser::ParseError> {
|
pub fn type_term_from_str(&self, tn: &str) -> Option<TypeTerm> {
|
||||||
self.type_dict.write().unwrap().parse(&tn)
|
self.type_dict.read().unwrap().type_term_from_str(&tn)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_term_to_str(&self, t: &TypeTerm) -> String {
|
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 dict = self.type_dict.clone();
|
||||||
let mut dict = dict.write().unwrap();
|
let mut dict = dict.write().unwrap();
|
||||||
|
|
||||||
|
@ -260,7 +248,7 @@ impl Context {
|
||||||
drop(dict);
|
drop(dict);
|
||||||
|
|
||||||
self.add_morphism(morphism_pattern, Arc::new(move |node, dst_type| {
|
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 {
|
let mk_node = ctx.read().unwrap().get_morphism(MorphismType {
|
||||||
src_type: None,
|
src_type: None,
|
||||||
dst_type: type_term.clone()
|
dst_type: type_term.clone()
|
||||||
|
@ -296,6 +284,7 @@ impl Context {
|
||||||
/* create new context per node ?? too heavy.. whats the reason? TODO */
|
/* 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_ctx = Arc::new(RwLock::new(Context::with_parent(Some(ctx.clone()))));
|
||||||
|
let _new_depth = depth;
|
||||||
|
|
||||||
mk_node(
|
mk_node(
|
||||||
NestedNode::new(new_ctx, ReprTree::new_arc(type_term.clone()), depth),
|
NestedNode::new(new_ctx, ReprTree::new_arc(type_term.clone()), depth),
|
||||||
|
@ -331,10 +320,10 @@ impl Context {
|
||||||
/// adds an object without any representations
|
/// adds an object without any representations
|
||||||
pub fn add_obj(ctx: Arc<RwLock<Context>>, name: String, typename: &str) {
|
pub fn add_obj(ctx: Arc<RwLock<Context>>, name: String, typename: &str) {
|
||||||
let type_tag = ctx.read().unwrap()
|
let type_tag = ctx.read().unwrap()
|
||||||
.type_dict.write().unwrap()
|
.type_dict.read().unwrap()
|
||||||
.parse(typename).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);
|
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 context;
|
||||||
|
|
||||||
|
pub mod dict;
|
||||||
|
pub mod term;
|
||||||
|
//pub mod ladder;
|
||||||
pub mod repr_tree;
|
pub mod repr_tree;
|
||||||
|
|
||||||
pub use {
|
pub use {
|
||||||
context::{Context, MorphismMode, MorphismType, MorphismTypePattern},
|
dict::*,
|
||||||
repr_tree::ReprTree
|
// ladder::*,
|
||||||
|
repr_tree::*,
|
||||||
|
term::*,
|
||||||
|
context::{Context, MorphismMode, MorphismType, MorphismTypePattern}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use {
|
use {
|
||||||
r3vi::view::{AnyOuterViewPort, OuterViewPort, View},
|
r3vi::view::{AnyOuterViewPort, OuterViewPort, View},
|
||||||
laddertypes::{TypeTerm},
|
|
||||||
crate::{
|
crate::{
|
||||||
type_system::{Context}
|
type_system::{TypeTerm, Context}
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
@ -51,7 +50,7 @@ impl ReprTree {
|
||||||
pub fn from_char(ctx: &Arc<RwLock<Context>>, c: char) -> Arc<RwLock<Self>> {
|
pub fn from_char(ctx: &Arc<RwLock<Context>>, c: char) -> Arc<RwLock<Self>> {
|
||||||
let buf = r3vi::buffer::singleton::SingletonBuffer::<char>::new(c);
|
let buf = r3vi::buffer::singleton::SingletonBuffer::<char>::new(c);
|
||||||
ReprTree::new_leaf(
|
ReprTree::new_leaf(
|
||||||
Context::parse(ctx, "Char"),
|
(ctx, "( Char )"),
|
||||||
buf.get_port().into()
|
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 {
|
pub fn bg_style_from_depth(depth: usize) -> TerminalStyle {
|
||||||
match depth {
|
match depth {
|
||||||
0 => TerminalStyle::bg_color((150,80,230)),
|
0 => TerminalStyle::bg_color((150,80,230)),
|
||||||
1 => TerminalStyle::bg_color((66,66,66)),
|
1 => TerminalStyle::bg_color((75,75,75)),
|
||||||
2 => TerminalStyle::bg_color((44,44,44)),
|
2 => TerminalStyle::bg_color((40,40,40)),
|
||||||
3 => TerminalStyle::bg_color((33,33,33)),
|
3 => TerminalStyle::bg_color((30,30,30)),
|
||||||
4 => TerminalStyle::bg_color((28,28,28)),
|
4 => TerminalStyle::bg_color((25,25,25)),
|
||||||
5 => TerminalStyle::bg_color((21,21,21)),
|
5 => TerminalStyle::bg_color((20,20,20)),
|
||||||
_ => TerminalStyle::default(),
|
_ => TerminalStyle::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fg_style_from_depth(depth: usize) -> TerminalStyle {
|
pub fn fg_style_from_depth(depth: usize) -> TerminalStyle {
|
||||||
if depth == 0 {
|
match depth % 6 {
|
||||||
TerminalStyle::fg_color((200, 200, 200))
|
0 => TerminalStyle::fg_color((120, 120, 0)),
|
||||||
} else {
|
1 => TerminalStyle::fg_color((250, 165, 40)),
|
||||||
match depth % 5 {
|
2 => TerminalStyle::fg_color((80, 180, 180)),
|
||||||
0 => TerminalStyle::fg_color((128, 106, 97)),
|
3 => TerminalStyle::fg_color((180, 240, 85)),
|
||||||
1 => TerminalStyle::fg_color((100, 120, 232)),
|
4 => TerminalStyle::fg_color((200, 190, 70)),
|
||||||
2 => TerminalStyle::fg_color((180, 100, 96)),
|
|
||||||
3 => TerminalStyle::fg_color((188, 155, 18)),
|
|
||||||
4 => TerminalStyle::fg_color((135, 182, 134)),
|
|
||||||
_ => TerminalStyle::default()
|
_ => TerminalStyle::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue