Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,12 @@ impl FunctionBuilder {
assert!(databus.databus.is_none(), "initializing finalized call data");
let typ = self.current_function.dfg[value].get_type().into_owned();
match typ {
Type::Numeric(_) => {
Type::Numeric(numeric_type) => {
let value = if matches!(numeric_type, NumericType::NativeField) {
value
} else {
self.insert_cast(value, NumericType::NativeField)
};
databus.values.push_back(value);
databus.index += 1;
}
Expand Down
13 changes: 13 additions & 0 deletions compiler/noirc_evaluator/src/ssa/interpreter/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,19 @@ pub enum InternalError {
actual_length: usize,
instruction: &'static str,
},
#[error(
"make_array with {elements_count} elements and {types_count} types but {elements_count} % {types_count} != 0"
)]
MakeArrayElementCountMismatch { result: ValueId, elements_count: usize, types_count: usize },
#[error(
"make_array element at index `{index}` has type `{actual_type}` but the expected type is `{expected_type}`"
)]
MakeArrayElementTypeMismatch {
result: ValueId,
index: usize,
expected_type: String,
actual_type: String,
},
#[error("Expected input to be `{expected_type}` for `{name}` but it was `{value}`")]
UnexpectedInput { name: &'static str, expected_type: &'static str, value: String },
#[error("Error parsing `{name}` into `{expected_type}` from `{value}`: {error}")]
Expand Down
47 changes: 39 additions & 8 deletions compiler/noirc_evaluator/src/ssa/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,11 @@ impl<'ssa, W: Write> Interpreter<'ssa, W> {
let actual_type = value.get_type();

if expected_type != actual_type {
return Err(InterpreterError::Internal(
InternalError::ValueTypeDoesNotMatchReturnType {
value_id: id,
expected_type: expected_type.to_string(),
actual_type: actual_type.to_string(),
},
));
return Err(internal(InternalError::ValueTypeDoesNotMatchReturnType {
value_id: id,
expected_type: expected_type.to_string(),
actual_type: actual_type.to_string(),
}));
}
}

Expand Down Expand Up @@ -1012,10 +1010,43 @@ impl<'ssa, W: Write> Interpreter<'ssa, W> {
let elements = try_vecmap(elements, |element| self.lookup(*element))?;
let is_slice = matches!(&result_type, Type::Slice(..));

// The number of elements in the array must be a multiple of the number of element types
let element_types = result_type.clone().element_types();
if element_types.is_empty() {
if !elements.is_empty() {
return Err(internal(InternalError::MakeArrayElementCountMismatch {
result,
elements_count: elements.len(),
types_count: element_types.len(),
}));
}
} else if elements.len() % element_types.len() != 0 {
return Err(internal(InternalError::MakeArrayElementCountMismatch {
result,
elements_count: elements.len(),
types_count: element_types.len(),
}));
}

// Make sure each element's type matches the one in element_types
for (index, (element, expected_type)) in
elements.iter().zip(element_types.iter().cycle()).enumerate()
{
let actual_type = element.get_type();
if &actual_type != expected_type {
return Err(internal(InternalError::MakeArrayElementTypeMismatch {
result,
index,
actual_type: actual_type.to_string(),
expected_type: expected_type.to_string(),
}));
}
}

let array = Value::ArrayOrSlice(ArrayValue {
elements: Shared::new(elements),
rc: Shared::new(1),
element_types: result_type.clone().element_types(),
element_types,
is_slice,
});
self.define(result, array)
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_evaluator/src/ssa/interpreter/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ impl NumericValue {
}
}

pub(crate) fn convert_to_field(&self) -> FieldElement {
pub fn convert_to_field(&self) -> FieldElement {
match self {
NumericValue::Field(field) => *field,
NumericValue::U1(boolean) if *boolean => FieldElement::one(),
Expand Down
18 changes: 10 additions & 8 deletions tooling/nargo_cli/src/cli/interpret_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use noirc_driver::{CompilationResult, CompileOptions, gen_abi};
use clap::Args;
use noirc_errors::CustomDiagnostic;
use noirc_evaluator::ssa::interpreter::InterpreterOptions;
use noirc_evaluator::ssa::interpreter::value::Value;
use noirc_evaluator::ssa::interpreter::value::{NumericValue, Value};
use noirc_evaluator::ssa::ir::types::{NumericType, Type};
use noirc_evaluator::ssa::ssa_gen::{Ssa, generate_ssa};
use noirc_evaluator::ssa::{SsaEvaluatorOptions, SsaLogging, primary_passes};
Expand Down Expand Up @@ -121,7 +121,7 @@ pub(crate) fn run(args: InterpretCommand, workspace: Workspace) -> Result<(), Cl
let ssa_return = ssa_return.map(|ssa_return| {
let main_function = &ssa.functions[&ssa.main_id];
if main_function.has_data_bus_return_data() {
let values = flatten_values(ssa_return);
let values = flatten_databus_values(ssa_return);
vec![Value::array(values, vec![Type::Numeric(NumericType::NativeField)])]
} else {
ssa_return
Expand Down Expand Up @@ -289,23 +289,25 @@ fn print_and_interpret_ssa(
interpret_ssa(passes_to_interpret, ssa, msg, args, return_value, interpreter_options)
}

fn flatten_values(values: Vec<Value>) -> Vec<Value> {
fn flatten_databus_values(values: Vec<Value>) -> Vec<Value> {
let mut flattened_values = Vec::new();
for value in values {
flatten_value(value, &mut flattened_values);
flatten_databus_value(value, &mut flattened_values);
}
flattened_values
}

fn flatten_value(value: Value, flattened_values: &mut Vec<Value>) {
fn flatten_databus_value(value: Value, flattened_values: &mut Vec<Value>) {
match value {
Value::ArrayOrSlice(array_value) => {
for value in array_value.elements.borrow().iter() {
flatten_value(value.clone(), flattened_values);
flatten_databus_value(value.clone(), flattened_values);
}
}
Value::Numeric(..)
| Value::Reference(..)
Value::Numeric(value) => {
flattened_values.push(Value::Numeric(NumericValue::Field(value.convert_to_field())));
}
Value::Reference(..)
| Value::Function(..)
| Value::Intrinsic(..)
| Value::ForeignFunction(..) => flattened_values.push(value),
Expand Down
Loading