Compare commits

...

10 commits

29 changed files with 495 additions and 907 deletions

View file

@ -5,11 +5,12 @@ name = "nested"
version = "0.1.0"
[dependencies]
#r3vi = { git = "https://git.exobiont.de/senvas/r3vi.git" }
r3vi = { path = "../../r3vi" }
#r3vi = { git = "https://git.exobiont.de/senvas/lib-r3vi.git" }
r3vi = { path = "../../lib-r3vi" }
laddertypes = { path = "../../lib-laddertypes" }
no_deadlocks = "*"
cgmath = { version = "0.18.0", features = ["serde"] }
termion = "1.5.5"
termion = "2.0.1"
vte = "0.10.1"
ansi_colours = "1.0"
signal-hook = "0.3.1"

View file

@ -6,8 +6,9 @@ use {
},
buffer::singleton::*
},
laddertypes::{TypeTerm},
crate::{
type_system::{Context, ReprTree, TypeTerm},
type_system::{Context, ReprTree},
terminal::{TerminalAtom},
tree::{NestedNode, TreeNavResult},
commander::{ObjCommander}
@ -19,8 +20,8 @@ use {
pub fn init_ctx( ctx: &mut Context ) {
ctx.add_node_ctor(
"Char",
Arc::new(|ctx: Arc<RwLock<Context>>, _ty: TypeTerm, _depth: usize| {
Some(CharEditor::new_node(ctx))
Arc::new(|ctx: Arc<RwLock<Context>>, _ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| {
Some(CharEditor::new_node(ctx, depth))
}));
}
@ -34,7 +35,7 @@ impl ObjCommander for CharEditor {
let cmd_obj = cmd_obj.read().unwrap();
let cmd_type = cmd_obj.get_type().clone();
if cmd_type == (&self.ctx, "( Char )").into() {
if cmd_type == Context::parse(&self.ctx, "Char") {
if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() {
let value = cmd_view.get();
@ -69,7 +70,7 @@ impl CharEditor {
self.get_port().get_view().unwrap().get()
}
pub fn new_node(ctx0: Arc<RwLock<Context>>) -> NestedNode {
pub fn new_node(ctx0: Arc<RwLock<Context>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode {
let data = SingletonBuffer::new('\0');
let ctx = ctx0.clone();
let editor = Arc::new(RwLock::new(CharEditor{ ctx, data: data.clone() }));
@ -77,14 +78,14 @@ impl CharEditor {
NestedNode::new(
ctx0.clone(),
ReprTree::new_leaf(
ctx0.read().unwrap().type_term_from_str("( Char )").unwrap(),
ctx0.read().unwrap().type_term_from_str("Char").unwrap(),
data.get_port().into()
),
0 // fixme
depth
)
.set_view(data
.get_port()
.map(move |c| TerminalAtom::from(c))
.map(move |c| TerminalAtom::from(if c == '\0' { ' ' } else { c }))
.to_grid()
)
.set_cmd( editor.clone() )

View file

@ -1,6 +1,11 @@
use {
r3vi::{
view::{OuterViewPort, singleton::*}
},
laddertypes::{TypeTerm},
crate::{
type_system::{Context, TypeTerm},
type_system::{Context},
editors::{
list::*,
integer::*
@ -19,7 +24,7 @@ pub fn init_ctx(ctx: &mut Context) {
ctx.add_node_ctor(
"Digit", Arc::new(
|ctx: Arc<RwLock<Context>>, ty: TypeTerm, depth: usize| {
|ctx: Arc<RwLock<Context>>, ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| {
match ty {
TypeTerm::App(args) => {
if args.len() > 1 {
@ -50,9 +55,6 @@ pub fn init_ctx(ctx: &mut Context) {
ctx.add_morphism(pattern,
Arc::new(
|mut node, dst_type| {
let _depth = node.depth.get();
let _editor = node.editor.get().unwrap().downcast::<RwLock<ListEditor>>().unwrap();
// todo: check src_type parameter to be ( Digit radix )
match dst_type {
@ -87,7 +89,7 @@ pub fn init_ctx(ctx: &mut Context) {
ctx.add_node_ctor(
"PosInt", Arc::new(
|ctx0: Arc<RwLock<Context>>, dst_typ: TypeTerm, depth: usize| {
|ctx0: Arc<RwLock<Context>>, dst_typ: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| {
match dst_typ.clone() {
TypeTerm::App(args) => {
if args.len() > 1 {
@ -105,7 +107,7 @@ pub fn init_ctx(ctx: &mut Context) {
.clone()
.into()
]),
depth+1
depth.map(|d| d+1)
).unwrap();
node = node.morph(dst_typ);

View file

@ -10,8 +10,9 @@ use {
index_hashmap::*
}
},
laddertypes::{TypeTerm},
crate::{
type_system::{Context, TypeTerm, ReprTree},
type_system::{Context, ReprTree},
editors::list::{ListCmd, PTYListController, PTYListStyle},
terminal::{
TerminalAtom, TerminalStyle, make_label
@ -40,7 +41,7 @@ impl ObjCommander for DigitEditor {
let cmd_obj = cmd_obj.read().unwrap();
let cmd_type = cmd_obj.get_type().clone();
if cmd_type == (&self.ctx, "( Char )").into() {
if cmd_type == Context::parse(&self.ctx, "Char") {
if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() {
let c = cmd_view.get();
@ -84,7 +85,7 @@ impl DigitEditor {
}
}
pub fn into_node(self, depth: usize) -> NestedNode {
pub fn into_node(self, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode {
let data = self.get_data();
let editor = Arc::new(RwLock::new(self));
let ed = editor.write().unwrap();
@ -99,7 +100,7 @@ impl DigitEditor {
TerminalAtom::new(
c.unwrap_or('?'),
if c.unwrap_or('?').to_digit(r).is_some() {
TerminalStyle::fg_color((100, 140, 100))
TerminalStyle::fg_color((90, 160, 90))
} else {
//TerminalStyle::bg_color((90, 10, 10))
TerminalStyle::fg_color((200, 40, 40))
@ -125,7 +126,7 @@ impl DigitEditor {
pub fn get_data(&self) -> Arc<RwLock<ReprTree>> {
ReprTree::ascend(
&ReprTree::new_leaf(
self.ctx.read().unwrap().type_term_from_str("( Seq u32 )").unwrap(),
self.ctx.read().unwrap().type_term_from_str("<Seq u32>").unwrap(),
self.get_data_port().into()
),
self.get_type()
@ -145,8 +146,8 @@ impl PosIntEditor {
pub fn new(ctx: Arc<RwLock<Context>>, radix: u32) -> Self {
let mut node = Context::make_node(
&ctx,
(&ctx, format!("( List ( Digit {} ) )", radix).as_str()).into(),
0
Context::parse(&ctx, format!("<List <Digit {}>>", radix).as_str()),
r3vi::buffer::singleton::SingletonBuffer::new(0).get_port()
).unwrap();
// Set Type

View file

@ -26,7 +26,7 @@ impl ListCmd {
pub fn into_repr_tree(self, ctx: &Arc<RwLock<Context>>) -> Arc<RwLock<ReprTree>> {
let buf = r3vi::buffer::singleton::SingletonBuffer::new(self);
ReprTree::new_leaf(
(ctx, "( ListCmd )"),
Context::parse(ctx, "ListCmd"),
buf.get_port().into()
)
}
@ -58,6 +58,8 @@ impl ObjCommander for ListEditor {
}
else if let Some(cmd) = cmd_repr.get_view::<dyn SingletonView<Item = ListCmd>>() {
eprintln!("pty-list-editor some list cmmd");
let cur = self.cursor.get();
drop(cmd_repr);
@ -71,55 +73,53 @@ impl ObjCommander for ListEditor {
match cur.mode {
ListCursorMode::Select => {
if let Some(mut item) = self.get_item().clone() {
if self.is_listlist() {
let item_cur = item.get_cursor();
match cmd.get() {
ListCmd::DeletePxev => {
if idx > 0
&& item_cur.tree_addr.iter().fold(
true,
|is_zero, x| is_zero && (*x == 0)
)
{
self.listlist_join_pxev(idx);
TreeNavResult::Continue
} else {
item.send_cmd_obj(cmd_obj)
}
}
ListCmd::DeleteNexd => {
let item_cur = item.get_cursor_warp();
let next_idx = idx as usize + 1;
if next_idx < self.data.len()
&& item_cur.tree_addr.iter().fold(
true,
|is_end, x| is_end && (*x == -1)
)
{
self.listlist_join_nexd(idx as usize);
TreeNavResult::Continue
} else {
item.send_cmd_obj(cmd_obj)
}
}
ListCmd::Split => {
self.listlist_split();
TreeNavResult::Continue
}
_ => {
item.send_cmd_obj(cmd_obj);
let item_cur = item.get_cursor();
match cmd.get() {
ListCmd::DeletePxev => {
eprintln!("SELECT: delete pxev");
if idx > 0
&& item_cur.tree_addr.iter().fold(
true,
|is_zero, x| is_zero && (*x == 0)
)
{
self.listlist_join_pxev(idx);
TreeNavResult::Continue
} else {
item.send_cmd_obj(cmd_obj)
}
}
} else {
TreeNavResult::Exit
ListCmd::DeleteNexd => {
let item_cur = item.get_cursor_warp();
let next_idx = idx as usize + 1;
if next_idx < self.data.len()
&& item_cur.tree_addr.iter().fold(
true,
|is_end, x| is_end && (*x == -1)
)
{
self.listlist_join_nexd(idx as usize);
TreeNavResult::Continue
} else {
item.send_cmd_obj(cmd_obj)
}
}
ListCmd::Split => {
self.listlist_split();
TreeNavResult::Continue
}
_ => {
item.send_cmd_obj(cmd_obj);
TreeNavResult::Continue
}
}
} else {
eprintln!("ptylist: no item");
TreeNavResult::Exit
}
},
@ -127,6 +127,7 @@ impl ObjCommander for ListEditor {
ListCursorMode::Insert => {
match cmd.get() {
ListCmd::DeletePxev => {
eprintln!("INSERT: delete pxev");
self.delete_pxev();
TreeNavResult::Continue
}
@ -149,18 +150,19 @@ impl ObjCommander for ListEditor {
}
}
} else {
eprintln!("ptylist: cursor has no idx");
TreeNavResult::Exit
}
}
}
} else {
if let Some(cur_item) = self.get_item_mut() {
drop(cmd_repr);
cur_item.write().unwrap().send_cmd_obj(cmd_obj)
} else {
cur_item.write().unwrap().send_cmd_obj(cmd_obj);
TreeNavResult::Continue
} else {
TreeNavResult::Exit
}
}
}

View file

@ -1,6 +1,8 @@
use {
r3vi::{view::{OuterViewPort, singleton::*}},
laddertypes::{TypeTerm},
crate::{
type_system::{Context, TypeTerm},
type_system::{Context},
editors::list::{ListEditor, PTYListController, PTYListStyle}
},
std::sync::{Arc, RwLock}
@ -9,12 +11,12 @@ use {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub fn init_ctx(ctx: &mut Context) {
ctx.add_list_typename("ListCmd".into());
ctx.add_typename("ListCmd".into());
ctx.add_list_typename("List".into());
ctx.add_node_ctor(
"List", Arc::new(
|ctx: Arc<RwLock<Context>>, ty: TypeTerm, depth: usize| {
|ctx: Arc<RwLock<Context>>, ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| {
match ty {
TypeTerm::App(args) => {
if args.len() > 1 {

View file

@ -1,10 +1,11 @@
use {
r3vi::{
view::{OuterViewPort, singleton::*, sequence::*},
view::{ViewPort, OuterViewPort, singleton::*, sequence::*},
buffer::{singleton::*, vec::*}
},
laddertypes::{TypeTerm},
crate::{
type_system::{Context, TypeTerm, ReprTree},
type_system::{Context, ReprTree},
editors::list::{ListCursor, ListCursorMode, ListCmd},
tree::{NestedNode, TreeNav, TreeCursor},
diagnostics::Diagnostics,
@ -22,10 +23,12 @@ pub struct ListEditor {
pub data: VecBuffer< Arc<RwLock<NestedNode>> >,
pub spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>,
pub(super) addr_port: OuterViewPort<dyn SequenceView<Item = isize>>,
pub(super) mode_port: OuterViewPort<dyn SingletonView<Item = ListCursorMode>>,
depth: OuterViewPort<dyn SingletonView<Item = usize>>,
pub(crate) ctx: Arc<RwLock<Context>>,
/// item type
@ -95,13 +98,16 @@ impl ListEditor {
data,
spillbuf: Arc::new(RwLock::new(Vec::new())),
ctx,
typ
typ,
depth: SingletonBuffer::new(0).get_port()
}
}
pub fn into_node(self, depth: usize) -> NestedNode {
pub fn into_node(mut self, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode {
let data = self.get_data();
let ctx = self.ctx.clone();
self.depth = depth.clone();
let editor = Arc::new(RwLock::new(self));
let e = editor.read().unwrap();
@ -189,6 +195,7 @@ impl ListEditor {
}
}
/// is the element-type also a list-like editor (i.e. impls TreeNav)
pub fn is_listlist(&self) -> bool {
self.ctx.read().unwrap().is_list_type(&self.typ)
}
@ -227,6 +234,12 @@ impl ListEditor {
/// insert a new element
pub fn insert(&mut self, item: Arc<RwLock<NestedNode>>) {
eprintln!("list insert");
item.read().unwrap().depth.0.set_view(
self.depth.map(|d| d+1).get_view()
);
let mut cur = self.cursor.get();
if let Some(idx) = cur.idx {
match cur.mode {
@ -235,7 +248,9 @@ impl ListEditor {
if self.is_listlist() {
cur.mode = ListCursorMode::Select;
} else {
cur.idx = Some(idx + 1);
eprintln!("list insert: is not a listlist ({:?})", self.typ);
item.write().unwrap().goto(TreeCursor::none());
cur.idx = Some(idx + 1);
}
}
@ -254,7 +269,8 @@ impl ListEditor {
}
/// 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();
if let Some(idx) = cur.idx {
let idx = idx as usize;
@ -264,10 +280,32 @@ impl ListEditor {
);
self.data.remove(idx);
}
/* in case the split leaves an empty item-list
* as a last element, remove it
*/
/*
if self.is_listlist() {
if idx > 0 && idx < self.data.len()+1 {
/* we are in insert mode,
* get element before cursor
*/
let prev_idx = idx - 1;
let prev_node = self.data.get(prev_idx);
let prev_node = prev_node.read().unwrap();
if prev_node.get_data_view::<dyn SequenceView<Item = NestedNode>>(vec![].into_iter()).iter().count() == 0 {
drop(prev_node);
self.data.remove(prev_idx);
}
}
}
*/
}
}
pub fn listlist_split(&mut self) {
eprintln!("listlist split");
let cur = self.get_cursor();
if let Some(mut item) = self.get_item().clone() {
@ -280,14 +318,15 @@ impl ListEditor {
self.nexd();
let mut b = item.spillbuf.write().unwrap();
let mut tail_node = Context::make_node(&self.ctx, self.typ.clone(), item.depth.get()).unwrap();
let mut tail_node = Context::make_node(&self.ctx, self.typ.clone(), self.depth.map(|d| d+1)).unwrap();
tail_node.goto(TreeCursor::home());
for node in b.iter() {
eprintln!("splid :send to tail node");
tail_node
.send_cmd_obj(
ReprTree::new_leaf(
(&self.ctx, "( NestedNode )"),
Context::parse(&self.ctx, "NestedNode"),
SingletonBuffer::<NestedNode>::new(
node.read().unwrap().clone()
).get_port().into()
@ -299,7 +338,7 @@ impl ListEditor {
drop(item);
tail_node.goto(TreeCursor::home());
if cur.tree_addr.len() > 2 {
if cur.tree_addr.len() > 1 {
tail_node.dn();
}
@ -341,7 +380,7 @@ impl ListEditor {
for x in data.iter() {
pxv_editor.send_cmd_obj(
ReprTree::new_leaf(
(&self.ctx, "( NestedNode )"),
Context::parse(&self.ctx, "NestedNode"),
SingletonBuffer::<NestedNode>::new(
x.read().unwrap().clone()
).get_port().into()
@ -349,13 +388,15 @@ impl ListEditor {
);
}
// fixme: is it oc0 or old_cur ??
if oc0.tree_addr.len() > 1 {
pxv_editor.goto(TreeCursor {
tree_addr: vec![ old_cur.tree_addr[0], 0 ],
leaf_mode: ListCursorMode::Insert
});
pxv_editor.send_cmd_obj(ListCmd::DeletePxev.into_repr_tree( &self.ctx ));
} else {
} else if oc0.tree_addr.len() > 0 {
pxv_editor.goto(TreeCursor {
tree_addr: vec![ old_cur.tree_addr[0] ],
leaf_mode: ListCursorMode::Insert
@ -398,7 +439,7 @@ impl ListEditor {
for x in data.iter() {
cur_editor.send_cmd_obj(
ReprTree::new_leaf(
(&self.ctx, "( NestedNode )"),
Context::parse(&self.ctx, "NestedNode"),
SingletonBuffer::<NestedNode>::new(
x.read().unwrap().clone()
).get_port().into()
@ -406,17 +447,20 @@ impl ListEditor {
);
}
// fixme: is it oc0 or old_cur ??
if oc0.tree_addr.len() > 1 {
cur_editor.goto(TreeCursor {
tree_addr: vec![ old_cur.tree_addr[0], -1 ],
leaf_mode: ListCursorMode::Insert
});
cur_editor.send_cmd_obj(ListCmd::DeleteNexd.into_repr_tree( &self.ctx ));
} else {
} else if oc0.tree_addr.len() > 0 {
cur_editor.goto(TreeCursor {
tree_addr: vec![ old_cur.tree_addr[0] ],
leaf_mode: ListCursorMode::Insert
});
} else {
cur_editor.goto(TreeCursor::none());
}
}

View file

@ -195,6 +195,7 @@ impl TreeNav for ListEditor {
TreeNavResult::Exit
} else if direction.y > 0 {
// dn
eprintln!("dn: data.len() = {}", self.data.len());
self.cursor.set(ListCursor {
mode: if self.data.len() > 0 { cur.leaf_mode } else { ListCursorMode::Insert },
idx: Some(0)
@ -210,6 +211,7 @@ impl TreeNav for ListEditor {
1 => {
if direction.y > 0 {
// dn
if cur.tree_addr[0] < self.data.len() as isize {
if self.data
.get_mut(cur.tree_addr[0] as usize)
@ -219,7 +221,8 @@ impl TreeNav for ListEditor {
self.cursor.set(ListCursor {
mode: ListCursorMode::Select,
idx: Some(cur.tree_addr[0])
})
});
self.set_leaf_mode(cur.leaf_mode);
}
}

View file

@ -1,6 +1,6 @@
use {
r3vi::{
view::{OuterViewPort, sequence::*},
view::{ViewPort, OuterViewPort, sequence::*},
projection::decorate_sequence::*,
},
crate::{
@ -18,23 +18,20 @@ use {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct PTYListStyle {
style: (String, String, String),
depth: usize
style: (String, String, String)
}
impl PTYListStyle {
pub fn new(style: (&str, &str, &str), depth: usize) -> PTYListStyle {
pub fn new(style: (&str, &str, &str)) -> PTYListStyle {
PTYListStyle {
style: (style.0.into(), style.1.into(), style.2.into()),
depth
style: (style.0.into(), style.1.into(), style.2.into())
}
}
pub fn get_seg_seq_view(&self, editor: &ListEditor) -> OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>> {
let seg_seq = ListSegmentSequence::new(
editor.get_cursor_port(),
editor.get_data_port(),
self.depth
editor.get_data_port()
);
let se = seg_seq.read().unwrap();
se.get_view().map(move |segment| segment.pty_view())
@ -43,8 +40,7 @@ impl PTYListStyle {
pub fn pty_view(&self, editor: &ListEditor) -> OuterViewPort<dyn TerminalView> {
let seg_seq = ListSegmentSequence::new(
editor.get_cursor_port(),
editor.get_data_port(),
self.depth
editor.get_data_port()
);
let seg_seq = seg_seq.read().unwrap();
@ -59,7 +55,7 @@ impl PTYListStyle {
pub fn for_node(node: &mut NestedNode, style: (&str, &str, &str)) {
node.view = Some(
Self::new(style, node.depth.get())
Self::new(style)
.pty_view(
&node.get_edit::<ListEditor>().unwrap().read().unwrap()
)
@ -69,13 +65,15 @@ impl PTYListStyle {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
// todo: rename to CharController
pub struct PTYListController {
pub editor: Arc<RwLock<ListEditor>>,
split_char: Option<char>,
close_char: Option<char>,
depth: usize
depth: OuterViewPort<dyn SingletonView<Item = usize>>
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -85,7 +83,7 @@ impl PTYListController {
editor: Arc<RwLock<ListEditor>>,
split_char: Option<char>,
close_char: Option<char>,
depth: usize
depth: OuterViewPort<dyn SingletonView<Item = usize>>
) -> Self {
PTYListController {
editor,
@ -113,7 +111,7 @@ impl PTYListController {
}
let editor = node.get_edit::<ListEditor>().unwrap();
let controller = Arc::new(RwLock::new(PTYListController::from_editor( editor, split_char, close_char, node.depth.get() )));
let controller = Arc::new(RwLock::new(PTYListController::from_editor( editor, split_char, close_char, node.depth.clone() )));
node.cmd.set(Some(controller.clone()));
node.close_char.set(close_char);
@ -131,10 +129,6 @@ impl PTYListController {
self.editor.read().unwrap().get_item()
}
pub fn set_depth(&mut self, depth: usize) {
self.depth = depth;
}
pub fn handle_term_event(&mut self, event: &TerminalEvent, _cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
let mut e = self.editor.write().unwrap();
match event {
@ -155,6 +149,7 @@ impl PTYListController {
// || Some(c) == child_close_char
{
e.listlist_split();
eprintln!("done listlist split");
TreeNavResult::Continue
} else if Some(c) == child_close_char {
e.goto(TreeCursor::none());
@ -176,12 +171,12 @@ impl PTYListController {
match cur.mode {
ListCursorMode::Insert => {
let mut new_edit = Context::make_node(&e.ctx, e.typ.clone(), self.depth+1).unwrap();
let mut new_edit = Context::make_node(&e.ctx, e.typ.clone(), self.depth.map(|d| d+1)).unwrap();
new_edit.goto(TreeCursor::home());
match new_edit.send_cmd_obj(cmd_obj.clone()) {
TreeNavResult::Continue => {
e.insert(Arc::new(RwLock::new(new_edit)));
e.insert(Arc::new(RwLock::new(new_edit.clone())));
TreeNavResult::Continue
}
TreeNavResult::Exit => {
@ -194,12 +189,12 @@ impl PTYListController {
let res = item.write().unwrap().send_cmd_obj(cmd_obj.clone());
let child_close_char = item.read().unwrap().close_char.get();
match res {
match res {
TreeNavResult::Continue => TreeNavResult::Continue,
TreeNavResult::Exit => {
// child editor returned control, probably for meta-char handling..
if cmd_obj.read().unwrap().get_type().clone() == ctx.type_term_from_str("( Char )").unwrap() {
if cmd_obj.read().unwrap().get_type().clone() == ctx.type_term_from_str("Char").unwrap() {
let co = cmd_obj.read().unwrap();
if let Some(cmd_view) = co.get_view::<dyn SingletonView<Item = char>>() {
drop(co);
@ -230,13 +225,13 @@ impl ObjCommander for PTYListController {
let mut e = self.editor.write().unwrap();
let cmd_type = cmd_obj.read().unwrap().get_type().clone();
if cmd_type == (&e.ctx, "( ListCmd )").into()
|| cmd_type == (&e.ctx, "( NestedNode )").into()
if cmd_type == Context::parse(&e.ctx, "ListCmd").into()
|| cmd_type == Context::parse(&e.ctx, "NestedNode").into()
{
e.send_cmd_obj( cmd_obj )
}
else if cmd_type == (&e.ctx, "( TerminalEvent )").into() {
else if cmd_type == Context::parse(&e.ctx, "TerminalEvent").into() {
let co = cmd_obj.read().unwrap();
if let Some(view) = co.get_view::<dyn SingletonView<Item = TerminalEvent>>() {
drop( co );

View file

@ -22,7 +22,6 @@ pub enum ListSegment {
InsertCursor,
Item {
editor: NestedNode,
depth: usize,
cur_dist: isize,
}
}
@ -37,9 +36,8 @@ impl PtySegment for ListSegment {
.add_style_front(TerminalStyle::bold(true))
})
}
ListSegment::Item{ editor, depth, cur_dist } => {
ListSegment::Item{ editor, cur_dist } => {
let e = editor.clone();
let d = *depth;
let cur_dist = *cur_dist;
editor.get_view().map_item(move |_pt, atom| {
let c = e.get_cursor();
@ -50,10 +48,11 @@ impl PtySegment for ListSegment {
} else {
usize::MAX
};
atom
.add_style_back(bg_style_from_depth(select))
.add_style_back(TerminalStyle::bold(select==1))
.add_style_back(fg_style_from_depth(d))
.add_style_back(fg_style_from_depth(e.depth.get_view().get()))
})
}
}
@ -64,7 +63,6 @@ pub struct ListSegmentSequence {
data: Arc<dyn SequenceView<Item = NestedNode>>,
cursor: Arc<dyn SingletonView<Item = ListCursor>>,
depth: usize,
cur_cursor: ListCursor,
port: ViewPort<dyn SequenceView<Item = ListSegment>>,
@ -95,7 +93,6 @@ impl SequenceView for ListSegmentSequence {
ListCursorMode::Select => {
ListSegment::Item {
editor: self.data.get(idx)?,
depth: self.depth,
cur_dist: cur - *idx as isize
}
}
@ -103,7 +100,6 @@ impl SequenceView for ListSegmentSequence {
if *idx < cur as usize {
ListSegment::Item {
editor: self.data.get(idx)?,
depth: self.depth,
cur_dist: cur - *idx as isize
}
} else if *idx == cur as usize {
@ -111,7 +107,6 @@ impl SequenceView for ListSegmentSequence {
} else {
ListSegment::Item {
editor: self.data.get(&(*idx - 1))?,
depth: self.depth,
cur_dist: cur - *idx as isize
}
}
@ -120,7 +115,6 @@ impl SequenceView for ListSegmentSequence {
} else {
ListSegment::Item {
editor: self.data.get(&idx)?,
depth: self.depth,
cur_dist: *idx as isize + 1
}
})
@ -131,14 +125,12 @@ impl ListSegmentSequence {
pub fn new(
cursor_port: OuterViewPort<dyn SingletonView<Item = ListCursor>>,
data_port: OuterViewPort<dyn SequenceView<Item = NestedNode>>,
depth: usize
) -> Arc<RwLock<Self>> {
let out_port = ViewPort::new();
let mut proj_helper = ProjectionHelper::new(out_port.update_hooks.clone());
let proj = Arc::new(RwLock::new(ListSegmentSequence {
cur_cursor: cursor_port.get_view().get(),
port: out_port.clone(),
depth,
cursor: proj_helper.new_singleton_arg(0, cursor_port, |s: &mut Self, _msg| {
let _old_cursor = s.cur_cursor;

View file

@ -9,8 +9,9 @@ use {
index_hashmap::*
}
},
laddertypes::{TypeTerm},
crate::{
type_system::{Context, TypeTerm},
type_system::{Context},
terminal::{
TerminalEditor, TerminalEditorResult,
TerminalEvent, TerminalView
@ -202,7 +203,7 @@ impl ObjCommander for ProductEditor {
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
let co = cmd_obj.read().unwrap();
let cmd_type = co.get_type().clone();
let term_event_type = (&self.ctx, "( TerminalEvent )").into();
let term_event_type = Context::parse(&self.ctx, "TerminalEvent").into();
if cmd_type == term_event_type {
if let Some(te_view) = co.get_view::<dyn SingletonView<Item = TerminalEvent>>() {
@ -238,7 +239,7 @@ impl ObjCommander for ProductEditor {
}
}
} else {
let mut e = Context::make_node(&self.ctx, t.clone(), *ed_depth+1).unwrap();
let mut e = Context::make_node(&self.ctx, t.clone(), r3vi::buffer::singleton::SingletonBuffer::new(*ed_depth).get_port()).unwrap();
*editor = Some(e.clone());
update_segment = true;

View file

@ -71,7 +71,7 @@ impl TreeNav for ProductEditor {
e.goto(c.clone());
} else if c.tree_addr.len() > 0 {
// create editor
let mut e = Context::make_node(&self.ctx, t.clone(), *ed_depth+1).unwrap();
let mut e = Context::make_node(&self.ctx, t.clone(), r3vi::buffer::singleton::SingletonBuffer::new(*ed_depth+1).get_port()).unwrap();
*editor = Some(e.clone());
e.goto(c.clone());
}
@ -128,7 +128,7 @@ impl TreeNav for ProductEditor {
} else {
// create editor
let mut e = Context::make_node(&self.ctx, t.clone(), *ed_depth+1).unwrap();
let mut e = Context::make_node(&self.ctx, t.clone(), r3vi::buffer::singleton::SingletonBuffer::new(*ed_depth+1).get_port()).unwrap();
*editor = Some(e.clone());
e.goby(direction);
}

View file

@ -4,8 +4,9 @@ use {
OuterViewPort
}
},
laddertypes::{TypeTerm},
crate::{
type_system::{Context, TypeTerm},
type_system::{Context},
terminal::{
TerminalStyle, TerminalView,
make_label

View file

@ -6,10 +6,11 @@ use {
sequence::*,
}
},
laddertypes::{TypeTerm},
crate::{
terminal::TerminalView,
editors::list::ListCursorMode,
type_system::{Context, TypeTerm, ReprTree},
type_system::{Context, ReprTree},
tree::{TreeNav, TreeCursor, TreeNavResult},
diagnostics::{Diagnostics, Message},
tree::NestedNode,
@ -60,7 +61,7 @@ impl SumEditor {
NestedNode::new(
ctx.clone(),
ReprTree::new_arc(TypeTerm::TypeID(ctx.read().unwrap().get_typeid("Sum").unwrap())),
0
r3vi::buffer::singleton::SingletonBuffer::new(0).get_port()
)
.set_view(view)
.set_editor(editor.clone())

View file

@ -3,8 +3,8 @@ use {
view::{singleton::*}
},
crate::{
type_system::{ReprTree},
editors::{list::{ListEditor, ListCmd}},
type_system::{Context, ReprTree},
editors::{list::{ListEditor, ListCmd, ListCursorMode}},
tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor},
commander::ObjCommander
},
@ -20,7 +20,7 @@ impl ObjCommander for TypeTermEditor {
let cmd_obj = co.clone();
let cmd_obj = cmd_obj.read().unwrap();
if cmd_obj.get_type().clone() == (&self.ctx, "( Char )").into() {
if cmd_obj.get_type().clone() == Context::parse(&self.ctx, "Char") {
if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() {
let c = cmd_view.get();
@ -44,7 +44,7 @@ impl ObjCommander for TypeTermEditor {
TreeNavResult::Exit
}
_ => {
self.set_state( State::AnySymbol );
self.set_state( State::FunSymbol );
self.cur_node.get_mut().goto(TreeCursor::home());
self.send_child_cmd( co )
}
@ -52,71 +52,138 @@ impl ObjCommander for TypeTermEditor {
}
State::Char => {
match c {
'\'' => {
self.cur_node.get_mut().goto(TreeCursor::none());
match self.send_child_cmd( co ) {
TreeNavResult::Exit => {
match c {
'\'' => {
self.cur_node.get_mut().goto(TreeCursor::none());
}
_ => {}
}
TreeNavResult::Exit
}
_ => {
self.send_child_cmd( co )
}
},
TreeNavResult::Continue => TreeNavResult::Continue
}
}
State::Ladder => {
let res = self.send_child_cmd( co.clone() );
match res {
TreeNavResult::Continue => {
match self.get_cursor().tree_addr.len() {
// entire term is selected
0 => {
match c {
'<' => {
self.morph_to_list(State::App);
TreeNavResult::Continue
}
_ => { TreeNavResult::Exit }
}
}
// entire item selected or insert mode
1 => {
match c {
'~' => {
self.normalize_nested_ladder();
// ignore '~' since we are already in a ladder
// and cant split current item
TreeNavResult::Continue
}
_ => {
self.send_child_cmd( co.clone() )
}
_ => {}
}
TreeNavResult::Continue
}
TreeNavResult::Exit => {
// some subterm
_ => {
match c {
'~' => TreeNavResult::Continue,
_ => TreeNavResult::Exit
'~' => {
let i0 = self.cur_node.get().get_edit::<ListEditor>().unwrap();
let cur_it = i0.clone().read().unwrap().get_item().clone();
if let Some(i) = cur_it {
let cur_tte = i.get_edit::<TypeTermEditor>().unwrap();
if cur_tte.read().unwrap().state == State::App || cur_tte.read().unwrap().get_cursor().tree_addr.len() > 1 {
self.send_child_cmd( co.clone() )
} else {
drop(cur_tte);
drop(i);
self.send_child_cmd(
ListCmd::Split.into_repr_tree( &self.ctx )
)
}
} else {
self.send_child_cmd( co.clone() )
}
}
_ => {
self.send_child_cmd( co.clone() )
}
}
}
}
}
State::App => {
let res = self.send_child_cmd( co.clone() );
match res {
TreeNavResult::Exit => {
match self.get_cursor().tree_addr.len() {
// entire Term is selected
0 => {
match c {
'~' => {
self.previous_item_into_ladder();
self.morph_to_list(State::Ladder);
self.goto(TreeCursor {
tree_addr: vec![ -1 ],
leaf_mode: ListCursorMode::Insert
});
TreeNavResult::Continue
},
_ => {TreeNavResult::Exit}
}
'<' => {
self.morph_to_list(State::App);
TreeNavResult::Continue
}
_ => {
TreeNavResult::Exit
}
}
},
TreeNavResult::Continue => {
match c {
'>'|
' ' => {
let i = self.cur_node.get().get_edit::<ListEditor>().unwrap();
let i = i.read().unwrap();
if let Some(i) = i.get_item() {
let tte = i.get_edit::<TypeTermEditor>().unwrap();
let mut tte = tte.write().unwrap();
if tte.state == State::Ladder {
tte.normalize_singleton();
}
},
// some item is selected
_ => {
match self.send_child_cmd( co.clone() ) {
TreeNavResult::Exit => {
match c {
'~' => {
self.previous_item_into_ladder();
TreeNavResult::Continue
},
_ => {TreeNavResult::Exit}
}
},
_ => {}
TreeNavResult::Continue => {
match c {
'>'|
' ' => {
let i = self.cur_node.get().get_edit::<ListEditor>().unwrap();
let i = i.read().unwrap();
if let Some(i) = i.get_item() {
let tte = i.get_edit::<TypeTermEditor>().unwrap();
let mut tte = tte.write().unwrap();
if tte.state == State::Ladder {
tte.normalize_singleton();
}
}
},
_ => {}
}
TreeNavResult::Continue
}
}
TreeNavResult::Continue
}
}
}
@ -128,11 +195,19 @@ impl ObjCommander for TypeTermEditor {
match res {
TreeNavResult::Exit => {
match c {
'<' => {
self.goto(TreeCursor::none());
self.morph_to_list(State::App);
TreeNavResult::Continue
}
'~' => {
self.morph_to_ladder();
self.morph_to_list(State::Ladder);
self.set_addr(0);
self.dn();
self.send_cmd_obj(
ListCmd::Split.into_repr_tree( &self.ctx )
)
);
TreeNavResult::Continue
}
_ => {
TreeNavResult::Exit
@ -156,11 +231,11 @@ impl ObjCommander for TypeTermEditor {
match &self.state {
State::Any => {
let cmd_repr = co.read().unwrap();
if cmd_repr.get_type().clone() == (&self.ctx, "( NestedNode )").into() {
if cmd_repr.get_type().clone() == Context::parse(&self.ctx, "NestedNode") {
if let Some(view) = cmd_repr.get_view::<dyn SingletonView<Item = NestedNode>>() {
let node = view.get();
if node.data.read().unwrap().get_type().clone() == (&self.ctx, "( Char )").into() {
if node.data.read().unwrap().get_type().clone() == Context::parse(&self.ctx, "Char") {
self.set_state( State::AnySymbol );
} else {
self.set_state( State::Ladder );
@ -184,7 +259,6 @@ impl ObjCommander for TypeTermEditor {
let res = self.send_child_cmd( co.clone() );
self.normalize_empty();
if let Some(cmd) = co.read().unwrap().get_view::<dyn SingletonView<Item = ListCmd>>() {
match cmd.get() {
ListCmd::Split => {

View file

@ -1,8 +1,16 @@
use {
r3vi::{
view::{OuterViewPort, singleton::*}
},
laddertypes::{TypeTerm},
crate::{
type_system::{Context, TypeTerm, MorphismTypePattern},
type_system::{Context, MorphismTypePattern},
terminal::{TerminalStyle, TerminalProjections},
editors::{list::{PTYListStyle, PTYListController}, typeterm::{State, TypeTermEditor}}
editors::{
list::{PTYListStyle, PTYListController, ListEditor, ListSegmentSequence},
typeterm::{State, TypeTermEditor}
},
PtySegment
},
std::{sync::{Arc, RwLock}},
cgmath::{Point2}
@ -25,7 +33,7 @@ pub fn init_ctx(ctx: &mut Context) {
let ctx : Arc<RwLock<Context>> = Arc::new(RwLock::new(Context::with_parent(Some(node.ctx.clone()))));
ctx.write().unwrap().meta_chars.push('~');
let new_node = TypeTermEditor::with_node( ctx, node.depth.get(), node.clone(), State::Any );
let new_node = TypeTermEditor::with_node( ctx, node.clone(), State::Any );
Some(new_node)
}));
@ -34,14 +42,29 @@ pub fn init_ctx(ctx: &mut Context) {
Arc::new(|mut node, _dst_type: _| {
PTYListController::for_node( &mut node, Some('~'), None );
let vertical_view = false;
let vertical_view = true;
if vertical_view {
let editor = node.get_edit::<crate::editors::list::ListEditor>().unwrap();
let mut e = editor.write().unwrap();
let seg_view = PTYListStyle::new( ("","~",""), node.depth.get() ).get_seg_seq_view( &mut e );
let seg_view = PTYListStyle::new( ("","~","") ).get_seg_seq_view( &mut e );
node = node.set_view(
seg_view.to_grid_vertical().flatten()
seg_view.to_grid_vertical()
.map_item(
|pt,x|
if pt.y > 0 {
r3vi::buffer::vec::VecBuffer::with_data(vec![
crate::terminal::make_label("~"),
x.clone()
])
.get_port()
.to_sequence()
.to_grid_horizontal()
.flatten()
} else {
x.clone()
}
).flatten()
);
} else {
PTYListStyle::for_node( &mut node, ("","~","") );
@ -71,6 +94,7 @@ pub fn init_ctx(ctx: &mut Context) {
Arc::new(|mut node, _dst_type:_| {
PTYListController::for_node( &mut node, Some(' '), None );
PTYListStyle::for_node( &mut node, ("","","") );
Some(node)
}));
@ -80,11 +104,6 @@ pub fn init_ctx(ctx: &mut Context) {
PTYListController::for_node( &mut node, Some(' '), None );
PTYListStyle::for_node( &mut node, ("","","") );
// display variables blue color
if let Some(v) = node.view {
node.view = Some(
v.map_item(|_i,p| p.add_style_front(TerminalStyle::fg_color((5, 120, 240)))));
}
Some(node)
}));
@ -97,6 +116,7 @@ pub fn init_ctx(ctx: &mut Context) {
ctx.add_morphism(
MorphismTypePattern { src_tyid: ctx.get_typeid("Char"), dst_tyid: ctx.get_typeid("Type::Lit::Char").unwrap() },
Arc::new(|mut node, _dst_type:_| {
node.ctx.write().unwrap().meta_chars = vec![ '\'' ];
let mut grid = r3vi::buffer::index_hashmap::IndexBuffer::new();
grid.insert_iter(
@ -117,7 +137,7 @@ pub fn init_ctx(ctx: &mut Context) {
}));
ctx.add_node_ctor("Type", Arc::new(
|ctx: Arc<RwLock<Context>>, _ty: TypeTerm, depth: usize| {
|ctx: Arc<RwLock<Context>>, _ty: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>| {
Some(TypeTermEditor::new_node(ctx, depth))
}));
}

View file

@ -6,10 +6,12 @@ pub use ctx::init_ctx;
use {
r3vi::{
view::{OuterViewPort, singleton::*},
buffer::{singleton::*}
},
laddertypes::{TypeID, TypeTerm},
crate::{
type_system::{Context, TypeID, TypeTerm, ReprTree},
type_system::{Context, ReprTree},
editors::{list::{ListCursorMode, ListEditor, ListCmd}},
tree::{NestedNode, TreeNav, TreeNavResult, TreeCursor},
commander::ObjCommander
@ -36,8 +38,9 @@ pub struct TypeTermEditor {
data: Arc<RwLock<ReprTree>>,
close_char: SingletonBuffer<Option<char>>,
spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>,
depth: OuterViewPort<dyn SingletonView<Item = usize>>,
depth: usize,
buf: SingletonBuffer< TypeTerm >,
// editing/parsing state
state: State,
@ -47,8 +50,8 @@ pub struct TypeTermEditor {
}
impl TypeTermEditor {
pub fn from_type_term(ctx: Arc<RwLock<Context>>, depth: usize, term: &TypeTerm) -> NestedNode {
let mut node = TypeTermEditor::new_node(ctx.clone(), depth);
pub fn from_type_term(ctx: Arc<RwLock<Context>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>, term: &TypeTerm) -> NestedNode {
let mut node = TypeTermEditor::new_node(ctx.clone(), depth.clone());
node.goto(TreeCursor::home());
match term {
@ -74,11 +77,11 @@ impl TypeTermEditor {
let parent_ctx = editor.read().unwrap().cur_node.get().ctx.clone();
for x in args.iter() {
let arg_node = TypeTermEditor::from_type_term( parent_ctx.clone(), depth+1, x );
let arg_node = TypeTermEditor::from_type_term( parent_ctx.clone(), depth.map(|d| d+1), x );
node.send_cmd_obj(
ReprTree::new_leaf(
(&ctx, "( NestedNode )"),
Context::parse(&ctx, "NestedNode"),
SingletonBuffer::new(arg_node).get_port().into()
)
);
@ -92,11 +95,11 @@ impl TypeTermEditor {
let parent_ctx = editor.read().unwrap().cur_node.get().ctx.clone();
for x in args.iter() {
let arg_node = TypeTermEditor::from_type_term( parent_ctx.clone(), depth+1, x );
let arg_node = TypeTermEditor::from_type_term( parent_ctx.clone(), depth.map(|d| d+1), x );
node.send_cmd_obj(
ReprTree::new_leaf(
(&ctx, "( NestedNode )"),
Context::parse(&ctx, "NestedNode"),
SingletonBuffer::new(arg_node).get_port().into()
)
);
@ -122,7 +125,7 @@ impl TypeTermEditor {
editor.send_cmd_obj(ReprTree::from_char(&ctx, *c));
}
}
node.goto(TreeCursor::none());
node
}
@ -130,38 +133,37 @@ impl TypeTermEditor {
fn set_state(&mut self, new_state: State) {
let mut node = match new_state {
State::Any => {
Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth ).unwrap()
.morph( (&self.ctx, "( Type::Sym )").into() )
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Char>"), self.depth.map(|x| x) ).unwrap()
.morph( Context::parse(&self.ctx, "Type::Sym") )
}
State::App => {
Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth ).unwrap()
.morph( (&self.ctx, "( Type::App )").into() )
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Type>"), self.depth.map(|x| x) ).unwrap()
.morph( Context::parse(&self.ctx, "Type::App") )
}
State::Ladder => {
Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth ).unwrap()
.morph( (&self.ctx, "( Type::Ladder )").into() )
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Type>"), self.depth.map(|x| x) ).unwrap()
.morph( Context::parse(&self.ctx, "Type::Ladder") )
}
State::AnySymbol => {
Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth ).unwrap()
.morph( (&self.ctx, "( Type::Sym )").into() )
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Char>"), self.depth.map(|x| x) ).unwrap()
.morph( Context::parse(&self.ctx, "Type::Sym") )
},
State::FunSymbol => {
Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth ).unwrap()
.morph( (&self.ctx, "( Type::Sym::Fun )").into() )
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Char>"), self.depth.map(|x| x) ).unwrap()
.morph( Context::parse(&self.ctx, "Type::Sym::Fun") )
},
State::VarSymbol => {
Context::make_node( &self.ctx, (&self.ctx, "( List Char )").into(), self.depth ).unwrap()
.morph( (&self.ctx, "( Type::Sym::Var )").into() )
Context::make_node( &self.ctx, Context::parse(&self.ctx, "<List Char>"), self.depth.map(|x| x) ).unwrap()
.morph( Context::parse(&self.ctx, "Type::Sym::Var") )
}
State::Num => {
crate::editors::integer::PosIntEditor::new(self.ctx.clone(), 10)
.into_node()
.morph( (&self.ctx, "( Type::Lit::Num )").into() )
.morph( Context::parse(&self.ctx, "Type::Lit::Num") )
}
State::Char => {
Context::make_node( &self.ctx, (&self.ctx, "( Char )").into(), self.depth ).unwrap()
.morph( (&self.ctx, "( Type::Lit::Char )").into() )
Context::make_node( &self.ctx, Context::parse(&self.ctx, "Char"), self.depth.map(|x| x) ).unwrap()
.morph( Context::parse(&self.ctx, "Type::Lit::Char") )
}
};
@ -173,36 +175,37 @@ impl TypeTermEditor {
self.state = new_state;
}
pub fn new_node(ctx: Arc<RwLock<Context>>, depth: usize) -> NestedNode {
pub fn new_node(ctx: Arc<RwLock<Context>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode {
let ctx : Arc<RwLock<Context>> = Arc::new(RwLock::new(Context::with_parent(Some(ctx))));
ctx.write().unwrap().meta_chars.push('~');
ctx.write().unwrap().meta_chars.push('<');
let mut symb_node = Context::make_node( &ctx, (&ctx, "( List Char )").into(), depth ).unwrap();
symb_node = symb_node.morph( (&ctx, "( Type::Sym )").into() );
let mut symb_node = Context::make_node( &ctx, Context::parse(&ctx, "<List Char>"), depth ).unwrap();
symb_node = symb_node.morph( Context::parse(&ctx, "Type::Sym") );
Self::with_node(
ctx.clone(),
depth,
symb_node,
State::Any
)
}
fn with_node(ctx: Arc<RwLock<Context>>, depth: usize, node: NestedNode, state: State) -> NestedNode {
let _buffer = SingletonBuffer::<Option<TypeTerm>>::new( None );
fn with_node(ctx: Arc<RwLock<Context>>, cur_node: NestedNode, state: State) -> NestedNode {
let buf = SingletonBuffer::<TypeTerm>::new( TypeTerm::unit() );
let data = Arc::new(RwLock::new(ReprTree::new(
(&ctx, "( Type )")
Context::parse(&ctx, "Type")
)));
let editor = TypeTermEditor {
ctx: ctx.clone(),
data: data.clone(),
state,
cur_node: SingletonBuffer::new(node),
buf,
cur_node: SingletonBuffer::new(cur_node.clone()),
close_char: SingletonBuffer::new(None),
spillbuf: Arc::new(RwLock::new(Vec::new())),
depth
depth: cur_node.depth.clone()
};
let view = editor.cur_node
@ -215,16 +218,16 @@ impl TypeTermEditor {
let _cc = editor.cur_node.get().close_char;
let editor = Arc::new(RwLock::new(editor));
let mut node = NestedNode::new(ctx, data, depth)
let mut super_node = NestedNode::new(ctx, data, cur_node.depth)
.set_view(view)
.set_nav(editor.clone())
.set_cmd(editor.clone())
.set_editor(editor.clone());
editor.write().unwrap().close_char = node.close_char.clone();
node.spillbuf = editor.read().unwrap().spillbuf.clone();
node
editor.write().unwrap().close_char = super_node.close_char.clone();
super_node.spillbuf = editor.read().unwrap().spillbuf.clone();
super_node
}
fn forward_spill(&mut self) {
@ -288,71 +291,34 @@ impl TypeTermEditor {
let subladder_list_edit = subladder_list_edit.read().unwrap();
if subladder_list_edit.data.len() == 0 {
self.set_state( State::Any );
}
}
/* unwrap a ladder if it only contains one element
*/
pub fn normalize_singleton(&mut self) {
eprintln!("normalize singleton");
let subladder_list_node = self.cur_node.get().clone();
let subladder_list_edit = subladder_list_node.get_edit::<ListEditor>().unwrap();
let subladder_list_edit = subladder_list_edit.read().unwrap();
if subladder_list_edit.data.len() == 1 {
let it_node = subladder_list_edit.data.get(0);
let it_node = it_node.read().unwrap();
if it_node.get_type() == (&self.ctx, "( Type )").into() {
let other_tt = it_node.get_edit::<TypeTermEditor>().unwrap();
if self.state == State::Ladder {
let subladder_list_node = self.cur_node.get().clone();
let subladder_list_edit = subladder_list_node.get_edit::<ListEditor>().unwrap();
let mut other_tt = other_tt.write().unwrap();
let subladder_list_edit = subladder_list_edit.read().unwrap();
if subladder_list_edit.data.len() == 1 {
let it_node = subladder_list_edit.data.get(0);
let it_node = it_node.read().unwrap();
if it_node.get_type() == Context::parse(&self.ctx, "Type") {
let other_tt = it_node.get_edit::<TypeTermEditor>().unwrap();
other_tt.normalize_singleton();
let mut other_tt = other_tt.write().unwrap();
self.close_char.set(other_tt.close_char.get());
self.cur_node.set(other_tt.cur_node.get());
self.state = other_tt.state;
}
} else {
}
}
other_tt.normalize_singleton();
other_tt.depth.0.set_view( self.depth.map(|x| x).get_view() );
/* 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();
self.close_char.set(other_tt.close_char.get());
self.cur_node.set(other_tt.cur_node.get());
self.state = other_tt.state;
}
}
}
@ -371,96 +337,58 @@ impl TypeTermEditor {
app_edit.delete_nexd();
}
// select previous element
app_edit.goto(TreeCursor{
tree_addr: vec![ cur.tree_addr[0]-1 ],
leaf_mode: ListCursorMode::Select
});
if let Some(item_node) = app_edit.get_item() {
// get selected element
if let Some(item_node) = app_edit.get_item() {
let item_typterm = item_node.get_edit::<TypeTermEditor>().expect("typetermedit");
let mut item_typterm = item_typterm.write().unwrap();
match item_typterm.state {
// if item at cursor is Ladder
State::Ladder => {
drop(item_typterm);
app_edit.dn();
app_edit.qnexd();
}
_ => {
item_typterm.goto(TreeCursor::none());
drop(item_typterm);
// else create new ladder
let mut list_node = Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth ).unwrap();
list_node = list_node.morph( (&self.ctx, "( Type::Ladder )").into() );
let mut new_node = TypeTermEditor::with_node(
self.ctx.clone(),
self.depth,
list_node,
State::Ladder
);
// insert old node and split
new_node.goto(TreeCursor::home());
new_node.send_cmd_obj(
ReprTree::new_leaf(
(&self.ctx, "( NestedNode )"),
SingletonBuffer::<NestedNode>::new( item_node ).get_port().into()
)
);
*app_edit.get_item_mut().unwrap().write().unwrap() = new_node;
app_edit.dn();
}
if item_typterm.state != State::Ladder {
item_typterm.morph_to_list( State::Ladder );
}
item_typterm.goto(TreeCursor {
tree_addr: vec![ -1 ],
leaf_mode: ListCursorMode::Insert
});
}
}
}
/* replace with new ladder node with self as first element
/* replace with new list-node (ladder/app) with self as first element
*/
pub fn morph_to_ladder(&mut self) {
pub(super) fn morph_to_list(&mut self, state: State) {
eprintln!("morph into ladder");
let old_node = self.cur_node.get().clone();
*old_node.depth.get_mut() += 1;
let mut old_node = self.cur_node.get().clone();
/* reconfigure current node to display new_node list-editor
*/
self.set_state( state );
/* create a new NestedNode with TerminaltypeEditor,
* that has same state & child-node as current node.
*/
let old_edit_node = TypeTermEditor::new_node( self.ctx.clone(), self.depth );
let old_edit_node = TypeTermEditor::new_node( self.ctx.clone(), SingletonBuffer::new(0).get_port() );
old_node.depth.0.set_view( old_edit_node.depth.map(|x|x).get_view() );
let old_edit_clone = old_edit_node.get_edit::<TypeTermEditor>().unwrap();
old_edit_clone.write().unwrap().set_state( self.state );
old_edit_clone.write().unwrap().close_char.set( old_node.close_char.get() );
old_edit_clone.write().unwrap().cur_node.set( old_node );
/* create new list-edit node for the ladder
*/
let mut new_node = Context::make_node( &self.ctx, (&self.ctx, "( List Type )").into(), self.depth ).unwrap();
new_node = new_node.morph( (&self.ctx, "( Type::Ladder )").into() );
/* reconfigure current node to display new_node list-editor
*/
self.close_char.set(new_node.close_char.get());
self.cur_node.set(new_node);
self.state = State::Ladder;
/* insert old node and split
*/
self.goto(TreeCursor::home());
self.send_cmd_obj(
self.send_child_cmd(
ReprTree::new_leaf(
(&self.ctx, "( NestedNode )"),
Context::parse(&self.ctx, "NestedNode"),
SingletonBuffer::new( old_edit_node ).get_port().into()
)
);
self.set_addr(0);
self.dn();
}
}

View file

@ -42,4 +42,3 @@ impl TreeNav for TypeTermEditor {
self.cur_node.get_mut().goto(new_cur)
}
}

View file

@ -24,6 +24,17 @@ impl TreeCursor {
tree_addr: vec![],
}
}
pub fn get_subcursor(&self, depth: usize) -> TreeCursor {
TreeCursor {
leaf_mode: self.leaf_mode,
tree_addr: if depth < self.tree_addr.len() {
self.tree_addr[ depth.. ].iter().cloned().collect()
} else {
vec![]
}
}
}
}
impl Default for TreeCursor {

View file

@ -21,10 +21,10 @@ use {
cgmath::Vector2,
};
#[derive(Clone, Copy, Eq, PartialEq)]
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub enum TreeNavResult { Continue, Exit }
#[derive(Clone, Copy, Eq, PartialEq)]
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub enum TreeHeightOp { P, Q, Max }
pub trait TreeNav {
@ -181,3 +181,4 @@ pub trait TreeNav {
}
}

View file

@ -5,8 +5,9 @@ use {
view::{View, ViewPort, OuterViewPort, AnyOuterViewPort, singleton::*, sequence::*},
buffer::{singleton::*}
},
laddertypes::{TypeTerm},
crate::{
type_system::{ReprTree, Context, TypeTerm},
type_system::{ReprTree, Context},
terminal::{TerminalView, TerminalEvent, TerminalEditor, TerminalEditorResult, TerminalAtom},
diagnostics::{Diagnostics, Message},
tree::{TreeNav, TreeCursor, TreeNavResult, TreeHeightOp},
@ -32,18 +33,15 @@ struct NestedNodeEdit {
/// abstract editor
pub editor: SingletonBuffer<
Option< Arc<dyn Any + Send + Sync> >
>,
>,
pub input_buf:: VecBuffer< NestedNode >,
pub output_buf: VecBuffer< NestedNode >,
pub spillbuf: VecBuffer< NestedNode >,
/// commander & navigation
pub cmd: SingletonBuffer<
Option< Arc<RwLock<dyn ObjCommander + Send + Sync>> >
>,
pub close_char: SingletonBuffer<
Option< char >
>,
pub close_char: SingletonBuffer< Option< char > >,
// could be replaced by cmd when TreeNav -CmdObjects are used
pub tree_nav: SingletonBuffer<
@ -82,16 +80,13 @@ pub struct NestedNode {
pub diag: Option< OuterViewPort<dyn SequenceView<Item = Message>> >,
/// depth
pub depth: SingletonBuffer< usize >,
pub depth: OuterViewPort< dyn SingletonView<Item = usize> >,
/// abstract editor
pub editor: SingletonBuffer<
Option< Arc<dyn Any + Send + Sync> >
>,
/* TODO:
* - spill buffer (contains overflowing elements as well as 'split-off' parts)
*/
pub spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>,
/// commander & navigation
@ -107,13 +102,13 @@ pub struct NestedNode {
}
impl NestedNode {
pub fn new(ctx: Arc<RwLock<Context>>, data: Arc<RwLock<ReprTree>>, depth: usize) -> Self {
pub fn new(ctx: Arc<RwLock<Context>>, data: Arc<RwLock<ReprTree>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> Self {
NestedNode {
ctx,
data,
view: None,
diag: None,
depth: SingletonBuffer::new(depth),
depth,
editor: SingletonBuffer::new(None),
spillbuf: Arc::new(RwLock::new(Vec::new())),
cmd: SingletonBuffer::new(None),
@ -130,10 +125,10 @@ impl NestedNode {
NestedNode::new(
ctx.clone(),
ReprTree::new_leaf(
(&ctx, "( Char )"),
Context::parse(&ctx, "Char"),
buf.get_port().into()
),
0
SingletonBuffer::new(0).get_port()
)
.set_view(buf.get_port()
.map(|c| TerminalAtom::from(c))
@ -200,7 +195,7 @@ impl NestedNode {
pub fn get_data_port<'a, V: View + ?Sized + 'static>(&'a self, type_str: impl Iterator<Item = &'a str>) -> Option<OuterViewPort<V>>
where V::Msg: Clone {
let ctx = self.ctx.clone();
let type_ladder = type_str.map(|s| ((&ctx, s)).into());
let type_ladder = type_str.map(|s| Context::parse(&ctx, s));
let repr_tree = ReprTree::descend_ladder(&self.data, type_ladder)?;
repr_tree.clone().read().unwrap()
@ -262,7 +257,7 @@ impl TerminalEditor for NestedNode {
if let Some(cmd) = self.cmd.get() {
cmd.write().unwrap().send_cmd_obj(
ReprTree::new_leaf(
self.ctx.read().unwrap().type_term_from_str("( TerminalEvent )").unwrap(),
self.ctx.read().unwrap().type_term_from_str("TerminalEvent").unwrap(),
AnyOuterViewPort::from(buf.get_port())
));
}

View file

@ -1,14 +1,14 @@
use {
laddertypes::{TypeTerm, TypeID},
crate::{
type_system::{TypeTerm, TypeID},
tree::{TreeAddr}
}
};
pub trait TreeType {
fn get_type(&self, _addr: &TreeAddr) -> TypeTerm {
TypeTerm::new(TypeID::Var(0))
fn get_type(&self, addr: &TreeAddr) -> Vec<TypeTerm> {
vec![]
}
}

View file

@ -1,6 +1,8 @@
use {
r3vi::{view::{OuterViewPort, singleton::*}, buffer::{singleton::*}},
laddertypes::{TypeDict, TypeTerm, TypeID},
crate::{
type_system::{TypeDict, TypeTerm, TypeID, ReprTree},
type_system::{ReprTree},
tree::NestedNode
},
std::{
@ -134,12 +136,6 @@ impl Default for Context {
}
}
impl Into<TypeTerm> for (&Arc<RwLock<Context>>, &str) {
fn into(self) -> TypeTerm {
self.0.read().unwrap().type_term_from_str(self.1).expect("could not parse type term")
}
}
impl Context {
pub fn with_parent(parent: Option<Arc<RwLock<Context>>>) -> Self {
Context {
@ -173,6 +169,10 @@ impl Context {
}
}
pub fn parse(ctx: &Arc<RwLock<Self>>, s: &str) -> TypeTerm {
ctx.read().unwrap().type_term_from_str(s).expect("could not parse type term")
}
pub fn add_typename(&mut self, tn: &str) -> TypeID {
self.type_dict.write().unwrap().add_typename(tn.to_string())
}
@ -195,6 +195,18 @@ impl Context {
TypeTerm::TypeID(id) => {
self.list_types.contains(id)
}
TypeTerm::Ladder(args) |
TypeTerm::App(args) => {
if args.len() > 0 {
if self.is_list_type(&args[0]) {
true
} else {
false
}
} else {
false
}
}
_ => false
}
}
@ -221,15 +233,15 @@ impl Context {
}
}
pub fn type_term_from_str(&self, tn: &str) -> Option<TypeTerm> {
self.type_dict.read().unwrap().type_term_from_str(&tn)
pub fn type_term_from_str(&self, tn: &str) -> Result<TypeTerm, laddertypes::parser::ParseError> {
self.type_dict.write().unwrap().parse(&tn)
}
pub fn type_term_to_str(&self, t: &TypeTerm) -> String {
self.type_dict.read().unwrap().type_term_to_str(&t)
self.type_dict.read().unwrap().unparse(&t)
}
pub fn add_node_ctor(&mut self, tn: &str, mk_editor: Arc<dyn Fn(Arc<RwLock<Self>>, TypeTerm, usize) -> Option<NestedNode> + Send + Sync>) {
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>) {
let dict = self.type_dict.clone();
let mut dict = dict.write().unwrap();
@ -248,7 +260,7 @@ impl Context {
drop(dict);
self.add_morphism(morphism_pattern, Arc::new(move |node, dst_type| {
mk_editor(node.ctx.clone(), dst_type, node.depth.get())
mk_editor(node.ctx.clone(), dst_type, node.depth)
}));
}
@ -275,7 +287,7 @@ impl Context {
}
}
pub fn make_node(ctx: &Arc<RwLock<Self>>, type_term: TypeTerm, depth: usize) -> Option<NestedNode> {
pub fn make_node(ctx: &Arc<RwLock<Self>>, type_term: TypeTerm, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> Option<NestedNode> {
let mk_node = ctx.read().unwrap().get_morphism(MorphismType {
src_type: None,
dst_type: type_term.clone()
@ -284,7 +296,6 @@ impl Context {
/* create new context per node ?? too heavy.. whats the reason? TODO */
let new_ctx = Arc::new(RwLock::new(Context::with_parent(Some(ctx.clone()))));
let _new_depth = depth;
mk_node(
NestedNode::new(new_ctx, ReprTree::new_arc(type_term.clone()), depth),
@ -320,10 +331,10 @@ impl Context {
/// adds an object without any representations
pub fn add_obj(ctx: Arc<RwLock<Context>>, name: String, typename: &str) {
let type_tag = ctx.read().unwrap()
.type_dict.read().unwrap()
.type_term_from_str(typename).unwrap();
.type_dict.write().unwrap()
.parse(typename).unwrap();
if let Some(node) = Context::make_node(&ctx, type_tag, 0) {
if let Some(node) = Context::make_node(&ctx, type_tag, SingletonBuffer::new(0).get_port()) {
ctx.write().unwrap().nodes.insert(name, node);
}
}

View file

@ -1,73 +0,0 @@
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..get(tn).cloned()
}
pub fn type_term_from_str(&self, typename: &str) -> Option<TypeTerm> {
TypeTerm::from_str(typename, &self.typenames.)
}
pub fn type_term_to_str(&self, term: &TypeTerm) -> String {
term.to_str(&self.typenames.my)
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>

View file

@ -1,71 +0,0 @@
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
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>

View file

@ -1,15 +1,8 @@
pub mod context;
pub mod dict;
pub mod term;
//pub mod ladder;
pub mod repr_tree;
pub use {
dict::*,
// ladder::*,
repr_tree::*,
term::*,
context::{Context, MorphismMode, MorphismType, MorphismTypePattern}
context::{Context, MorphismMode, MorphismType, MorphismTypePattern},
repr_tree::ReprTree
};

View file

@ -1,7 +1,8 @@
use {
r3vi::view::{AnyOuterViewPort, OuterViewPort, View},
laddertypes::{TypeTerm},
crate::{
type_system::{TypeTerm, Context}
type_system::{Context}
},
std::{
collections::HashMap,
@ -50,7 +51,7 @@ impl ReprTree {
pub fn from_char(ctx: &Arc<RwLock<Context>>, c: char) -> Arc<RwLock<Self>> {
let buf = r3vi::buffer::singleton::SingletonBuffer::<char>::new(c);
ReprTree::new_leaf(
(ctx, "( Char )"),
Context::parse(ctx, "Char"),
buf.get_port().into()
)
}

View file

@ -1,351 +0,0 @@
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]),
}
}
}

View file

@ -5,23 +5,27 @@ use {
pub fn bg_style_from_depth(depth: usize) -> TerminalStyle {
match depth {
0 => TerminalStyle::bg_color((150,80,230)),
1 => TerminalStyle::bg_color((75,75,75)),
2 => TerminalStyle::bg_color((40,40,40)),
3 => TerminalStyle::bg_color((30,30,30)),
4 => TerminalStyle::bg_color((25,25,25)),
5 => TerminalStyle::bg_color((20,20,20)),
1 => TerminalStyle::bg_color((66,66,66)),
2 => TerminalStyle::bg_color((44,44,44)),
3 => TerminalStyle::bg_color((33,33,33)),
4 => TerminalStyle::bg_color((28,28,28)),
5 => TerminalStyle::bg_color((21,21,21)),
_ => TerminalStyle::default(),
}
}
pub fn fg_style_from_depth(depth: usize) -> TerminalStyle {
match depth % 6 {
0 => TerminalStyle::fg_color((120, 120, 0)),
1 => TerminalStyle::fg_color((250, 165, 40)),
2 => TerminalStyle::fg_color((80, 180, 180)),
3 => TerminalStyle::fg_color((180, 240, 85)),
4 => TerminalStyle::fg_color((200, 190, 70)),
_ => TerminalStyle::default()
}
if depth == 0 {
TerminalStyle::fg_color((200, 200, 200))
} else {
match depth % 5 {
0 => TerminalStyle::fg_color((128, 106, 97)),
1 => TerminalStyle::fg_color((100, 120, 232)),
2 => TerminalStyle::fg_color((180, 100, 96)),
3 => TerminalStyle::fg_color((188, 155, 18)),
4 => TerminalStyle::fg_color((135, 182, 134)),
_ => TerminalStyle::default()
}
}
}