type terms, first parsing & serialization
This commit is contained in:
parent
0feaee454c
commit
a1b95c5892
6 changed files with 386 additions and 39 deletions
|
@ -8,7 +8,9 @@ use {
|
||||||
Observer,
|
Observer,
|
||||||
ObserverBroadcast,
|
ObserverBroadcast,
|
||||||
InnerViewPort,
|
InnerViewPort,
|
||||||
OuterViewPort
|
OuterViewPort,
|
||||||
|
TypeTerm,
|
||||||
|
TypeDict
|
||||||
},
|
},
|
||||||
sequence::{SequenceView, VecBuffer},
|
sequence::{SequenceView, VecBuffer},
|
||||||
integer::{RadixProjection}
|
integer::{RadixProjection}
|
||||||
|
@ -17,6 +19,23 @@ use {
|
||||||
|
|
||||||
#[async_std::main]
|
#[async_std::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
let mut td = TypeDict::new();
|
||||||
|
for tn in vec![
|
||||||
|
"MachineWord", "MachineInt", "MachineSlab",
|
||||||
|
"Vec", "NullTerminatedString",
|
||||||
|
"Sequence", "Ascii",
|
||||||
|
"PositionalInt", "Digit", "LittleEndian", "BigEndian",
|
||||||
|
"DiffStream", "ℕ"
|
||||||
|
] { td.add_typename(tn.into()); }
|
||||||
|
|
||||||
|
let radix_types = vec![
|
||||||
|
td.type_term_from_str("( ℕ )").unwrap(),
|
||||||
|
td.type_term_from_str("( PositionalInt 10 LittleEndian )").unwrap(),
|
||||||
|
td.type_term_from_str("( Sequence ( Digit 10 ) )").unwrap(),
|
||||||
|
td.type_term_from_str("( Sequence Ascii )").unwrap(),
|
||||||
|
td.type_term_from_str("( Sequence MachineSlab )").unwrap()
|
||||||
|
];
|
||||||
|
|
||||||
nested::magic_header();
|
nested::magic_header();
|
||||||
eprintln!(" Convert Radix of Positional Integer");
|
eprintln!(" Convert Radix of Positional Integer");
|
||||||
nested::magic_header();
|
nested::magic_header();
|
||||||
|
@ -24,50 +43,69 @@ async fn main() {
|
||||||
let mut args = std::env::args();
|
let mut args = std::env::args();
|
||||||
args.next().expect("Arg $0 missing!");
|
args.next().expect("Arg $0 missing!");
|
||||||
|
|
||||||
eprintln!("
|
eprintln!("\n$1: src_radix");
|
||||||
$1: src_radix
|
for t in radix_types.iter() {
|
||||||
( ℕ )
|
eprintln!(" {}", td.type_term_to_str(t));
|
||||||
( PositionalInt 10 LittleEndian )
|
}
|
||||||
( Sequence (Digit 10) )
|
|
||||||
( Sequence Ascii )
|
eprintln!("\n$2: dst_radix");
|
||||||
( ArgString )
|
for t in radix_types.iter() {
|
||||||
");
|
eprintln!(" {}", td.type_term_to_str(t));
|
||||||
|
}
|
||||||
|
|
||||||
let src_radix_str = args.next().expect("Arg $1 required!");
|
let src_radix_str = args.next().expect("Arg $1 required!");
|
||||||
|
|
||||||
|
|
||||||
eprintln!("
|
|
||||||
$2: dst_radix
|
|
||||||
( ℕ )
|
|
||||||
( PositionalInt 10 LittleEndian )
|
|
||||||
( Sequence (Digit 10) )
|
|
||||||
( Sequence Ascii )
|
|
||||||
( ArgString )
|
|
||||||
");
|
|
||||||
let dst_radix_str = args.next().expect("Arg $2 required!");
|
let dst_radix_str = args.next().expect("Arg $2 required!");
|
||||||
|
|
||||||
eprintln!("
|
|
||||||
>0: n
|
|
||||||
( ℕ ) ~~ <1
|
|
||||||
( PositionalInt src_radix LittleEndian )
|
|
||||||
( Sequence (Digit src_radix) )
|
|
||||||
( Sequence MachineInt )
|
|
||||||
( PipeStream bincode (SequenceDiff MachineInt) )
|
|
||||||
");
|
|
||||||
|
|
||||||
eprintln!("
|
|
||||||
<1: n
|
|
||||||
( ℕ ) ~~ >0
|
|
||||||
( PositionalInt dst_radix LittleEndian )
|
|
||||||
( Sequence (Digit dst_radix) )
|
|
||||||
( Sequence MachineInt )
|
|
||||||
( PipeStream bincode (SequenceDiff MachineInt) )
|
|
||||||
");
|
|
||||||
|
|
||||||
nested::magic_header();
|
|
||||||
|
|
||||||
let src_radix = usize::from_str_radix(&src_radix_str, 10).expect("could not parse src_radix");
|
let src_radix = usize::from_str_radix(&src_radix_str, 10).expect("could not parse src_radix");
|
||||||
let dst_radix = usize::from_str_radix(&dst_radix_str, 10).expect("could not parse dst_radix");
|
let dst_radix = usize::from_str_radix(&dst_radix_str, 10).expect("could not parse dst_radix");
|
||||||
|
|
||||||
|
let in_types = vec![
|
||||||
|
td.type_term_from_str("( ℕ )").unwrap(),
|
||||||
|
td.type_term_from_str("( PositionalInt )").unwrap()
|
||||||
|
.num_arg(src_radix as i64)
|
||||||
|
.arg(td.type_term_from_str("( LittleEndian )").unwrap())
|
||||||
|
.clone(),
|
||||||
|
|
||||||
|
td.type_term_from_str("( Sequence )").unwrap()
|
||||||
|
.arg(
|
||||||
|
td.type_term_from_str("( Digit )").unwrap()
|
||||||
|
.num_arg(src_radix as i64).clone()
|
||||||
|
)
|
||||||
|
.clone(),
|
||||||
|
|
||||||
|
td.type_term_from_str("( Sequence MachineInt )").unwrap(),
|
||||||
|
td.type_term_from_str("( DiffStream ( Vec MachineInt ) )").unwrap(),
|
||||||
|
];
|
||||||
|
|
||||||
|
let out_types = vec![
|
||||||
|
td.type_term_from_str("( ℕ )").unwrap(),
|
||||||
|
td.type_term_from_str("( PositionalInt )").unwrap()
|
||||||
|
.num_arg(dst_radix as i64)
|
||||||
|
.arg(td.type_term_from_str("( LittleEndian )").unwrap()).clone(),
|
||||||
|
|
||||||
|
td.type_term_from_str("( Sequence )").unwrap()
|
||||||
|
.arg(
|
||||||
|
td.type_term_from_str("( Digit )").unwrap()
|
||||||
|
.num_arg(dst_radix as i64).clone()
|
||||||
|
)
|
||||||
|
.clone(),
|
||||||
|
|
||||||
|
td.type_term_from_str("( Sequence MachineInt )").unwrap(),
|
||||||
|
td.type_term_from_str("( DiffStream ( Vec MachineInt ) )").unwrap(),
|
||||||
|
];
|
||||||
|
|
||||||
|
eprintln!("\n>0: n");
|
||||||
|
for t in in_types.iter() {
|
||||||
|
eprintln!(" {}", td.type_term_to_str(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
eprintln!("\n<1: n");
|
||||||
|
for t in out_types.iter() {
|
||||||
|
eprintln!(" {}", td.type_term_to_str(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
nested::magic_header();
|
||||||
|
|
||||||
let src_digits_port = ViewPort::new();
|
let src_digits_port = ViewPort::new();
|
||||||
let dst_digits_port = ViewPort::new();
|
let dst_digits_port = ViewPort::new();
|
||||||
|
|
||||||
|
|
28
nested/src/bimap.rs
Normal file
28
nested/src/bimap.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
hash::Hash
|
||||||
|
};
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
pub struct Bimap<V: Eq + Hash, Λ: Eq + Hash> {
|
||||||
|
pub mλ: HashMap::<V, Λ>,
|
||||||
|
pub my: HashMap::<Λ, V>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Eq + Hash + Clone, Λ: Eq + Hash + Clone> Bimap<V, Λ> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Bimap {
|
||||||
|
mλ: HashMap::new(),
|
||||||
|
my: HashMap::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, y: V, λ: Λ) {
|
||||||
|
self.mλ.insert(y.clone(), λ.clone());
|
||||||
|
self.my.insert(λ, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
133
nested/src/core/context.rs
Normal file
133
nested/src/core/context.rs
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
use {
|
||||||
|
std::{
|
||||||
|
collections::HashMap,
|
||||||
|
sync::{Arc, RwLock},
|
||||||
|
any::Any
|
||||||
|
},
|
||||||
|
crate::{
|
||||||
|
bimap::Bimap,
|
||||||
|
core::type_term::{TypeID, TypeTerm}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
pub enum ReprTree {
|
||||||
|
Leaf(Arc<dyn Any + Send + Sync>),
|
||||||
|
Branch(HashMap<TypeTerm, Arc<RwLock<ReprTree>>>)
|
||||||
|
}
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Object {
|
||||||
|
type_tag: TypeTerm,
|
||||||
|
repr: Arc<RwLock<ReprTree>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Object {
|
||||||
|
fn downcast(&self, repr_type: TypeTerm) -> Option<Object> {
|
||||||
|
match &*self.repr.read().unwrap() {
|
||||||
|
ReprTree::Leaf(data) =>
|
||||||
|
if self.type_tag == repr_type {
|
||||||
|
Some(self.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
ReprTree::Branch(reprs) =>
|
||||||
|
Some(Object{
|
||||||
|
type_tag: repr_type.clone(),
|
||||||
|
repr: reprs.get(&repr_type)?.clone()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn downcast_chain<'a>(
|
||||||
|
&self,
|
||||||
|
repr_chain: impl Iterator<Item = &'a TypeTerm>
|
||||||
|
) -> Option<Object> {
|
||||||
|
repr_chain.fold(
|
||||||
|
Some(self.clone()),
|
||||||
|
|s, t| s?.downcast(t.clone())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_data<T: Any + Send + Sync>(&self) -> Option<Arc<T>> {
|
||||||
|
match &*self.repr.read().unwrap() {
|
||||||
|
ReprTree::Leaf(data) => Arc::downcast::<T>(data.clone()).ok(),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
pub struct TypeDict {
|
||||||
|
typenames: Bimap::<String, u64>,
|
||||||
|
type_id_counter: u64
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeDict {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
TypeDict {
|
||||||
|
typenames: Bimap::new(),
|
||||||
|
type_id_counter: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_typename(&mut self, tn: String) {
|
||||||
|
self.typenames.insert(tn, self.type_id_counter);
|
||||||
|
self.type_id_counter += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
pub struct Context {
|
||||||
|
type_dict: TypeDict,
|
||||||
|
|
||||||
|
// map type_id -> constructor
|
||||||
|
constructors: HashMap<u64, Box<Fn() -> Arc<dyn Any + Send + Sync>>>,
|
||||||
|
|
||||||
|
objects: HashMap<String, Object>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Context {
|
||||||
|
pub fn add_obj(
|
||||||
|
&mut self,
|
||||||
|
name: String,
|
||||||
|
typename: &str
|
||||||
|
) {
|
||||||
|
self.objects.insert(
|
||||||
|
name,
|
||||||
|
Object {
|
||||||
|
type_tag: self.type_dict.type_term_from_str(typename).unwrap(),
|
||||||
|
repr: Arc::new(RwLock::new(ReprTree::Branch(HashMap::new())))
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_repr(&mut self, name: &String, typename: &str, repr: Arc<RwLock<ReprTree>>) {
|
||||||
|
match &mut *self.objects.get_mut(name).unwrap().repr.write().unwrap() {
|
||||||
|
ReprTree::Leaf(_) => {/*error*/},
|
||||||
|
ReprTree::Branch(repr_map) => {
|
||||||
|
repr_map.insert(self.type_dict.type_term_from_str(typename).unwrap(), repr.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_obj(&self, name: &String) -> Option<Object> {
|
||||||
|
self.objects.get(name).cloned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
|
@ -3,6 +3,8 @@ pub mod view;
|
||||||
pub mod observer;
|
pub mod observer;
|
||||||
pub mod channel;
|
pub mod channel;
|
||||||
pub mod port;
|
pub mod port;
|
||||||
|
pub mod type_term;
|
||||||
|
pub mod context;
|
||||||
|
|
||||||
pub use {
|
pub use {
|
||||||
view::{View},
|
view::{View},
|
||||||
|
@ -24,6 +26,16 @@ pub use {
|
||||||
ViewPort,
|
ViewPort,
|
||||||
InnerViewPort,
|
InnerViewPort,
|
||||||
OuterViewPort
|
OuterViewPort
|
||||||
|
},
|
||||||
|
type_term::{
|
||||||
|
TypeID,
|
||||||
|
TypeTerm
|
||||||
|
},
|
||||||
|
context::{
|
||||||
|
ReprTree,
|
||||||
|
TypeDict,
|
||||||
|
Context,
|
||||||
|
Object
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
133
nested/src/core/type_term.rs
Normal file
133
nested/src/core/type_term.rs
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
use std::{
|
||||||
|
sync::Arc,
|
||||||
|
any::Any,
|
||||||
|
ops::Deref,
|
||||||
|
collections::HashMap,
|
||||||
|
iter::Peekable
|
||||||
|
};
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
pub type TypeID = u64;
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub enum TypeTerm {
|
||||||
|
Type {
|
||||||
|
id: TypeID,
|
||||||
|
args: Vec<TypeTerm>
|
||||||
|
},
|
||||||
|
Num(i64)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeTerm {
|
||||||
|
pub fn new(id: TypeID) -> Self {
|
||||||
|
TypeTerm::Type{ id, args: vec![] }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn arg(&mut self, t: TypeTerm) -> &mut Self {
|
||||||
|
if let TypeTerm::Type{ id, args } = self {
|
||||||
|
args.push(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn num_arg(&mut self, v: i64) -> &mut Self {
|
||||||
|
self.arg(TypeTerm::Num(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_str(s: &str, names: &HashMap<String, u64>) -> 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 mut f = term_stack.last_mut().unwrap();
|
||||||
|
if let Some(f) = f {
|
||||||
|
f.arg(t.unwrap());
|
||||||
|
} else {
|
||||||
|
//error
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
atom => {
|
||||||
|
let mut f = term_stack.last_mut().unwrap();
|
||||||
|
|
||||||
|
match f {
|
||||||
|
Some(f) =>
|
||||||
|
if atom.chars().nth(0).unwrap().is_numeric() {
|
||||||
|
f.num_arg(i64::from_str_radix(atom, 10).unwrap());
|
||||||
|
} else {
|
||||||
|
f.arg(TypeTerm::new(*names.get(atom).expect(&format!("invalid atom {}", atom))));
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
*f = Some(TypeTerm::new(*names.get(atom).expect(&format!("invalid atom {}", atom))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
// only adds parenthesis where args.len > 0
|
||||||
|
pub fn to_str1(&self, names: &HashMap<u64, String>) -> String {
|
||||||
|
match self {
|
||||||
|
TypeTerm::Type{ id, args } =>
|
||||||
|
if args.len() > 0 {
|
||||||
|
format!(
|
||||||
|
"( {} {})",
|
||||||
|
names[id],
|
||||||
|
if args.len() > 0 {
|
||||||
|
args.iter().fold(
|
||||||
|
String::new(),
|
||||||
|
|str, term| format!("{}{} ", str, term.to_str1(names) )
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
names[id].clone()
|
||||||
|
},
|
||||||
|
|
||||||
|
TypeTerm::Num(n) =>
|
||||||
|
format!("{}", n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// always adds an enclosing pair of parenthesis
|
||||||
|
pub fn to_str(&self, names: &HashMap<u64, String>) -> String {
|
||||||
|
match self {
|
||||||
|
TypeTerm::Type{ id, args } =>
|
||||||
|
format!(
|
||||||
|
"( {} {})",
|
||||||
|
names[id],
|
||||||
|
if args.len() > 0 {
|
||||||
|
args.iter().fold(
|
||||||
|
String::new(),
|
||||||
|
|str, term| format!("{}{} ", str, term.to_str1(names) )
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
}),
|
||||||
|
|
||||||
|
TypeTerm::Num(n) =>
|
||||||
|
format!("{}", n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![feature(trait_alias)]
|
#![feature(trait_alias)]
|
||||||
|
#![feature(non_ascii_idents)]
|
||||||
|
|
||||||
pub mod core;
|
pub mod core;
|
||||||
pub mod projection;
|
pub mod projection;
|
||||||
|
@ -13,6 +14,8 @@ pub mod integer;
|
||||||
pub mod string_editor;
|
pub mod string_editor;
|
||||||
pub mod leveled_term_view;
|
pub mod leveled_term_view;
|
||||||
|
|
||||||
|
pub mod bimap;
|
||||||
|
|
||||||
pub fn magic_header() {
|
pub fn magic_header() {
|
||||||
eprintln!("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>");
|
eprintln!("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue