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,
|
||||
ObserverBroadcast,
|
||||
InnerViewPort,
|
||||
OuterViewPort
|
||||
OuterViewPort,
|
||||
TypeTerm,
|
||||
TypeDict
|
||||
},
|
||||
sequence::{SequenceView, VecBuffer},
|
||||
integer::{RadixProjection}
|
||||
|
@ -17,6 +19,23 @@ use {
|
|||
|
||||
#[async_std::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();
|
||||
eprintln!(" Convert Radix of Positional Integer");
|
||||
nested::magic_header();
|
||||
|
@ -24,50 +43,69 @@ async fn main() {
|
|||
let mut args = std::env::args();
|
||||
args.next().expect("Arg $0 missing!");
|
||||
|
||||
eprintln!("
|
||||
$1: src_radix
|
||||
( ℕ )
|
||||
( PositionalInt 10 LittleEndian )
|
||||
( Sequence (Digit 10) )
|
||||
( Sequence Ascii )
|
||||
( ArgString )
|
||||
");
|
||||
eprintln!("\n$1: src_radix");
|
||||
for t in radix_types.iter() {
|
||||
eprintln!(" {}", td.type_term_to_str(t));
|
||||
}
|
||||
|
||||
eprintln!("\n$2: dst_radix");
|
||||
for t in radix_types.iter() {
|
||||
eprintln!(" {}", td.type_term_to_str(t));
|
||||
}
|
||||
|
||||
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!");
|
||||
|
||||
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 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 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 channel;
|
||||
pub mod port;
|
||||
pub mod type_term;
|
||||
pub mod context;
|
||||
|
||||
pub use {
|
||||
view::{View},
|
||||
|
@ -24,6 +26,16 @@ pub use {
|
|||
ViewPort,
|
||||
InnerViewPort,
|
||||
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(non_ascii_idents)]
|
||||
|
||||
pub mod core;
|
||||
pub mod projection;
|
||||
|
@ -13,6 +14,8 @@ pub mod integer;
|
|||
pub mod string_editor;
|
||||
pub mod leveled_term_view;
|
||||
|
||||
pub mod bimap;
|
||||
|
||||
pub fn magic_header() {
|
||||
eprintln!("<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue