Skip to content

Commit e8451a5

Browse files
committed
Use reference counting in AST
Closes #19
1 parent 5951701 commit e8451a5

File tree

8 files changed

+254
-249
lines changed

8 files changed

+254
-249
lines changed

src/check/mod.rs

+60-59
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Type and kind-checking for our DDL
22
3+
use std::rc::Rc;
4+
35
use syntax::{binary, host};
46
use syntax::{Name, Named, Program, Var};
57
use syntax::context::{Binding, Context};
@@ -19,28 +21,28 @@ pub enum ExpectedType<N> {
1921
#[derive(Debug, Clone, PartialEq, Eq)]
2022
pub enum TypeError<N> {
2123
/// A variable of the requested name was not bound in this scope
22-
UnboundVariable { expr: host::BoxExpr<N>, name: N },
24+
UnboundVariable { expr: host::RcExpr<N>, name: N },
2325
/// Variable bound in the context was not at the value level
2426
ExprBindingExpected {
25-
expr: host::BoxExpr<N>,
27+
expr: host::RcExpr<N>,
2628
found: Named<N, Binding<N>>,
2729
},
2830
/// One type was expected, but another was found
2931
Mismatch {
30-
expr: host::BoxExpr<N>,
31-
found: host::BoxType<N>,
32+
expr: host::RcExpr<N>,
33+
found: host::RcType<N>,
3234
expected: ExpectedType<N>,
3335
},
3436
/// Unexpected operand types in a equality comparison
3537
EqualityOperands {
36-
expr: host::BoxExpr<N>,
37-
lhs_ty: host::BoxType<N>,
38-
rhs_ty: host::BoxType<N>,
38+
expr: host::RcExpr<N>,
39+
lhs_ty: host::RcType<N>,
40+
rhs_ty: host::RcType<N>,
3941
},
4042
/// A field was missing when projecting on a record
4143
MissingField {
42-
struct_expr: host::BoxExpr<N>,
43-
struct_ty: host::BoxType<N>,
44+
struct_expr: host::RcExpr<N>,
45+
struct_ty: host::RcType<N>,
4446
field_name: N,
4547
},
4648
}
@@ -49,13 +51,13 @@ pub enum TypeError<N> {
4951
/// in the environment
5052
pub fn ty_of<N: Name>(
5153
ctx: &Context<N>,
52-
expr: &host::BoxExpr<N>,
53-
) -> Result<host::BoxType<N>, TypeError<N>> {
54+
expr: &host::RcExpr<N>,
55+
) -> Result<host::RcType<N>, TypeError<N>> {
5456
use syntax::host::{Binop, Expr, Type, TypeConst, Unop};
5557

5658
match **expr {
5759
// Constants are easy!
58-
Expr::Const(_, c) => Ok(Box::new(Type::Const(c.ty_const_of()))),
60+
Expr::Const(_, c) => Ok(Rc::new(Type::Const(c.ty_const_of()))),
5961

6062
// Variables
6163
Expr::Var(_, Var::Free(ref name)) => Err(TypeError::UnboundVariable {
@@ -77,11 +79,11 @@ pub fn ty_of<N: Name>(
7779
Expr::Unop(_, op, ref expr) => match op {
7880
Unop::Neg => {
7981
expect_ty(ctx, expr, Type::int())?;
80-
Ok(Box::new(Type::int()))
82+
Ok(Rc::new(Type::int()))
8183
}
8284
Unop::Not => {
8385
expect_ty(ctx, expr, Type::bool())?;
84-
Ok(Box::new(Type::bool()))
86+
Ok(Rc::new(Type::bool()))
8587
}
8688
},
8789

@@ -93,24 +95,24 @@ pub fn ty_of<N: Name>(
9395
expect_ty(ctx, lhs_expr, Type::bool())?;
9496
expect_ty(ctx, rhs_expr, Type::bool())?;
9597

96-
Ok(Box::new(Type::bool()))
98+
Ok(Rc::new(Type::bool()))
9799
}
98100

99101
// Equality operators
100102
Binop::Eq | Binop::Ne => {
101103
let lhs_ty = ty_of(ctx, lhs_expr)?;
102104
let rhs_ty = ty_of(ctx, rhs_expr)?;
103105

104-
match (*lhs_ty, *rhs_ty) {
105-
(Type::Const(TypeConst::Bit), Type::Const(TypeConst::Bit)) |
106-
(Type::Const(TypeConst::Bool), Type::Const(TypeConst::Bool)) |
107-
(Type::Const(TypeConst::Int), Type::Const(TypeConst::Int)) => {
108-
Ok(Box::new(Type::bool()))
106+
match (&*lhs_ty, &*rhs_ty) {
107+
(&Type::Const(TypeConst::Bit), &Type::Const(TypeConst::Bit)) |
108+
(&Type::Const(TypeConst::Bool), &Type::Const(TypeConst::Bool)) |
109+
(&Type::Const(TypeConst::Int), &Type::Const(TypeConst::Int)) => {
110+
Ok(Rc::new(Type::bool()))
109111
}
110112
(lhs_ty, rhs_ty) => Err(TypeError::EqualityOperands {
111113
expr: expr.clone(),
112-
lhs_ty: Box::new(lhs_ty),
113-
rhs_ty: Box::new(rhs_ty),
114+
lhs_ty: Rc::new(lhs_ty.clone()),
115+
rhs_ty: Rc::new(rhs_ty.clone()),
114116
}),
115117
}
116118
}
@@ -120,15 +122,15 @@ pub fn ty_of<N: Name>(
120122
expect_ty(ctx, lhs_expr, Type::int())?;
121123
expect_ty(ctx, rhs_expr, Type::int())?;
122124

123-
Ok(Box::new(Type::bool()))
125+
Ok(Rc::new(Type::bool()))
124126
}
125127

126128
// Arithmetic operators
127129
Binop::Add | Binop::Sub | Binop::Mul | Binop::Div => {
128130
expect_ty(ctx, lhs_expr, Type::int())?;
129131
expect_ty(ctx, rhs_expr, Type::int())?;
130132

131-
Ok(Box::new(Type::int()))
133+
Ok(Rc::new(Type::int()))
132134
}
133135
}
134136
}
@@ -153,11 +155,11 @@ pub fn ty_of<N: Name>(
153155

154156
match *ty_of(ctx, array_expr)? {
155157
// Check if index is in bounds?
156-
Type::Array(elem_ty, _) => Ok(elem_ty),
157-
found => Err(TypeError::Mismatch {
158+
Type::Array(ref elem_ty, _) => Ok(elem_ty.clone()),
159+
ref found => Err(TypeError::Mismatch {
158160
expr: array_expr.clone(),
159161
expected: ExpectedType::Array,
160-
found: Box::new(found),
162+
found: Rc::new(found.clone()),
161163
}),
162164
}
163165
}
@@ -167,7 +169,7 @@ pub fn ty_of<N: Name>(
167169
// FIXME: avoid cloning the environment
168170
let mut ctx = ctx.clone();
169171
ctx.extend(param_name.clone(), Binding::Expr(param_ty.clone()));
170-
Ok(Box::new(
172+
Ok(Rc::new(
171173
Type::arrow(param_ty.clone(), ty_of(&ctx, body_expr)?),
172174
))
173175
}
@@ -176,13 +178,10 @@ pub fn ty_of<N: Name>(
176178

177179
// Kinding
178180

179-
pub fn simplify_ty<N: Name>(ctx: &Context<N>, ty: &binary::BoxType<N>) -> binary::BoxType<N> {
181+
pub fn simplify_ty<N: Name>(ctx: &Context<N>, ty: &binary::RcType<N>) -> binary::RcType<N> {
180182
use syntax::binary::Type;
181183

182-
fn compute_ty<N: Name>(
183-
ctx: &Context<N>,
184-
ty: &binary::BoxType<N>,
185-
) -> Option<binary::BoxType<N>> {
184+
fn compute_ty<N: Name>(ctx: &Context<N>, ty: &binary::RcType<N>) -> Option<binary::RcType<N>> {
186185
match **ty {
187186
Type::Var(_, Var::Bound(Named(_, i))) => match ctx.lookup_ty_def(i) {
188187
Ok(Named(_, def_ty)) => Some(def_ty.clone()),
@@ -192,7 +191,7 @@ pub fn simplify_ty<N: Name>(ctx: &Context<N>, ty: &binary::BoxType<N>) -> binary
192191
Type::Abs(_, _, ref body_ty) => {
193192
// FIXME: Avoid clone
194193
let mut body = body_ty.clone();
195-
body.instantiate(arg_ty);
194+
Rc::make_mut(&mut body).instantiate(arg_ty);
196195
Some(body)
197196
}
198197
_ => None,
@@ -216,24 +215,24 @@ pub fn simplify_ty<N: Name>(ctx: &Context<N>, ty: &binary::BoxType<N>) -> binary
216215
#[derive(Debug, Clone, PartialEq, Eq)]
217216
pub enum ExpectedKind {
218217
Arrow,
219-
Actual(binary::BoxKind),
218+
Actual(binary::RcKind),
220219
}
221220

222221
/// An error that was encountered during kind checking
223222
#[derive(Debug, Clone, PartialEq, Eq)]
224223
pub enum KindError<N> {
225224
/// A variable of the requested name was not bound in this scope
226-
UnboundVariable { ty: binary::BoxType<N>, name: N },
225+
UnboundVariable { ty: binary::RcType<N>, name: N },
227226
/// Variable bound in the context was not at the type level
228227
TypeBindingExpected {
229-
ty: binary::BoxType<N>,
228+
ty: binary::RcType<N>,
230229
found: Named<N, Binding<N>>,
231230
},
232231
/// One kind was expected, but another was found
233232
Mismatch {
234-
ty: binary::BoxType<N>,
233+
ty: binary::RcType<N>,
235234
expected: ExpectedKind,
236-
found: binary::BoxKind,
235+
found: binary::RcKind,
237236
},
238237
/// A repr error
239238
Repr(binary::ReprError<N>),
@@ -257,8 +256,8 @@ impl<N> From<TypeError<N>> for KindError<N> {
257256
/// the environment
258257
pub fn kind_of<N: Name>(
259258
ctx: &Context<N>,
260-
ty: &binary::BoxType<N>,
261-
) -> Result<binary::BoxKind, KindError<N>> {
259+
ty: &binary::RcType<N>,
260+
) -> Result<binary::RcKind, KindError<N>> {
262261
use syntax::binary::{Kind, Type, TypeConst};
263262

264263
match **ty {
@@ -276,14 +275,14 @@ pub fn kind_of<N: Name>(
276275
},
277276

278277
// Bit type
279-
Type::Const(TypeConst::Bit) => Ok(Box::new(Kind::Type)),
278+
Type::Const(TypeConst::Bit) => Ok(Rc::new(Kind::Type)),
280279

281280
// Array types
282281
Type::Array(_, ref elem_ty, ref size_expr) => {
283282
expect_ty_kind(ctx, elem_ty)?;
284283
expect_ty(ctx, size_expr, host::Type::int())?;
285284

286-
Ok(Box::new(Kind::Type))
285+
Ok(Rc::new(Kind::Type))
287286
}
288287

289288
// Conditional types
@@ -292,7 +291,7 @@ pub fn kind_of<N: Name>(
292291
let pred_ty = host::Type::arrow(ty.repr()?, host::Type::bool());
293292
expect_ty(ctx, pred_expr, pred_ty)?;
294293

295-
Ok(Box::new(Kind::Type))
294+
Ok(Rc::new(Kind::Type))
296295
}
297296

298297
// Interpreted types
@@ -301,15 +300,15 @@ pub fn kind_of<N: Name>(
301300
let conv_ty = host::Type::arrow(ty.repr()?, host_ty.clone());
302301
expect_ty(ctx, conv_expr, conv_ty)?;
303302

304-
Ok(Box::new(Kind::Type))
303+
Ok(Rc::new(Kind::Type))
305304
}
306305

307306
// Type abstraction
308307
Type::Abs(_, Named(ref name, ref param_kind), ref body_ty) => {
309308
// FIXME: avoid cloning the environment
310309
let mut ctx = ctx.clone();
311310
ctx.extend(name.clone(), Binding::Type(param_kind.clone()));
312-
Ok(Box::new(
311+
Ok(Rc::new(
313312
Kind::arrow(param_kind.clone(), kind_of(&ctx, body_ty)?),
314313
))
315314
}
@@ -320,7 +319,7 @@ pub fn kind_of<N: Name>(
320319
expect_ty_kind(ctx, ty)?;
321320
}
322321

323-
Ok(Box::new(Kind::Type))
322+
Ok(Rc::new(Kind::Type))
324323
}
325324

326325
// Struct type
@@ -335,19 +334,19 @@ pub fn kind_of<N: Name>(
335334
ctx.extend(field.name.clone(), Binding::Expr(field_ty.repr()?));
336335
}
337336

338-
Ok(Box::new(Kind::Type))
337+
Ok(Rc::new(Kind::Type))
339338
}
340339

341340
// Type application
342341
Type::App(_, ref fn_ty, ref arg_ty) => match *kind_of(ctx, fn_ty)? {
343342
Kind::Type => Err(KindError::Mismatch {
344343
ty: fn_ty.clone(),
345-
found: Box::new(Kind::Type),
344+
found: Rc::new(Kind::Type),
346345
expected: ExpectedKind::Arrow,
347346
}),
348-
Kind::Arrow(param_kind, ret_kind) => {
349-
expect_kind(ctx, arg_ty, param_kind)?;
350-
Ok(ret_kind)
347+
Kind::Arrow(ref param_kind, ref ret_kind) => {
348+
expect_kind(ctx, arg_ty, param_kind.clone())?;
349+
Ok(ret_kind.clone())
351350
}
352351
},
353352
}
@@ -368,9 +367,9 @@ pub fn check_program<N: Name>(program: &Program<N>) -> Result<(), KindError<N>>
368367

369368
fn expect_ty<N: Name>(
370369
ctx: &Context<N>,
371-
expr: &host::BoxExpr<N>,
370+
expr: &host::RcExpr<N>,
372371
expected: host::Type<N>,
373-
) -> Result<host::BoxType<N>, TypeError<N>> {
372+
) -> Result<host::RcType<N>, TypeError<N>> {
374373
let found = ty_of(ctx, expr)?;
375374

376375
if *found == expected {
@@ -386,9 +385,9 @@ fn expect_ty<N: Name>(
386385

387386
fn expect_kind<N: Name>(
388387
ctx: &Context<N>,
389-
ty: &binary::BoxType<N>,
390-
expected: binary::BoxKind,
391-
) -> Result<binary::BoxKind, KindError<N>> {
388+
ty: &binary::RcType<N>,
389+
expected: binary::RcKind,
390+
) -> Result<binary::RcKind, KindError<N>> {
392391
let found = kind_of(ctx, ty)?;
393392

394393
if found == expected {
@@ -402,6 +401,8 @@ fn expect_kind<N: Name>(
402401
}
403402
}
404403

405-
fn expect_ty_kind<N: Name>(ctx: &Context<N>, ty: &binary::BoxType<N>) -> Result<(), KindError<N>> {
406-
expect_kind(ctx, ty, Box::new(binary::Kind::Type)).map(|_| ())
404+
fn expect_ty_kind<N: Name>(ctx: &Context<N>, ty: &binary::RcType<N>) -> Result<(), KindError<N>> {
405+
use syntax::binary::Kind;
406+
407+
expect_kind(ctx, ty, Rc::new(Kind::Type)).map(|_| ())
407408
}

0 commit comments

Comments
 (0)