gdritter repos picoml / 7da5e65
Add some stubbed out crap for picoml Getty Ritter 5 years ago
5 changed file(s) with 191 addition(s) and 0 deletion(s). Collapse all Expand all
1
2 /target/
3 **/*.rs.bk
4 *~
1 [package]
2 name = "picoml"
3 version = "0.1.0"
4 authors = ["Getty Ritter <gettylefou@gmail.com>"]
5
6 [dependencies]
1 (* basic recursive factorial *)
2 let fact (n : Nat) : Nat = match n with
3 | 0 => 1
4 | _ => n * fact(n-1)
5 end;
6
7 (* tail-recursive factorial *)
8 let tail_fact (n : Nat) : Nat = do
9 let go (k : Nat) (r : Nat) : Nat = match k with
10 | 0 => r
11 | _ => go (k - 1) (r * k)
12 end;
13 go n 1
14 end;
15
16 (* unnecessarily elaborate monoidal approach *)
17 type Monoid m = {
18 mappend : m -> m -> m,
19 mempty : m,
20 };
21
22 let mconcat (m : Monoid t) (lst: List t) -> t = match lst with
23 | Cons x xs -> m.mappend x (mconcat m xs)
24 | Nil -> m.mempty
25 end;
26
27 let prod_monoid : Monoid Nat = {
28 mappend = (*),
29 mempty = 1,
30 };
31
32 let range x y = cond
33 | x == y = Nil
34 | x < y = Cons x (range (x+1) y)
35 | else = panic "Bad range!"
36 end
37
38 let product = mconcat prod_monoid;
39 let monoidal_fact n = product (range 1 n);
1 io.print_ln "Hello, world!";
1 use std::collections::HashMap;
2
3 type Ident = String;
4 type Env = HashMap<Ident, Value>;
5
6 #[derive(Debug, Clone)]
7 pub enum Stmt {
8 Let(Pat, Option<Type>, Vec<Pat>, Expr),
9 Expr(Expr),
10 }
11
12 impl Stmt {
13 fn eval(&self, env: &mut Env) -> Result<Value, String> {
14 match *self {
15 Stmt::Expr(ref e) => e.eval(env),
16 Stmt::Let(ref p, _, _, ref e) => {
17 p.bind(e.eval(env)?, env);
18 Ok(Value::Unit)
19 },
20 }
21 }
22 }
23
24 #[derive(Debug, Clone)]
25 pub enum Pat {
26 Var(Ident),
27 }
28
29 impl Pat {
30 fn bind(&self, val: Value, env: &mut Env) {
31 match *self {
32 Pat::Var(ref n) => {
33 let _ = env.insert(n.clone(), val);
34 }
35 }
36 }
37
38 fn mk_var<S: Into<String>>(s: S) -> Pat {
39 Pat::Var(s.into())
40 }
41 }
42
43 #[derive(Debug, Clone)]
44 pub enum Type {
45 Prim(PrimType),
46 Arr(Box<Type>, Box<Type>),
47 }
48
49 #[derive(Debug, Clone)]
50 pub enum PrimType {
51 Unit,
52 Nat,
53 }
54
55 #[derive(Debug, Clone)]
56 pub enum Expr {
57 Var(Ident),
58 Lit(Literal),
59 Fn(Box<Pat>, Box<Expr>),
60 App(Box<Expr>, Box<Expr>),
61 Do(Vec<Stmt>),
62 }
63
64 #[derive(Debug, Clone)]
65 pub enum Value {
66 Closure(Pat, Expr, Box<Env>),
67 Lit(Literal),
68 Unit,
69 }
70
71 impl Expr {
72 pub fn eval(&self, env: &mut Env) -> Result<Value, String> {
73 match *self {
74 Expr::Var(ref n) => Ok(env.get(n).unwrap().clone()),
75
76 Expr::Lit(ref l) => Ok(Value::Lit(l.clone())),
77
78 Expr::Fn(ref pat, ref e) =>
79 Ok(Value::Closure(
80 *pat.clone(),
81 *e.clone(),
82 Box::new(env.clone()),
83 )),
84
85 Expr::App(ref e1, ref e2) => {
86 let v1 = e1.eval(env)?;
87 let v2 = e2.eval(env)?;
88 match v1 {
89 Value::Closure(p, e, mut env2) => {
90 p.bind(v2, &mut env2);
91 e.eval(&mut env2)
92 },
93 _ => return Err(format!("not a function")),
94 }
95 },
96
97 Expr::Do(ref stmts) => {
98 let mut result = Value::Unit;
99 for stmt in stmts.iter() {
100 result = stmt.eval(env)?;
101 }
102 Ok(result)
103 },
104 }
105 }
106
107 fn mk_fn(p: Pat, e: Expr) -> Expr {
108 Expr::Fn(Box::new(p), Box::new(e))
109 }
110
111 fn mk_app(e1: Expr, e2: Expr) -> Expr {
112 Expr::App(Box::new(e1), Box::new(e2))
113 }
114
115 fn mk_var<S: Into<String>>(s: S) -> Expr {
116 Expr::Var(s.into())
117 }
118 }
119
120 #[derive(Debug, Clone)]
121 pub enum Literal {
122 Int(i64),
123 }
124
125
126 fn main() {
127 let sample = Expr::mk_app(
128 Expr::mk_fn(
129 Pat::mk_var("x"),
130 Expr::mk_fn(
131 Pat::mk_var("y"),
132 Expr::mk_var("y"),
133 ),
134 ),
135 Expr::Lit(Literal::Int(5)),
136 );
137
138 let mut env = HashMap::new();
139 println!("{:#?}", sample.eval(&mut env));
140 println!("{:#?}", Expr::mk_app(sample, Expr::Lit(Literal::Int(6))).eval(&mut env));
141 }