Skip to content

Commit eef8109

Browse files
committed
Sketch out IR
Playing around with IR
1 parent f28321e commit eef8109

File tree

13 files changed

+216
-29
lines changed

13 files changed

+216
-29
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ members = [
33
"crates/sml-driver",
44
"crates/sml-core",
55
"crates/sml-frontend",
6+
"crates/sml-ir",
67
"crates/sml-util",
78
]
89

README.md

-12
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,3 @@ We take an approach similar to MLton, where we will be performing whole-program
1414
- [ ] SSA transformation
1515
- [ ] Optimization passes
1616
- [ ] Native code generation
17-
18-
19-
### Compilation speeds
20-
21-
Current speeds as of 6/30/2020:
22-
23-
For a 10k line file:
24-
25-
Lexing and parsing takes ~10 ms
26-
Elaboration and type reconstruction takes ~30ms
27-
28-
Moving to an arena allocator for the CoreML language takes us down to around ~35 ms for elaboration

crates/sml-core/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ edition = "2018"
99
[dependencies]
1010
typed-arena = "2.0"
1111

12+
[dependencies.sml-ir]
13+
path = "../sml-ir"
14+
1215
[dependencies.sml-frontend]
1316
path = "../sml-frontend"
1417

crates/sml-core/src/arenas.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ impl<'a> CoreArena<'a> {
193193
tyvar_rank: usize,
194194
) -> Expr<'a> {
195195
let expr = self.expr_tuple(iter.into_iter().map(|(sym, ty)| (ExprKind::Var(sym), ty)));
196-
let tyvars = expr.ty.ftv_rank(tyvar_rank + 1);
196+
let tyvars = expr.ty.ftv_rank(tyvar_rank);
197197
let decl = Decl::Val(
198198
tyvars,
199199
Rule {
@@ -218,7 +218,7 @@ impl<'a> CoreArena<'a> {
218218
tyvar_rank: usize,
219219
) -> Expr<'a> {
220220
let pat = self.pat_tuple(iter.into_iter().map(|(sym, ty)| (PatKind::Var(sym), ty)));
221-
let tyvars = pat.ty.ftv_rank(tyvar_rank + 1);
221+
let tyvars = pat.ty.ftv_rank(tyvar_rank);
222222
let decl = Decl::Val(
223223
tyvars,
224224
Rule {
@@ -247,7 +247,7 @@ impl<'a> CoreArena<'a> {
247247
.map(|(field, sym, ty)| (field, PatKind::Var(sym), ty)),
248248
);
249249

250-
let tyvars = pat.ty.ftv_rank(tyvar_rank + 1);
250+
let tyvars = pat.ty.ftv_rank(tyvar_rank);
251251
let decl = Decl::Val(
252252
tyvars,
253253
Rule {

crates/sml-core/src/builtin/constructors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ use sml_util::interner::*;
88
// datatype 'a list = nil | :: of 'a * 'a list
99
pub const C_NIL: Constructor = Constructor {
1010
name: S_NIL,
11+
tycon: S_LIST,
1112
type_id: TypeId(6),
1213
tag: 0,
1314
arity: 0,
1415
type_arity: 2,
1516
};
1617
pub const C_CONS: Constructor = Constructor {
1718
name: S_CONS,
19+
tycon: S_LIST,
1820
type_id: TypeId(6),
1921
tag: 1,
2022
arity: 1,
@@ -24,13 +26,15 @@ pub const C_CONS: Constructor = Constructor {
2426
// datatype bool = true | false
2527
pub const C_TRUE: Constructor = Constructor {
2628
name: S_TRUE,
29+
tycon: S_BOOL,
2730
type_id: TypeId(7),
2831
tag: 0,
2932
arity: 0,
3033
type_arity: 2,
3134
};
3235
pub const C_FALSE: Constructor = Constructor {
3336
name: S_FALSE,
37+
tycon: S_BOOL,
3438
type_id: TypeId(7),
3539
tag: 1,
3640
arity: 0,
@@ -39,6 +43,7 @@ pub const C_FALSE: Constructor = Constructor {
3943

4044
pub const C_REF: Constructor = Constructor {
4145
name: S_REF,
46+
tycon: S_REF,
4247
type_id: TypeId(5),
4348
tag: 0,
4449
arity: 1,
@@ -47,6 +52,7 @@ pub const C_REF: Constructor = Constructor {
4752

4853
pub const C_MATCH: Constructor = Constructor {
4954
name: S_MATCH,
55+
tycon: S_EXN,
5056
type_id: TypeId(8),
5157
tag: 0,
5258
arity: 0,
@@ -55,6 +61,7 @@ pub const C_MATCH: Constructor = Constructor {
5561

5662
pub const C_BIND: Constructor = Constructor {
5763
name: S_BIND,
64+
tycon: S_EXN,
5865
type_id: TypeId(8),
5966
tag: 0,
6067
arity: 0,

crates/sml-core/src/core_pp.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl<'a> Print for Expr<'a> {
4848
match &self.kind {
4949
App(e1, e2) => pp.print(e1).text(" ").print(e2),
5050
Case(casee, rules) => pp.nest(2, |pp| {
51-
pp.line().text("case ").print(casee).nest(2, |pp| {
51+
pp.line().text("case ").print(&casee.0).nest(2, |pp| {
5252
pp.line()
5353
.text("of ")
5454
.print(&rules[0].pat)

crates/sml-core/src/elaborate.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -776,8 +776,19 @@ impl<'a> Context<'a> {
776776
.message("branches of `if` expression don't have the same types")
777777
});
778778

779+
let var = self.fresh_var();
780+
let pat = self.arena.pat_var(var, self.arena.types.bool());
781+
782+
let decl = Decl::Val(Vec::new(), Rule { pat, expr: e1 });
783+
let body = Expr::new(
784+
self.arena
785+
.exprs
786+
.alloc(ExprKind::Case((var, pat.ty), vec![tru, fls])),
787+
e2.ty,
788+
sp,
789+
);
779790
Expr::new(
780-
self.arena.exprs.alloc(ExprKind::Case(e1, vec![tru, fls])),
791+
self.arena.exprs.alloc(ExprKind::Let(vec![decl], body)),
781792
e2.ty,
782793
sp,
783794
)
@@ -1391,6 +1402,7 @@ impl<'a> Context<'a> {
13911402

13921403
let cons = Constructor {
13931404
name: con.label,
1405+
tycon: db.tycon,
13941406
type_id,
13951407
tag: tag as u8,
13961408
arity: con.data.is_some() as u8,
@@ -1462,6 +1474,7 @@ impl<'a> Context<'a> {
14621474
for exn in exns {
14631475
let con = Constructor {
14641476
name: exn.label,
1477+
tycon: crate::builtin::tycons::T_EXN.name,
14651478
type_id: TypeId(8),
14661479
tag: 0,
14671480
arity: exn.data.is_some() as u8,

crates/sml-core/src/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@ pub mod builtin;
2727
pub mod check;
2828
pub mod core_pp;
2929
pub mod elaborate;
30+
pub mod lower;
3031
pub mod match_compile;
3132
pub mod types;
3233

34+
pub type Var<'a> = (Symbol, &'a Type<'a>);
35+
3336
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd, Eq, Hash)]
3437
pub struct TypeId(pub u32);
3538

@@ -38,7 +41,7 @@ pub struct ExprId(pub u32);
3841

3942
pub enum ExprKind<'ar> {
4043
App(Expr<'ar>, Expr<'ar>),
41-
Case(Expr<'ar>, Vec<Rule<'ar>>),
44+
Case(Var<'ar>, Vec<Rule<'ar>>),
4245
Con(Constructor, Vec<&'ar Type<'ar>>),
4346
Const(Const),
4447
/// Handle: try, bound var, case expr

crates/sml-core/src/lower.rs

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#![allow(unused_imports)]
2+
#![allow(dead_code)]
3+
#![allow(unused_variables)]
4+
use crate::arenas::{CoreArena, TypeArena};
5+
use crate::builtin::{constructors, tycons};
6+
use crate::types::{Constructor, Flex, Scheme, Tycon, Type, TypeVar};
7+
use crate::{
8+
Datatype, Decl, Expr, ExprId, ExprKind, Lambda, Pat, PatKind, Row, Rule, SortedRecord, TypeId,
9+
};
10+
use sml_util::interner::Symbol;
11+
12+
use ir::Var;
13+
use sml_ir as ir;
14+
15+
pub struct LoweringCtx {}
16+
17+
impl LoweringCtx {
18+
fn lower_sym(&mut self, sym: &Symbol) -> Symbol {
19+
todo!()
20+
}
21+
22+
fn lower_constructor(&mut self, con: Constructor) -> ir::Constructor {
23+
ir::Constructor {
24+
name: self.lower_sym(&con.name),
25+
tycon: self.lower_tycon(&con.tycon),
26+
tag: con.tag,
27+
}
28+
}
29+
30+
fn lower_ty(&mut self, ty: &Type<'_>) -> ir::Type {
31+
match ty {
32+
Type::Var(tyvar) => match tyvar.ty() {
33+
Some(ty) => self.lower_ty(ty),
34+
None => self.lower_tyvar(tyvar.id),
35+
},
36+
Type::Record(fields) => {
37+
let args = fields.iter().map(|ty| self.lower_ty(ty.data)).collect();
38+
ir::Type::Con(ir::Tycon::Tuple, args)
39+
}
40+
Type::Flex(flex) => match flex.ty() {
41+
Some(ty) => self.lower_ty(ty),
42+
None => {
43+
// This should likely be an error, flexible type never instantiated
44+
ir::Type::Con(ir::Tycon::Unit, vec![])
45+
}
46+
},
47+
Type::Con(con, args) => ir::Type::Con(
48+
self.lower_tycon(&con.name),
49+
args.iter().map(|ty| self.lower_ty(ty)).collect(),
50+
),
51+
}
52+
}
53+
54+
fn lower_tyvar(&mut self, tyvar: usize) -> ir::Type {
55+
ir::Type::Var(tyvar)
56+
}
57+
58+
fn lower_tycon(&mut self, tycon: &Symbol) -> ir::Tycon {
59+
match tycon {
60+
&sml_util::interner::S_ARROW => ir::Tycon::Arrow,
61+
&sml_util::interner::S_UNIT => ir::Tycon::Unit,
62+
&sml_util::interner::S_CHAR => ir::Tycon::Char,
63+
&sml_util::interner::S_INT => ir::Tycon::Int,
64+
&sml_util::interner::S_STRING => ir::Tycon::String,
65+
&sml_util::interner::S_REF => ir::Tycon::Ref,
66+
&sml_util::interner::S_LIST => ir::Tycon::List,
67+
&sml_util::interner::S_BOOL => ir::Tycon::Bool,
68+
&sml_util::interner::S_EXN => ir::Tycon::Exn,
69+
_ => ir::Tycon::Datatype(*tycon),
70+
}
71+
}
72+
73+
fn lower_expr(&mut self, expr: &Expr<'_>) -> ir::Block {
74+
let ty = self.lower_ty(expr.ty);
75+
match &expr.kind {
76+
ExprKind::App(e1, e2) => {
77+
let b1 = self.lower_expr(e1);
78+
let b2 = self.lower_expr(e2);
79+
todo!()
80+
}
81+
ExprKind::Case(e1, rules) => todo!(),
82+
ExprKind::Con(con, tys) => todo!(),
83+
ExprKind::Const(con) => todo!(),
84+
ExprKind::Handle(e1, sym, e2) => todo!(),
85+
ExprKind::Lambda(lam) => todo!(),
86+
ExprKind::Let(decls, e1) => todo!(),
87+
ExprKind::List(exs) => todo!(),
88+
ExprKind::Primitive(sym) => todo!(),
89+
ExprKind::Raise(e1) => todo!(),
90+
ExprKind::Record(rows) => todo!(),
91+
ExprKind::Seq(exs) => todo!(),
92+
ExprKind::Var(sym) => {
93+
ir::Expr::Var(Var(self.lower_sym(sym), self.lower_ty(expr.ty)));
94+
todo!()
95+
}
96+
}
97+
}
98+
}

crates/sml-core/src/match_compile.rs

+9-11
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,13 @@
1616
use crate::builtin::constructors::{C_BIND, C_MATCH};
1717
use crate::elaborate::{Context, ElabError, ErrorKind};
1818
use crate::types::{Constructor, Type};
19-
use crate::{Decl, Expr, ExprKind, Lambda, Pat, PatKind, Row, Rule, SortedRecord};
19+
use crate::{Decl, Expr, ExprKind, Lambda, Pat, PatKind, Row, Rule, SortedRecord, Var};
2020
use sml_util::diagnostics::Level;
2121
use sml_util::interner::Symbol;
2222
use sml_util::span::Span;
2323
use sml_util::Const;
2424
use std::collections::{HashMap, HashSet, VecDeque};
2525

26-
pub type Var<'a> = (Symbol, &'a Type<'a>);
27-
2826
pub fn case<'a>(
2927
ctx: &mut Context<'a>,
3028
scrutinee: Expr<'a>,
@@ -575,10 +573,10 @@ impl<'a, 'ctx> Matrix<'a, 'ctx> {
575573
}
576574

577575
Expr::new(
578-
self.ctx.arena.exprs.alloc(ExprKind::Case(
579-
self.ctx.arena.expr_var(self.vars[0].0, self.vars[0].1),
580-
rules,
581-
)),
576+
self.ctx
577+
.arena
578+
.exprs
579+
.alloc(ExprKind::Case(self.vars[0], rules)),
582580
self.ret_ty,
583581
Span::dummy(),
584582
)
@@ -647,10 +645,10 @@ impl<'a, 'ctx> Matrix<'a, 'ctx> {
647645
}
648646

649647
Expr::new(
650-
self.ctx.arena.exprs.alloc(ExprKind::Case(
651-
self.ctx.arena.expr_var(self.vars[0].0, self.vars[0].1),
652-
rules,
653-
)),
648+
self.ctx
649+
.arena
650+
.exprs
651+
.alloc(ExprKind::Case(self.vars[0], rules)),
654652
self.ret_ty,
655653
Span::dummy(),
656654
)

crates/sml-core/src/types.rs

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ pub struct Tycon {
6060
pub struct Constructor {
6161
pub name: Symbol,
6262
pub type_id: TypeId,
63+
pub tycon: Symbol,
6364
pub tag: u8,
6465
pub arity: u8,
6566
pub type_arity: u8,

crates/sml-ir/Cargo.toml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "sml-ir"
3+
version = "0.1.0"
4+
authors = ["Michael Lazear <[email protected]>"]
5+
edition = "2018"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies.sml-util]
10+
path = "../sml-util"

0 commit comments

Comments
 (0)