Skip to content

Commit

Permalink
[multi]
Browse files Browse the repository at this point in the history
- move value into its own module
- remove _ from match clause
  • Loading branch information
kevaundray committed Feb 9, 2023
1 parent 846a24a commit cd78b1b
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 86 deletions.
87 changes: 1 addition & 86 deletions crates/noirc_evaluator/src/ssa/code_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::ssa::{
function::FuncIndex,
mem::ArrayId,
node::{Binary, BinaryOp, NodeId, ObjectType, Operation, Variable},
value::Value,
{block, builtin, node, ssa_form},
};
use crate::{errors, errors::RuntimeError};
Expand Down Expand Up @@ -31,92 +32,6 @@ pub struct IRGenerator {
pub program: Program,
}

#[derive(Debug, Clone)]
pub enum Value {
Single(NodeId),
Tuple(Vec<Value>),
}

impl Value {
pub fn unwrap_id(&self) -> NodeId {
match self {
Value::Single(id) => *id,
Value::Tuple(_) => panic!("Tried to unwrap a struct into a single value"),
}
}

pub fn dummy() -> Value {
Value::Single(NodeId::dummy())
}

pub fn is_dummy(&self) -> bool {
match self {
Value::Single(id) => *id == NodeId::dummy(),
_ => false,
}
}

pub fn to_node_ids(&self) -> Vec<NodeId> {
match self {
Value::Single(id) => vec![*id],
Value::Tuple(v) => v.iter().flat_map(|i| i.to_node_ids()).collect(),
}
}

pub fn zip<F>(&self, v2: &Value, f: &mut F) -> Value
where
F: FnMut(NodeId, NodeId) -> NodeId,
{
if self.is_dummy() || v2.is_dummy() {
return Value::dummy();
}

match (self, v2) {
(Value::Single(id1), Value::Single(id2)) => Value::Single(f(*id1, *id2)),
(Value::Tuple(tup1), Value::Tuple(tup2)) => {
Value::Tuple(vecmap(tup1.iter().zip(tup2), |(v1, v2)| v1.zip(v2, f)))
}
_ => unreachable!(),
}
}

pub fn into_field_member(self, field_index: usize) -> Value {
match self {
Value::Single(_) => {
unreachable!("Runtime type error, expected struct but found a single value")
}
Value::Tuple(mut fields) => fields.remove(field_index),
}
}

pub fn get_field_member(&self, field_index: usize) -> &Value {
match self {
Value::Single(_) => {
unreachable!("Runtime type error, expected struct but found a single value")
}
Value::Tuple(fields) => &fields[field_index],
}
}

//Reconstruct a value whose type is provided in argument, from a bunch of NodeIds
fn reshape(value_type: &Type, iter: &mut core::slice::Iter<NodeId>) -> Value {
match value_type {
Type::Tuple(tup) => {
let values = vecmap(tup, |v| Self::reshape(v, iter));
Value::Tuple(values)
}
_ => Value::Single(*iter.next().unwrap()),
}
}

fn from_slice(value_type: &Type, slice: &[NodeId]) -> Value {
let mut iter = slice.iter();
let result = Value::reshape(value_type, &mut iter);
assert!(iter.next().is_none());
result
}
}

impl IRGenerator {
pub fn new(program: Program) -> IRGenerator {
IRGenerator {
Expand Down
1 change: 1 addition & 0 deletions crates/noirc_evaluator/src/ssa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ pub mod mem;
pub mod node;
pub mod optimizations;
pub mod ssa_form;
mod value;
115 changes: 115 additions & 0 deletions crates/noirc_evaluator/src/ssa/value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
use crate::ssa::node::NodeId;
use iter_extended::vecmap;
use noirc_frontend::monomorphization::ast::Type;

/// A `Value` is the descriptor used for items in the SSA IR.
/// A `Value` can hold a `NodeId` which by proxy means that
/// it represents Variables, Constants, Functions and Instructions.
#[derive(Debug, Clone)]
pub enum Value {
Single(NodeId),
Tuple(Vec<Value>),
}

impl Value {
/// Returns a single NodeId.
/// Panics: If `Value` holds multiple Values
pub fn unwrap_id(&self) -> NodeId {
match self {
Value::Single(id) => *id,
Value::Tuple(_) => panic!("Tried to unwrap a struct into a single value"),
}
}

/// Returns a placeholder NodeId that can
/// be used to represent the absence of a value.
pub fn dummy() -> Value {
Value::Single(NodeId::dummy())
}

/// Checks if the `Value` corresponds to
/// `Option::None` or no value.
pub fn is_dummy(&self) -> bool {
match self {
Value::Single(id) => *id == NodeId::dummy(),
_ => false,
}
}

/// Converts `Value` into a vector of NodeId's
pub fn to_node_ids(&self) -> Vec<NodeId> {
match self {
Value::Single(id) => vec![*id],
Value::Tuple(v) => v.iter().flat_map(|i| i.to_node_ids()).collect(),
}
}

/// Calls the function `f` on `self` and the given `Value`
/// Panics: If `self` and the given value are not the same
/// enum variant
pub fn zip<F>(&self, rhs_value: &Value, f: &mut F) -> Value
where
F: FnMut(NodeId, NodeId) -> NodeId,
{
if self.is_dummy() || rhs_value.is_dummy() {
return Value::dummy();
}

match (self, rhs_value) {
(Value::Single(lhs), Value::Single(rhs)) => Value::Single(f(*lhs, *rhs)),
(Value::Tuple(lhs), Value::Tuple(rhs)) => {
Value::Tuple(vecmap(lhs.iter().zip(rhs), |(lhs_value, rhs_value)| {
lhs_value.zip(rhs_value, f)
}))
}
_ => {
unreachable!("ICE: expected both `Value` instances to be of the same enum variant")
}
}
}

/// Returns the `Value` at position `field_index` in the
/// Tuple Variant.
/// Panics: If the `self` is not the `Tuple` Variant.
pub fn into_field_member(self, field_index: usize) -> Value {
match self {
Value::Single(_) => {
unreachable!("Runtime type error, expected struct but found a single value")
}
Value::Tuple(mut fields) => fields.remove(field_index),
}
}
pub fn get_field_member(&self, field_index: usize) -> &Value {
match self {
Value::Single(_) => {
unreachable!("Runtime type error, expected struct but found a single value")
}
Value::Tuple(fields) => &fields[field_index],
}
}

/// Reconstruct a `Value` instance whose type is `value_type`
fn reshape(value_type: &Type, iter: &mut core::slice::Iter<NodeId>) -> Value {
match value_type {
Type::Tuple(tup) => {
let values = vecmap(tup, |v| Self::reshape(v, iter));
Value::Tuple(values)
}
Type::Unit
| Type::Function(..)
| Type::Array(..)
| Type::String(..)
| Type::Integer(..)
| Type::Bool
| Type::Field => Value::Single(*iter.next().unwrap()),
}
}

/// Reconstruct a `Value` instance from a slice of NodeId's
pub(crate) fn from_slice(value_type: &Type, slice: &[NodeId]) -> Value {
let mut iter = slice.iter();
let result = Value::reshape(value_type, &mut iter);
assert!(iter.next().is_none());
result
}
}

0 comments on commit cd78b1b

Please sign in to comment.