Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove branching and nested Refs #64

Merged
merged 13 commits into from
Aug 1, 2023
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 29 additions & 21 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ use ts_rs::TS;
pub enum Constraint {
/// Can be the `index` type of an `Array`.
Index,
/// Has a zero value and an addition operation.
Vector,
/// Can be the `scope` type of a `Ref`.
Scope,
/// Allows a `Ref` to be read when used as its `scope` type.
Read,
/// Allows a `Ref` to be accumulated into when used as its `scope` type.
Accum,
}

/// A type.
Expand All @@ -28,7 +28,6 @@ pub enum Constraint {
pub enum Ty {
Unit,
Bool,
/// Satisfies `Constraint::Vector`.
F64,
/// A nonnegative integer less than `size`. Satisfies `Constraint::Index`.
Fin {
Expand All @@ -37,22 +36,19 @@ pub enum Ty {
Generic {
id: id::Generic,
},
/// Satisfies `Constraint::Scope`.
/// May satisfy `Constraint::Read` or `Constraint::Accum` depending on the block.
Scope {
id: id::Block,
},
Ref {
/// Must satisfy `Constraint::Scope`.
scope: id::Ty,
inner: id::Ty,
},
/// Satisfies `Constraint::Vector` if `elem` does.
Array {
/// Must satisfy `Constraint::Index`.
index: id::Ty,
elem: id::Ty,
},
/// Satisfies `Constraint::Vector` if all `members` do.
Tuple {
members: Vec<id::Ty>,
},
Expand Down Expand Up @@ -166,38 +162,50 @@ pub enum Expr {
left: id::Var,
right: id::Var,
},
Select {
/// Must be of type `Bool`.
cond: id::Var,
then: id::Var,
els: id::Var,
},

Call {
func: id::Func,
arg: id::Var,
},
If {
cond: id::Var,
/// `arg` has type `Unit`.
then: id::Block,
/// `arg` has type `Unit`.
els: id::Block,
},
For {
/// Must satisfy `Constraint::Index`.
index: id::Ty,
/// `arg` has type `index`.
body: id::Block,
},
/// Scope for a `Ref` with `Constraint::Read`.
Read {
/// Contents of the `Ref`.
var: id::Var,
/// `arg` has type `Ref` with scope `body` and inner type same as `var`.
body: id::Block,
},
/// Scope for a `Ref` with `Constraint::Accum`.
Accum {
/// Final contents of the `Ref`.
var: id::Var,
/// Must satisfy `Constraint::Vector`.
vector: id::Ty,
/// `arg` has type `Ref` with scope `body` and inner type `vector`.
/// Topology of the `Ref`.
shape: id::Var,
/// `arg` has type `Ref` with scope `body` and inner type same as `shape`.
body: id::Block,
},

/// Accumulate into a `Ref`. Returned type is `Unit`.
/// Read from a `Ref` whose `scope` satisfies `Constraint::Read`.
Ask {
/// The `Ref`, which must be in scope.
var: id::Var,
},
/// Accumulate into a `Ref` whose `scope` satisfies `Constraint::Accum`. Returns `Unit`.
Add {
/// The `Ref`, which must be in scope.
accum: id::Var,
/// Must be of the `Ref`'s inner type, which must satisfy `Constraint::Vector`.
/// Must be of the `Ref`'s inner type.
addend: id::Var,
},
}
Expand Down
35 changes: 7 additions & 28 deletions crates/frontend/src/translate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,38 +314,17 @@ impl<'input, 'a> BlockCtx<'input, 'a> {
}
ast::Expr::If { cond, then, els } => {
let c = self.typecheck(*cond)?; // TODO: ensure this is `Bool`
let code = std::mem::take(&mut self.c);
// the `BlockCtx` type can only think about one under-construction block at a time,
// so when constructing an `If`, we keep swapping them out until we're done

let unit = self.newtype(ir::Ty::Unit);

let arg_then = self.newlocal(unit);
let ret_then = self.typecheck(*then)?;
let block_then = id::block(self.b.len());
let code_then = std::mem::take(&mut self.c);
self.b.push(ir::Block {
arg: arg_then,
code: code_then,
ret: ret_then,
});

let arg_els = self.newlocal(unit);
let ret_els = self.typecheck(*els)?;
let block_els = id::block(self.b.len());
let code_els = std::mem::replace(&mut self.c, code);
self.b.push(ir::Block {
arg: arg_els,
code: code_els,
ret: ret_els,
});
// IR doesn't currently support branching, so just evaluate both branches
let t = self.typecheck(*then)?;
let e = self.typecheck(*els)?;

Ok(self.instr(
self.getlocal(ret_then), // TODO: ensure this matches the type of `ret_els`
ir::Expr::If {
self.getlocal(t), // TODO: ensure this matches the type of `e`
ir::Expr::Select {
cond: c,
then: block_then,
els: block_els,
then: t,
els: e,
},
))
}
Expand Down
11 changes: 5 additions & 6 deletions crates/frontend/tests/interp.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use indexmap::IndexSet;
use rose_frontend::parse;
use rose_interp::{interp, Val};
use std::rc::Rc;
use rose_interp::{interp, val_f64, vals, Val};

#[test]
fn test_add() {
Expand All @@ -11,10 +10,10 @@ fn test_add() {
module.get_func("add").unwrap(),
IndexSet::new(),
&[],
Val::Tuple(Rc::new(vec![Val::F64(2.), Val::F64(2.)])),
Val::Tuple(vals([val_f64(2.), val_f64(2.)])),
)
.unwrap();
assert_eq!(answer, Val::F64(4.));
assert_eq!(answer, val_f64(4.));
}

#[test]
Expand All @@ -25,8 +24,8 @@ fn test_sub() {
module.get_func("sub").unwrap(),
IndexSet::new(),
&[],
Val::Tuple(Rc::new(vec![Val::F64(2.), Val::F64(2.)])),
Val::Tuple(vals([val_f64(2.), val_f64(2.)])),
)
.unwrap();
assert_eq!(answer, Val::F64(0.));
assert_eq!(answer, val_f64(0.));
}
1 change: 1 addition & 0 deletions crates/interp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ publish = false
edition = "2021"

[dependencies]
enumset = "1"
indexmap = "2"
rose = { path = "../core" }
serde = { version = "1", features = ["derive", "rc"], optional = true }
Expand Down
Loading