Skip to content

Commit b1ca1c8

Browse files
committed
Start working on test suite #8
1 parent 48e05f1 commit b1ca1c8

File tree

21 files changed

+419
-127
lines changed

21 files changed

+419
-127
lines changed

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,8 @@ members = [
88

99

1010
[profile.release]
11-
lto = true
11+
debug = false
12+
opt-level = 3
13+
debug-assertions = false
14+
lto = "fat"
15+
codegen-units = 1

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ Current speeds as of 6/30/2020:
2323
For a 10k line file:
2424

2525
Lexing and parsing takes ~10 ms
26-
Elaboration and type reconstruction takes ~45ms
26+
Elaboration and type reconstruction takes ~30ms
2727

2828
Moving to an arena allocator for the CoreML language takes us down to around ~35 ms for elaboration

crates/sml-core/Cargo.toml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ edition = "2018"
77
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
88

99
[dependencies]
10-
sml-util = {path = "../sml-util"}
11-
sml-frontend = {path = "../sml-frontend"}
12-
typed-arena = "2.0"
10+
typed-arena = "2.0"
11+
12+
[dependencies.sml-frontend]
13+
path = "../sml-frontend"
14+
15+
[dependencies.sml-util]
16+
path = "../sml-util"

crates/sml-core/src/elaborate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use super::*;
77
use sml_frontend::ast;
88
use sml_frontend::parser::precedence::{self, Fixity, Precedence, Query};
99
use sml_util::diagnostics::Diagnostic;
10-
use std::collections::{HashMap, HashSet};
10+
use std::collections::HashMap;
1111

1212
pub fn check_and_elaborate<'ar>(
1313
arena: &'ar CoreArena<'ar>,

crates/sml-core/src/match_compile.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
1616
use super::*;
1717
use elaborate::Context;
18-
use sml_util::diagnostics::Diagnostic;
1918
use std::collections::{HashMap, HashSet, VecDeque};
2019

2120
pub type Var<'a> = (Symbol, &'a Type<'a>);
@@ -201,15 +200,15 @@ impl Facts {
201200
Some(Fact::Con(_, Some(x))) => {
202201
queue.push_back((x, pat));
203202
}
204-
x => panic!("Bug: Facts.bind constructor"),
203+
_ => panic!("Bug: Facts.bind constructor"),
205204
},
206205
PatKind::Record(rp) => match facts.get(var) {
207206
Some(Fact::Record(rx)) => {
208207
for (rp, rx) in rp.iter().zip(rx.iter()) {
209208
queue.push_back((&rx.data, &rp.data));
210209
}
211210
}
212-
x => panic!("Bug: Facts.bind record"),
211+
_ => panic!("Bug: Facts.bind record"),
213212
},
214213
_ => continue,
215214
}
@@ -367,7 +366,8 @@ impl<'a, 'ctx> Matrix<'a, 'ctx> {
367366
type_arity = con.type_arity;
368367
}
369368
}
370-
369+
let mut set = set.into_iter().collect::<Vec<_>>();
370+
set.sort_by(|a, b| a.0.name.cmp(&b.0.name));
371371
// We only use `true` and `false` or `cons` and `nil`, so we know
372372
// there are only 2 constructors in each datatype. Otherwise we
373373
// would need to query a context to determine this

crates/sml-core/src/pretty_print/core.rs

Lines changed: 84 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ impl<'a> Print for Expr<'a> {
5757
use ExprKind::*;
5858
match &self.expr {
5959
App(e1, e2) => pp.print(e1).text(" ").print(e2),
60-
Case(casee, rules) => {
61-
pp.text("case ").print(casee).nest(2, |pp| {
60+
Case(casee, rules) => pp.nest(2, |pp| {
61+
pp.line().text("case ").print(casee).nest(2, |pp| {
6262
pp.line()
6363
.text("of ")
6464
.print(&rules[0].pat)
@@ -76,7 +76,7 @@ impl<'a> Print for Expr<'a> {
7676
});
7777
}
7878
pp
79-
}
79+
}),
8080
Con(con, tys) => pp.print(&con.name),
8181
Const(c) => pp.print(&c),
8282
Handle(tryy, sym, handler) => pp
@@ -86,21 +86,21 @@ impl<'a> Print for Expr<'a> {
8686
.text(" with ")
8787
.print(handler),
8888
Lambda(lam) => pp.text("fn ").print(&lam.arg).text(" => ").print(&lam.body),
89-
Let(decls, body) => pp
90-
.text("let")
91-
.line()
92-
.nest(2, |pp| {
93-
for decl in decls {
94-
pp.print(decl).line();
95-
}
96-
pp
97-
})
98-
.text("in")
99-
.line()
100-
.nest(2, |pp| pp.print(body).line())
101-
.line()
102-
.text("end")
103-
.line(),
89+
Let(decls, body) => pp.nest(2, |pp| {
90+
pp.line()
91+
.text("let")
92+
.nest(2, |pp| {
93+
for decl in decls {
94+
pp.print(decl);
95+
}
96+
pp
97+
})
98+
.line()
99+
.text("in ")
100+
.nest(2, |pp| pp.line().print(body))
101+
.line()
102+
.text("end")
103+
}),
104104
List(exprs) => {
105105
pp.text("[");
106106
for (idx, expr) in exprs.iter().enumerate() {
@@ -203,23 +203,83 @@ impl<'a> Type<'a> {
203203
impl<'a> Print for Decl<'a> {
204204
fn print<'b, 'c>(&self, pp: &'b mut PrettyPrinter<'c>) -> &'b mut PrettyPrinter<'c> {
205205
match self {
206-
Decl::Val(Rule { pat, .. }) => {
207-
pp.text("val ").print(pat).text(": ").print(pat.ty).line()
208-
}
206+
Decl::Val(Rule { pat, expr }) => pp
207+
.line()
208+
.text("val ")
209+
.print(pat)
210+
.text(": ")
211+
.print(pat.ty)
212+
.text(" = ")
213+
.print(expr),
209214
Decl::Fun(_, binds) => {
210215
for (name, lam) in binds {
211-
pp.text("val ")
216+
pp.line()
217+
.text("val ")
212218
.print(name)
213219
.text(": ")
214220
.print(&Type::Con(
215221
crate::builtin::tycons::T_ARROW,
216222
vec![lam.ty, lam.body.ty],
217223
))
218-
.line();
224+
.text(" = ")
225+
.print(&lam.body);
226+
}
227+
pp
228+
}
229+
Decl::Exn(con, Some(ty)) => pp
230+
.line()
231+
.text("exception ")
232+
.print(&con.name)
233+
.text(" of ")
234+
.print(*ty),
235+
Decl::Exn(con, None) => pp.text("exception ").print(&con.name),
236+
Decl::Datatype(dt) => {
237+
let mut map = HashMap::new();
238+
pp.line();
239+
let pp = match dt.tyvars.len() {
240+
0 => pp.text("datatype ").print(&dt.tycon.name),
241+
1 => {
242+
map.insert(dt.tyvars[0], "'a".into());
243+
pp.text("datatype 'a ").print(&dt.tycon.name)
244+
}
245+
_ => {
246+
pp.text("datatype (");
247+
for (idx, tyvar) in dt.tyvars.iter().enumerate() {
248+
let last = ((idx % 26) as u8 + 'a' as u8) as char;
249+
let name = format!(
250+
"'{}",
251+
(0..idx / 26)
252+
.map(|_| 'z')
253+
.chain(std::iter::once(last))
254+
.collect::<String>()
255+
);
256+
pp.text(&name);
257+
map.insert(*tyvar, name);
258+
if idx != dt.tyvars.len() - 1 {
259+
pp.text(", ");
260+
}
261+
}
262+
pp.text(") ").print(&dt.tycon.name)
263+
}
264+
};
265+
pp.text(" = ");
266+
267+
for (idx, con) in dt.constructors.iter().enumerate() {
268+
match con {
269+
(con, Some(ty)) => {
270+
pp.print(&con.name).text(" of ");
271+
ty.print_rename(pp, &mut map);
272+
}
273+
(con, None) => {
274+
pp.print(&con.name);
275+
}
276+
}
277+
if idx != dt.constructors.len().saturating_sub(1) {
278+
pp.text(" | ");
279+
}
219280
}
220281
pp
221282
}
222-
_ => pp,
223283
}
224284
}
225285
}

crates/sml-core/src/pretty_print/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ impl<'a> PrettyPrinter<'a> {
3535
commands: VecDeque::new(),
3636
}
3737
}
38+
3839
pub fn test(&mut self) {
3940
self.wrap(20, |pp| {
4041
pp.text("case")
@@ -75,6 +76,9 @@ impl<'a> PrettyPrinter<'a> {
7576
self.max = self.prev_max.pop().unwrap_or(120);
7677
}
7778
Line => {
79+
if self.width == self.indent {
80+
continue;
81+
}
7882
let spaces = (0..self.indent).map(|_| ' ').collect::<String>();
7983
write!(w, "\n{}", spaces)?;
8084
self.width = self.indent;
@@ -129,6 +133,14 @@ impl<'a> PrettyPrinter<'a> {
129133
}
130134
}
131135

136+
fn fresh_name(x: u32) -> String {
137+
let last = ((x % 26) as u8 + 'a' as u8) as char;
138+
(0..x / 26)
139+
.map(|_| 'z')
140+
.chain(std::iter::once(last))
141+
.collect::<String>()
142+
}
143+
132144
pub trait Print {
133145
fn print<'a, 'b>(&self, pp: &'a mut PrettyPrinter<'b>) -> &'a mut PrettyPrinter<'b>;
134146
}
@@ -137,6 +149,7 @@ impl Print for Symbol {
137149
fn print<'a, 'b>(&self, pp: &'a mut PrettyPrinter<'b>) -> &'a mut PrettyPrinter<'b> {
138150
match self {
139151
Symbol::Tuple(n) => pp.text(n.to_string()),
152+
Symbol::Gensym(n) => pp.text(fresh_name(*n % 100)),
140153
_ => pp.text(pp.interner.get(*self).unwrap_or("?")),
141154
}
142155
}

crates/sml-driver/Cargo.toml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ edition = "2018"
66

77
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
88

9-
[dependencies]
10-
sml-core = {path = "../sml-core"}
11-
sml-frontend = {path = "../sml-frontend"}
12-
sml-util = {path = "../sml-util"}
9+
[dependencies.sml-core]
10+
path = "../sml-core"
11+
12+
[dependencies.sml-frontend]
13+
path = "../sml-frontend"
14+
15+
[dependencies.sml-util]
16+
path = "../sml-util"
17+
18+
[dev-dependencies.goldentests]
19+
version = "0.3.5"

crates/sml-driver/src/config.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use super::*;
2+
use std::env;
3+
4+
#[derive(Default)]
5+
pub struct CompilerBuilder {
6+
measure: Option<bool>,
7+
verbosity: Option<u8>,
8+
}
9+
10+
impl CompilerBuilder {
11+
pub fn build<'a>(self, arena: &'a sml_core::arenas::CoreArena<'a>) -> Compiler<'a> {
12+
Compiler {
13+
arena,
14+
elab: sml_core::elaborate::Context::new(arena),
15+
interner: Interner::with_capacity(4096),
16+
measure: self.measure.unwrap_or(false),
17+
verbosity: self.verbosity.unwrap_or(0),
18+
times: Vec::new(),
19+
}
20+
}
21+
22+
pub fn verbosity(mut self, val: u8) -> Self {
23+
self.verbosity = Some(val);
24+
self
25+
}
26+
27+
pub fn measure(mut self, val: bool) -> Self {
28+
self.measure = Some(val);
29+
self
30+
}
31+
}
32+
33+
pub struct ArgParse {
34+
pub builder: CompilerBuilder,
35+
pub files: Vec<String>,
36+
}
37+
38+
impl ArgParse {
39+
pub fn parse(args: env::Args) -> ArgParse {
40+
let mut stack = args.into_iter().skip(1).rev().collect::<Vec<String>>();
41+
let mut files = Vec::new();
42+
let mut builder = CompilerBuilder::default();
43+
while !stack.is_empty() {
44+
let item = stack.pop().unwrap();
45+
if item.starts_with("--") {
46+
match item.as_ref() {
47+
"--silent" => {
48+
builder = builder.verbosity(0);
49+
}
50+
"--v" => {
51+
builder = builder.verbosity(1);
52+
}
53+
"--vv" => {
54+
builder = builder.verbosity(2);
55+
}
56+
"--measure" => {
57+
builder = builder.measure(true);
58+
}
59+
_ => panic!("unrecognized compiler flag: {}", item),
60+
}
61+
} else {
62+
files.push(item);
63+
}
64+
}
65+
66+
ArgParse { builder, files }
67+
}
68+
}

0 commit comments

Comments
 (0)