├── .gitignore ├── Cargo.lock ├── Cargo.toml └── src ├── cons.rs ├── env.rs ├── eval.rs ├── expr.rs ├── fun.rs ├── lib.rs ├── main.rs ├── num.rs ├── symbol.rs └── user.rs /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | [root] 2 | name = "rustlisp" 3 | version = "0.1.0" 4 | 5 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rustlisp" 3 | version = "0.1.0" 4 | authors = ["Sunrin SHIMURA (keen) <3han5chou7@gmail.com>"] 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /src/cons.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | use std::marker::PhantomData; 3 | use expr::*; 4 | use fun::*; 5 | use symbol::*; 6 | 7 | pub struct Nil{} 8 | impl Expr for Nil { 9 | fn to_string() -> String { 10 | "nil".to_string() 11 | } 12 | } 13 | pub struct ConsCell { 14 | p1: PhantomData, 15 | p2: PhantomData, 16 | } 17 | 18 | impl Expr for ConsCell{ 19 | fn to_string() -> String { 20 | format!("({} . {})", T1::to_string(), T2::to_string()) 21 | } 22 | } 23 | 24 | #[macro_export] 25 | macro_rules! list { 26 | () => { 27 | $crate::cons::Nil 28 | }; 29 | (,) => { 30 | $crate::cons::Nil 31 | }; 32 | (, $t: ty $(, $tys: ty)*) => { 33 | $crate::cons::ConsCell<$t , list!($(, $tys)*)> 34 | }; 35 | ($t: ty $(, $tys: ty)*) => { 36 | $crate::cons::ConsCell<$t , list!($(, $tys)*)> 37 | }; 38 | } 39 | 40 | pub type Cons = symbol!(C O N S); 41 | pub type Car = symbol!(C A R); 42 | pub type Cdr = symbol!(C D R); 43 | 44 | 45 | impl Fun2 for Cons { 46 | type Out = ConsCell; 47 | } 48 | 49 | impl Fun1> for Car { 50 | type Out = T1; 51 | } 52 | 53 | impl Fun1> for Cdr { 54 | type Out = T2; 55 | } 56 | -------------------------------------------------------------------------------- /src/env.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | use std::marker::PhantomData; 3 | use expr::*; 4 | 5 | pub trait Env{ } 6 | pub struct Bottom; 7 | pub struct Stack {pelm: PhantomData, pt: PhantomData} 8 | impl Env for Bottom {} 9 | impl Env for Stack {} 10 | 11 | pub type Stack1 = Stack; 12 | pub type Stack2 = Stack>; 13 | pub type Stack3 = Stack>; 14 | pub type Stack4 = Stack>; 15 | -------------------------------------------------------------------------------- /src/eval.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | use std::marker::PhantomData; 3 | use expr::*; 4 | use env::*; 5 | use fun::*; 6 | use num::*; 7 | use symbol::*; 8 | use cons::*; 9 | 10 | // trait Eval { 11 | // type Out: Env; 12 | // } 13 | 14 | // impl Eval> for Ev { 15 | // type Out = Stack, Ev>; 16 | // } 17 | 18 | // impl Eval> for Ev { 19 | // type Out = Stack, Ev>; 20 | // } 21 | 22 | // trait Call { 23 | // type Out: Env; 24 | // } 25 | 26 | // impl Eval, T1>> for Ev 27 | // where Ev: Eval>, 28 | // Symbol: Fun1, 29 | // { 30 | // type Out = Stack; 31 | // } 32 | 33 | pub trait Eval { 34 | type Out: Expr; 35 | } 36 | 37 | impl Eval for Number { 38 | type Out = Number; 39 | } 40 | 41 | impl Eval for Symbol { 42 | type Out = Symbol; 43 | } 44 | 45 | impl Eval for list!(Symbol, T1) 46 | where T1: Eval, 47 | Symbol: Fun1, 48 | { 49 | type Out = O; 50 | } 51 | 52 | impl Eval for list!(Symbol, T1, T2) 53 | where T1: Eval, 54 | T2: Eval, 55 | Symbol: Fun2, 56 | { 57 | type Out = O; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /src/expr.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | use std::marker::PhantomData; 3 | 4 | pub struct Stuck; 5 | pub struct Nothing; 6 | pub trait Expr { 7 | fn to_string() -> String; 8 | } 9 | impl Expr for Stuck { 10 | fn to_string() -> String { 11 | "stuck".to_string() 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/fun.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | use expr::*; 3 | 4 | pub trait Fun1 { 5 | type Out: Expr; 6 | } 7 | 8 | impl Fun1 for Stuck { 9 | type Out = Stuck; 10 | } 11 | 12 | pub trait Fun2 { 13 | type Out: Expr; 14 | } 15 | 16 | impl Fun2 for Stuck { 17 | type Out = Stuck; 18 | } 19 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::marker::PhantomData; 2 | 3 | pub mod expr; 4 | #[macro_use] 5 | pub mod symbol; 6 | pub mod fun; 7 | pub mod num; 8 | #[macro_use] 9 | pub mod cons; 10 | pub mod env; 11 | pub mod eval; 12 | pub mod user; 13 | 14 | 15 | #[macro_export] 16 | macro_rules! eval { 17 | ($t: ty) => { 18 | <<$t as $crate::eval::Eval>::Out as $crate::expr::Expr>::to_string() 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate rustlisp; 3 | use rustlisp::expr::*; 4 | use rustlisp::fun::*; 5 | use rustlisp::num::*; 6 | use rustlisp::symbol::*; 7 | use rustlisp::cons::*; 8 | use rustlisp::eval::*; 9 | use rustlisp::user::*; 10 | 11 | fn main() { 12 | println!("{}", Car::to_string()); 13 | println!("{}", _3::to_string()); 14 | println!("{}", <>::Out as Expr>::to_string()); 15 | println!("{}", eval!(list!(Fib, _3))); 16 | } 17 | -------------------------------------------------------------------------------- /src/num.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | use std::marker::PhantomData; 3 | use expr::*; 4 | use fun::*; 5 | use symbol::*; 6 | 7 | pub struct Number { 8 | number: PhantomData, 9 | } 10 | 11 | impl Expr for Number { 12 | fn to_string() -> String { 13 | N::to_string() 14 | } 15 | } 16 | 17 | pub trait Num { 18 | fn to_string() -> String { 19 | Self::to_int().to_string() 20 | } 21 | fn to_int() -> isize; 22 | } 23 | pub struct Zero; 24 | pub struct Succ {t: PhantomData} 25 | impl Num for Zero { 26 | fn to_int() -> isize { 27 | 0 28 | } 29 | } 30 | impl Num for Succ { 31 | fn to_int() -> isize { 32 | 1 + T::to_int() 33 | } 34 | } 35 | 36 | macro_rules! numty { 37 | ($num: ident, $n: ident, $p: ty) => { 38 | pub type $n= Succ<$p>; 39 | pub type $num = Number<$n>; 40 | } 41 | } 42 | 43 | pub type __0 = Zero; 44 | pub type _0 = Number<__0>; 45 | numty!(_1, __1, __0); 46 | numty!(_2, __2, __1); 47 | numty!(_3, __3, __2); 48 | numty!(_4, __4, __3); 49 | numty!(_5, __5, __4); 50 | numty!(_6, __6, __5); 51 | numty!(_7, __7, __6); 52 | numty!(_8, __8, __7); 53 | numty!(_9, __9, __8); 54 | numty!(_10, __10, __9); 55 | 56 | 57 | pub type Add = symbol!(A D D); 58 | pub type Mul = symbol!(M U L); 59 | 60 | impl Fun2, _0> for Add { 61 | type Out = Number; 62 | } 63 | 64 | impl Fun2, Number>> for Add 65 | where Add: Fun2>, Number, Out = Number> { 66 | type Out = Number; 67 | } 68 | 69 | 70 | -------------------------------------------------------------------------------- /src/symbol.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | use std::marker::PhantomData; 3 | use expr::*; 4 | 5 | pub struct Symbol{ 6 | s: PhantomData 7 | } 8 | 9 | impl Expr for Symbol { 10 | fn to_string() -> String { 11 | S::to_string() 12 | } 13 | } 14 | 15 | pub trait Sym { 16 | fn to_string() -> String; 17 | } 18 | pub trait SymChar{ 19 | fn to_string() -> String; 20 | } 21 | pub struct Eos; 22 | pub struct SymCons { 23 | cp: PhantomData, 24 | sp: PhantomData, 25 | } 26 | impl Sym for Eos{ 27 | fn to_string() -> String { 28 | "".to_string() 29 | } 30 | } 31 | impl Sym for SymCons{ 32 | fn to_string() -> String { 33 | C::to_string() + &S::to_string() 34 | } 35 | 36 | } 37 | 38 | macro_rules! symchar { 39 | ($c: ident) => { 40 | pub struct $c; 41 | impl SymChar for $c { 42 | fn to_string() -> String { 43 | stringify!($c).to_string() 44 | } 45 | } 46 | } 47 | } 48 | macro_rules! symchars { 49 | ($c1: ident) => { 50 | symchar!($c1); 51 | }; 52 | ($c1: ident,) => { 53 | symchar!($c1); 54 | }; 55 | ($c1: ident $(, $c: ident)*) => { 56 | symchar!($c1); 57 | symchars!($($c,)*); 58 | }; 59 | ($c1: ident $(, $c: ident)*,) => { 60 | symchar!($c1); 61 | symchars!($($c,)*); 62 | }; 63 | } 64 | symchars!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z); 65 | 66 | #[macro_export] 67 | macro_rules! sym { 68 | () => { 69 | $crate::symbol::Eos 70 | }; 71 | (,) => { 72 | $crate::symbol::Eos 73 | }; 74 | (, $t: ty $(, $tys: ty)*) => { 75 | $crate::symbol::SymCons<$t , sym!($(, $tys)*)> 76 | }; 77 | ($t: ty $(, $tys: ty)*) => { 78 | $crate::symbol::SymCons<$t , sym!($(, $tys)*)> 79 | }; 80 | } 81 | 82 | #[macro_export] 83 | macro_rules! symbol { 84 | ($($sym:ty)*) => { 85 | Symbol 86 | }; 87 | } 88 | -------------------------------------------------------------------------------- /src/user.rs: -------------------------------------------------------------------------------- 1 | use expr::*; 2 | use symbol::*; 3 | use fun::*; 4 | use num::*; 5 | use eval::*; 6 | 7 | pub type Fib = symbol!(F I B); 8 | 9 | impl Fun1<_0> for Fib { 10 | type Out = _1; 11 | } 12 | 13 | impl Fun1<_1> for Fib { 14 | type Out = _1; 15 | } 16 | 17 | impl Fun1>>> for Fib 18 | where Fib: Fun1>, Out = Number>, 19 | Fib: Fun1, Out = Number>, 20 | Add: Fun2, Number, Out = Number> 21 | { 22 | type Out = Number; 23 | } 24 | --------------------------------------------------------------------------------