Skip to content

Commit f92ba90

Browse files
chore: cleanup
1 parent 6e0848d commit f92ba90

File tree

6 files changed

+39
-41
lines changed

6 files changed

+39
-41
lines changed

README.md

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Algorithm J
2+
3+
Hindley–Milner Algorithm J implementation in Rust.
4+
5+
## Showcase
6+
7+
[![asciicast](https://asciinema.org/a/NT4YdX250se2wjcyOZi0Df8cx.svg)](https://asciinema.org/a/NT4YdX250se2wjcyOZi0Df8cx)
8+
9+
## Usage
10+
11+
To run the repl, use the following command:
12+
13+
```rust
14+
$ cargo run
15+
```
16+
17+
If you want to type check a file, use the following command:
18+
19+
```rust
20+
$ cargo run <filename>
21+
```
22+
23+
## References
24+
25+
- [Hindley–Milner Wikipedia page](https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system)
26+
- [How OCaml type checker works -- or what polymorphism and garbage collection have in common](https://okmij.org/ftp/ML/generalization.html)

examples/example.hm

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
let id = fun x -> x;
21
let unit = id ();
32
let perform = fun x -> x ();
43

4+
let id = fun x -> x;
55
let true = fun x -> fun y -> x;
66
let false = fun x -> fun y -> y;
77
let if = fun b -> fun x -> fun y -> b x y;
8-
let add = fun m -> fun n -> fun f -> fun x -> m f (n f x);
98

9+
let zero = fun f -> fun x -> x;
10+
let one = fun f -> fun x -> f x;
11+
let two = fun f -> fun x -> f f x;
12+
13+
let succ = fun n -> fun f -> fun x -> f (n f x);
14+
let pred = fun n -> fun f -> fun x -> n (fun g -> fun h -> h (g f)) (fun u -> x) (fun u -> u);

src/grammar.lalrpop

-5
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,7 @@ Let: Expr = {
3030
};
3131

3232
Terminal: Expr = {
33-
Int => Expr::Int(<>),
3433
"()" => Expr::Unit,
3534
Ident => Expr::Identifier(<>),
3635
"(" <Expr> ")",
3736
};
38-
39-
Int: i32 = {
40-
r"[0-9]+" => i32::from_str(<>).unwrap(),
41-
};

src/hm.rs

+2-29
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use crate::syntax::Expr;
21
/// Implementation of the Hindley-Milner type system
32
/// https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system
43
/// using the Algorithm J
4+
use crate::syntax::Expr;
55
use anyhow::{anyhow, bail};
66
use std::{
77
cell::RefCell,
@@ -151,20 +151,6 @@ impl Type {
151151
})))
152152
}
153153

154-
/// Unwrap the inner type of a Bound Var
155-
/// let bound_var = Expr::Var(Rc::new(RefCell::new { value: TypeVar::Bound { t: Type::Int } }));
156-
/// assert_eq!(bound_var.unwrap_boundvar(), Some(Type::Int))
157-
/// ```
158-
pub fn unwrap_boundvar(&self) -> Option<Type> {
159-
match self {
160-
Type::Var(tv) => match &*tv.borrow() {
161-
TypeVar::Bound { t } => Some(t.clone()),
162-
_ => None,
163-
},
164-
_ => None,
165-
}
166-
}
167-
168154
/// Replace vars that can be found in the table. Leave they if not found
169155
fn replace_vars(&self, table: &HashMap<VarId, Type>) -> Self {
170156
match self {
@@ -213,7 +199,7 @@ impl Type {
213199
}
214200
}
215201

216-
/// Unify algorithm in J performs mutation, so it doesnt return another type
202+
/// Unify algorithm in J performs mutation.
217203
pub fn unify(&self, other: &Type) -> anyhow::Result<()> {
218204
match (self, other) {
219205
(Type::Unit, Type::Unit) => Ok(()),
@@ -226,10 +212,6 @@ impl Type {
226212
match &mut *var {
227213
TypeVar::Bound { t: a } => a.unify(b),
228214
TypeVar::Unbound { id, level } => {
229-
// FIXME: check if its right
230-
// if &self == &other {
231-
// return Ok(());
232-
// }
233215
if b.occurs_check(*id, *level.borrow()) {
234216
bail!("Type Error (occurs check)");
235217
}
@@ -248,11 +230,6 @@ impl Type {
248230
match &mut *var {
249231
TypeVar::Bound { t: b } => b.unify(a),
250232
TypeVar::Unbound { id, level } => {
251-
// FIXME: check if its right
252-
// if &self == &other {
253-
// return Ok(());
254-
// }
255-
256233
if a.occurs_check(*id, *level.borrow()) {
257234
bail!("Type Error (occurs check)");
258235
}
@@ -293,10 +270,6 @@ impl Env {
293270
// -----------------------
294271
// Γ ⊢ () : unit
295272
Expr::Unit => Ok(Type::Unit),
296-
// Int rule
297-
// -----------------------
298-
// Γ ⊢ n where n is Int : Int
299-
Expr::Int(_) => Ok(Type::Int),
300273
// Var rule
301274
// x : polytype_a ∈ Γ t = inst(polytype_a)
302275
// -----------------------

src/main.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use std::{collections::HashMap, sync::atomic::Ordering};
22

3-
use algo_j::{hm::{Env, TYPEVAR_ID}, syntax::expand_all_lets};
3+
use algo_j::{
4+
hm::{Env, TYPEVAR_ID},
5+
syntax::expand_all_lets,
6+
};
47
use colored::Colorize;
58
use lalrpop_util::lalrpop_mod;
69

src/syntax.rs

-4
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ pub enum Expr {
1010
/// Identifier
1111
/// `x`
1212
Identifier(String),
13-
/// Int values
14-
/// `123`
15-
Int(i32),
1613
/// Lambda abstraction
1714
/// `\x -> e`
1815
Lambda(String, Box<Expr>),
@@ -33,7 +30,6 @@ impl Display for Expr {
3330
match self {
3431
Expr::Unit => write!(f, "()"),
3532
Expr::Identifier(id) => write!(f, "{id}"),
36-
Expr::Int(int) => write!(f, "{}", int),
3733
Expr::Lambda(x, body) => write!(f, "fun {} -> {}", x, body),
3834
Expr::Apply(e1, e2) => {
3935
if should_parenthesize(e1) {

0 commit comments

Comments
 (0)