// -- TODO ------------------------------------------------------------------- // Open Questions // - Can we avoid using Arc::clone(&x) each time, we use some value? // - Can we have global variables or do we need to pass a pointer to a // global state all the way down? What about TLS? // - As we have no non-local exit: We would need our own kind of // Result<> with provision for THROWing. // - Would it be possible to implement CATCH/THROW with async? // --------------------------------------------------------------------------- #![allow(dead_code)] #![allow(unused_assignments)] #![allow(unused_variables)] #[macro_use] extern crate lazy_static; use std::sync::{Arc, Mutex}; type Q = Arc>; type Flonum = f64; enum Node { Cons (Cons), Flonum (Flonum), Symbol (Symbol), Unbound } struct Cons { car :Q, cdr :Q } struct Symbol { val :Q, plist :Q } // -- Numbers ---------------------------------------------------------------- fn maknum (x :Flonum) -> Q { Arc::new(Mutex::new (Node::Flonum (x))) } fn getnum (x :Q) -> Flonum { match &*x.lock().unwrap() { Node::Flonum (a) => *a, _ => panic!("Not a number"), } } // fn plus (x :Q, y :Q) -> Q; // fn difference (x :Q, y :Q) -> Q; // fn quotient (x :Q, y :Q) -> Q; // fn remainder (x :Q, y :Q) -> Q; // fn eqn (x :Q, y :Q) -> bool; // fn lessp (x :Q, y :Q) -> bool; // -- Conses ----------------------------------------------------------------- fn cons (x :Q, y :Q) -> Q { Arc::new(Mutex::new (Node::Cons (Cons { car: Arc::clone(&x), cdr: Arc::clone(&y) }))) } fn car (x :Arc>) -> Arc> { match &*x.lock().unwrap() { Node::Cons (q) => Arc::clone(&q.car), _ => panic!("Not a cons"), } } fn cdr (x :Arc>) -> Arc> { match &*x.lock().unwrap() { Node::Cons (q) => Arc::clone(&q.cdr), _ => panic!("Not a cons"), } } fn rplaca (x :Q, y :Q) -> Q { match &mut *x.lock().unwrap() { Node::Cons (q) => { q.car = y }, _ => panic!("Not a cons"), }; x } fn rplacd (x :Q, y :Q) -> Q { match &mut *x.lock().unwrap() { Node::Cons (q) => { q.cdr = y }, _ => panic!("Not a cons"), }; x } // -- Symbols ---------------------------------------------------------------- lazy_static! { static ref OBLIST :Mutex = Mutex::new (Arc::new(Mutex::new(Node::Unbound))); } fn oblist () -> Q { Arc::clone(&OBLIST.lock().unwrap()) } fn set_oblist (x :Q) { *&mut *OBLIST.lock().unwrap() = Arc::clone(&x); } // fn maknam (x : Q) -> Q; // fn intern (x : Q) -> Q; // fn oblist (x : Q) -> Q; // fn symeval (x : Q) -> Q; // fn set (x : Q, y : Q) -> Q; // -- Atoms ------------------------------------------------------------------ // fn exploden (x : Q) -> Q; // fn implode (x : Q) -> Q; // -- Predicates ------------------------------------------------------------- fn consp (x :Q) -> bool { match *x.lock().unwrap() { Node::Cons (_) => true, _ => false, } } fn atom (x :Q) -> bool { !consp(x) } fn nump (x :Q) -> bool { match *x.lock().unwrap() { Node::Flonum (_) => true, _ => false, } } fn symbolp (x :Q) -> bool { match *x.lock().unwrap() { Node::Symbol (_) => true, _ => false, } } fn eq (x :Q, y :Q) -> bool { Arc::ptr_eq(&x,&y) } // fn null (x :Q) -> bool; // --------------------------------------------------------------------------- fn main () { let f = maknum (42 as Flonum); let g = maknum (69 as Flonum); println!("RC = {} / {}", Arc::strong_count(&f), Arc::strong_count(&g)); { let a = cons (Arc::clone (&f), Arc::clone(&g)); let a2 = Arc::clone(&a); println!("RC = {} / {}", Arc::strong_count(&f), Arc::strong_count(&g)); { let b = car(Arc::clone(&a)); println!("RC = {} / {}", Arc::strong_count(&f), Arc::strong_count(&g)); println!("a = {} . {}", getnum(cdr(Arc::clone(&a))), getnum(cdr(Arc::clone(&a)))); } { let b = Arc::clone(&f); println!("RC = {} / {}", Arc::strong_count(&f), Arc::strong_count(&g)); } println!("before rplaca {} / {}", Arc::strong_count(&f), Arc::strong_count(&g)); rplaca (Arc::clone (&a), cdr(Arc::clone(&a))); println!("after rplaca {} / {}", Arc::strong_count(&f), Arc::strong_count(&g)); { let b = car(Arc::clone(&a)); println!("RC = {} / {}", Arc::strong_count(&f), Arc::strong_count(&g)); println!("a = {} . {}", getnum(cdr(Arc::clone(&a))), getnum(cdr(Arc::clone(&a)))); } println!("{}", Arc::ptr_eq(&a,&a2)); println!("{}", eq(Arc::clone(&a), Arc::clone(&a2))); } println!("RC = {} / {}", Arc::strong_count(&f), Arc::strong_count(&g)); }