Skip to content

Commit 05df13f

Browse files
committed
feat: add Num & Str, implement type synthesize
1 parent a24b08b commit 05df13f

File tree

2 files changed

+68
-16
lines changed

2 files changed

+68
-16
lines changed

src/stlc.rs

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
use std::collections::HashMap;
22

33
#[derive(Clone)]
4-
pub enum Term {
4+
pub enum Term<E> {
5+
Num(u64),
6+
Str(String),
57
Var(String),
6-
Fun(Environment, String, Box<Term>),
7-
App(Box<Term>, Box<Term>),
8+
Fun(E, String, Type, Box<Term<E>>),
9+
App(Box<Term<E>>, Box<Term<E>>),
810
}
911

1012
#[derive(Clone)]
11-
pub struct Environment(HashMap<String, Term>);
13+
pub struct Environment(HashMap<String, Term<Environment>>);
1214

1315
impl Environment {
1416
pub fn init() -> Self {
1517
Self(HashMap::new())
1618
}
17-
pub fn find(&self, name: &String) -> Option<Term> {
19+
pub fn find(&self, name: &String) -> Option<Term<Environment>> {
1820
match self.0.get(name) {
1921
Some(term) => Some(term.clone()),
2022
None => None
2123
}
2224
}
23-
pub fn push(&self, name: String, term: Term) -> Self {
25+
pub fn push(&self, name: String, term: Term<Environment>) -> Self {
2426
let mut next_envt = self.0.clone();
2527
next_envt.insert(name, term);
2628
Self(next_envt)
@@ -29,8 +31,22 @@ impl Environment {
2931

3032
#[derive(Clone)]
3133
pub enum Type {
32-
Atom,
33-
Func(Box<Type>, Box<Type>)
34+
Num,
35+
Str,
36+
Fun(Box<Type>, Box<Type>)
37+
}
38+
39+
impl PartialEq for Type {
40+
fn eq(&self, other: &Self) -> bool {
41+
match (self, other) {
42+
(Type::Num, Type::Num) => true,
43+
(Type::Str, Type::Str) => true,
44+
(Type::Fun(self_para, self_body),
45+
Type::Fun(other_para, other_body)) =>
46+
self_para.eq(other_para) && self_body.eq(self_body),
47+
_ => false
48+
}
49+
}
3450
}
3551

3652
pub struct Context(HashMap<String, Type>);
@@ -42,4 +58,36 @@ impl Context {
4258
None => None
4359
}
4460
}
61+
pub fn push(&self, name: String, ty: Type) -> Self {
62+
let mut new_ctx = self.0.clone();
63+
new_ctx.insert(name, ty.clone());
64+
Self(new_ctx)
65+
}
66+
}
67+
68+
fn synthesize(ctx: &Context, term: &Term<Context>) -> Option<Type> {
69+
match term {
70+
Term::Num(_) => Some(Type::Num),
71+
Term::Str(_) => Some(Type::Str),
72+
Term::Var(name) => ctx.find(name),
73+
Term::Fun(_, name, para_type, body) => {
74+
let new_ctx = ctx.push(name.clone(), para_type.clone());
75+
let body_type = synthesize(&new_ctx, &body)?;
76+
Some(Type::Fun(Box::new(para_type.clone()), Box::new(body_type)))
77+
},
78+
Term::App(lier, cant) => {
79+
let lier = synthesize(&ctx, &lier)?;
80+
let cant = synthesize(&ctx, &cant)?;
81+
match lier {
82+
Type::Fun(para_type, body_type) => {
83+
if *para_type == cant {
84+
Some(*body_type)
85+
} else {
86+
None
87+
}
88+
},
89+
_ => None
90+
}
91+
}
92+
}
4593
}

src/utlc.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,30 @@ use std::collections::HashMap;
22

33
#[derive(Clone)]
44
pub enum Term {
5+
Num(u64),
6+
Str(String),
57
Var(String),
68
Fun(Environment, String, Box<Term>),
79
App(Box<Term>, Box<Term>),
810
}
911

1012
impl Term {
11-
pub fn eval(envt: Environment, expr: Term) -> Term {
13+
pub fn eval(env: Environment, expr: Term) -> Term {
1214
match expr {
15+
Term::Num(num) => Term::Num(num),
16+
Term::Str(str) => Term::Str(str),
1317
Term::Var(name) =>
14-
match envt.find(&name) {
15-
Some(term) => Self::eval(envt, term),
18+
match env.find(&name) {
19+
Some(term) => Self::eval(env, term),
1620
None => Term::Var(name)
1721
}
18-
Term::Fun(_, patt, expr) => Term::Fun(envt, patt, expr),
22+
Term::Fun(_, patt, expr) => Term::Fun(env, patt, expr),
1923
Term::App(lier, cant) => {
20-
let lier_result = Self::eval(envt, *lier);
24+
let lier_result = Self::eval(env, *lier);
2125
match lier_result {
22-
Term::Fun(next_envt, patt, body) => {
23-
let envt = next_envt.push(patt, *body.clone());
24-
Self::eval(envt, *body)
26+
Term::Fun(new_env, patt, body) => {
27+
let env = new_env.push(patt, *body.clone());
28+
Self::eval(env, *body)
2529
},
2630
_ => Term::App(Box::new(lier_result), cant),
2731
}

0 commit comments

Comments
 (0)