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.

40 changes: 0 additions & 40 deletions crates/core/src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,26 +86,6 @@ impl Ty {
}
}

/// Index of an instantiated function reference in a definition context.
#[cfg_attr(test, derive(TS), ts(export))]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(rename = "FuncId")
)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Func(usize);

pub fn func(id: usize) -> Func {
Func(id)
}

impl Func {
pub fn func(self) -> usize {
self.0
}
}

/// Index of a local variable in a function definition context.
#[cfg_attr(test, derive(TS), ts(export))]
#[cfg_attr(
Expand All @@ -125,23 +105,3 @@ impl Var {
self.0
}
}

/// Index of a block in a function definition context.
#[cfg_attr(test, derive(TS), ts(export))]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(rename = "BlockId")
)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Block(usize);

pub fn block(id: usize) -> Block {
Block(id)
}

impl Block {
pub fn block(self) -> usize {
self.0
}
}
132 changes: 64 additions & 68 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ use ts_rs::TS;
/// A type constraint.
#[cfg_attr(test, derive(TS), ts(export))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, EnumSetType)]
#[allow(clippy::derived_hash_with_manual_eq)] // `PartialEq` impl comes from enumset; should be fine
#[derive(Debug, EnumSetType, Hash)]
pub enum Constraint {
/// Not a `Ref`.
Value,
/// 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 +31,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,85 +39,59 @@ pub enum Ty {
Generic {
id: id::Generic,
},
/// Satisfies `Constraint::Scope`.
Scope {
id: id::Block,
/// Must be either `Read` or `Accum`.
kind: Constraint,
/// The `arg` variable of the `Expr` introducing this scope.
id: id::Var,
},
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>,
members: Vec<id::Ty>, // TODO: change to `Box<[id::Ty]`
},
}

/// Reference to a function, with types supplied for its generic parameters.
#[derive(Debug)]
pub struct Func {
pub id: id::Function,
pub generics: Vec<id::Ty>,
}

/// A function definition.
#[derive(Debug)]
pub struct Function {
/// Generic type parameters.
pub generics: Vec<EnumSet<Constraint>>,
pub generics: Box<[EnumSet<Constraint>]>,
/// Types used in this function definition.
pub types: Vec<Ty>,
/// Instantiations referenced functions with generic type parameters.
pub funcs: Vec<Func>,
/// Parameter type.
pub param: id::Ty,
/// Return type.
pub ret: id::Ty,
pub types: Box<[Ty]>,
/// Local variable types.
pub vars: Vec<id::Ty>,
/// Blocks of code.
pub blocks: Vec<Block>,
/// Main block.
pub main: id::Block,
pub vars: Box<[id::Ty]>,
/// Parameter variables.
pub params: Box<[id::Var]>,
/// Return variable.
pub ret: id::Var,
/// Function body.
pub body: Box<[Instr]>,
}

/// Wrapper for a `Function` that knows how to resolve its `id::Function`s.
pub trait FuncNode {
fn def(&self) -> &Function;

/// Only valid with `id::Function`s from `self.def().funcs`.
fn get(&self, id: id::Function) -> Option<Self>
where
Self: Sized;
}

#[cfg_attr(test, derive(TS), ts(export))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug)]
pub struct Block {
/// Input variable to this block.
pub arg: id::Var,
pub code: Vec<Instr>,
/// Output variable from this block.
pub ret: id::Var,
}

#[cfg_attr(test, derive(TS), ts(export))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug)]
pub struct Instr {
pub var: id::Var,
pub expr: Expr,
}

#[cfg_attr(test, derive(TS), ts(export))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug)]
pub enum Expr {
Expand All @@ -131,10 +107,10 @@ pub enum Expr {
},

Array {
elems: Vec<id::Var>,
elems: Box<[id::Var]>,
},
Tuple {
members: Vec<id::Var>,
members: Box<[id::Var]>,
},

Index {
Expand All @@ -154,7 +130,7 @@ pub enum Expr {
Field {
/// Must actually be a `Ref` of a tuple, not just a tuple.
tuple: id::Var,
field: id::Member,
member: id::Member,
},

Unary {
Expand All @@ -166,38 +142,58 @@ 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,
id: id::Function,
generics: Box<[id::Ty]>,
args: Box<[id::Var]>,
},
For {
/// Must satisfy `Constraint::Index`.
index: id::Ty,
/// `arg` has type `index`.
body: id::Block,
/// has type `index`.
arg: id::Var,
body: Box<[Instr]>,
/// Variable from `body` holding an array element.
ret: id::Var,
},
Accum {
/// Final contents of the `Ref`.
/// Scope for a `Ref` with `Constraint::Read`. Returns `Unit`.
Read {
/// 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`.
body: id::Block,
/// Has type `Ref` with scope `arg` and inner type same as `var`.
arg: id::Var,
body: Box<[Instr]>,
/// Variable from `body` holding the result of this block; escapes into outer scope.
ret: id::Var,
},
/// Scope for a `Ref` with `Constraint::Accum`. Returns the final contents of the `Ref`.
Accum {
/// Topology of the `Ref`.
shape: id::Var,
/// Has type `Ref` with scope `arg` and inner type same as `shape`.
arg: id::Var,
body: Box<[Instr]>,
/// Variable from `body` holding the result of this block; escapes into outer scope.
ret: id::Var,
},

/// 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
Loading