Skip to content

Commit

Permalink
Parse dynamic error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
asterite committed Nov 22, 2024
1 parent 1d403cc commit 74ca9d1
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 6 deletions.
3 changes: 2 additions & 1 deletion compiler/noirc_evaluator/src/ssa/parser/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ pub(crate) enum ParsedInstruction {

#[derive(Debug)]
pub(crate) enum AssertMessage {
String(String),
Static(String),
Dynamic(Vec<ParsedValue>),
}

#[derive(Debug)]
Expand Down
24 changes: 21 additions & 3 deletions compiler/noirc_evaluator/src/ssa/parser/into_ssa.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::collections::HashMap;

use acvm::acir::circuit::ErrorSelector;

use crate::ssa::{
function_builder::FunctionBuilder,
ir::{
Expand Down Expand Up @@ -34,6 +36,8 @@ struct Translator {
/// passes already which replaced some of the original IDs. The translator
/// will recreate the SSA step by step, which can result in a new ID layout.
variables: HashMap<FunctionId, HashMap<String, ValueId>>,

error_selector_counter: u64,
}

impl Translator {
Expand Down Expand Up @@ -67,8 +71,13 @@ impl Translator {
functions.insert(function.internal_name.clone(), function_id);
}

let mut translator =
Self { builder, functions, variables: HashMap::new(), blocks: HashMap::new() };
let mut translator = Self {
builder,
functions,
variables: HashMap::new(),
blocks: HashMap::new(),
error_selector_counter: 0,
};
translator.translate_function_body(main_function)?;

Ok(translator)
Expand Down Expand Up @@ -205,9 +214,18 @@ impl Translator {
let lhs = self.translate_value(lhs)?;
let rhs = self.translate_value(rhs)?;
let assert_message = match assert_message {
Some(AssertMessage::String(string)) => {
Some(AssertMessage::Static(string)) => {
Some(ConstrainError::StaticString(string))
}
Some(AssertMessage::Dynamic(values)) => {
let error_selector = ErrorSelector::new(self.error_selector_counter);
self.error_selector_counter += 1;

let is_string_type = false;
let values = self.translate_values(values)?;

Some(ConstrainError::Dynamic(error_selector, is_string_type, values))
}
None => None,
};
self.builder.insert_constrain(lhs, rhs, assert_message);
Expand Down
16 changes: 14 additions & 2 deletions compiler/noirc_evaluator/src/ssa/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,9 +316,11 @@ impl<'a> Parser<'a> {

let assert_message = if self.eat(Token::Comma)? {
if let Some(str) = self.eat_str()? {
Some(AssertMessage::String(str))
Some(AssertMessage::Static(str))
} else if self.eat_keyword(Keyword::Data)? {
Some(AssertMessage::Dynamic(self.parse_comma_separated_values()?))
} else {
todo!("Dynamic assert message")
return self.expected_string_or_data();
}
} else {
None
Expand Down Expand Up @@ -839,6 +841,13 @@ impl<'a> Parser<'a> {
})
}

fn expected_string_or_data<T>(&mut self) -> ParseResult<T> {
Err(ParserError::ExpectedStringOrData {
found: self.token.token().clone(),
span: self.token.to_span(),
})
}

fn expected_identifier<T>(&mut self) -> ParseResult<T> {
Err(ParserError::ExpectedIdentifier {
found: self.token.token().clone(),
Expand Down Expand Up @@ -900,6 +909,8 @@ pub(crate) enum ParserError {
ExpectedType { found: Token, span: Span },
#[error("Expected an instruction or terminator, found '{found}'")]
ExpectedInstructionOrTerminator { found: Token, span: Span },
#[error("Expected a string literal or 'data', found '{found}'")]
ExpectedStringOrData { found: Token, span: Span },
#[error("Expected a value, found '{found}'")]
ExpectedValue { found: Token, span: Span },
#[error("Multiple return values only allowed for call")]
Expand All @@ -916,6 +927,7 @@ impl ParserError {
| ParserError::ExpectedInt { span, .. }
| ParserError::ExpectedType { span, .. }
| ParserError::ExpectedInstructionOrTerminator { span, .. }
| ParserError::ExpectedStringOrData { span, .. }
| ParserError::ExpectedValue { span, .. } => *span,
ParserError::MultipleReturnValuesOnlyAllowedForCall { second_target, .. } => {
second_target.span
Expand Down
13 changes: 13 additions & 0 deletions compiler/noirc_evaluator/src/ssa/parser/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,19 @@ fn test_constrain_with_static_message() {
assert_ssa_roundtrip(src);
}

#[test]
fn test_constrain_with_dynamic_message() {
let src = "
acir(inline) fn main f0 {
b0(v0: Field, v1: Field):
v7 = make_array [u8 123, u8 120, u8 125, u8 32, u8 123, u8 121, u8 125] : [u8; 7]
constrain v0 == Field 1, data v7, u32 2, v0, v1
return
}
";
assert_ssa_roundtrip(src);
}

#[test]
fn test_enable_side_effects() {
let src = "
Expand Down
3 changes: 3 additions & 0 deletions compiler/noirc_evaluator/src/ssa/parser/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ pub(crate) enum Keyword {
Call,
Cast,
Constrain,
Data,
DecRc,
Div,
Inline,
Expand Down Expand Up @@ -178,6 +179,7 @@ impl Keyword {
"call" => Keyword::Call,
"cast" => Keyword::Cast,
"constrain" => Keyword::Constrain,
"data" => Keyword::Data,
"dec_rc" => Keyword::DecRc,
"div" => Keyword::Div,
"else" => Keyword::Else,
Expand Down Expand Up @@ -238,6 +240,7 @@ impl Display for Keyword {
Keyword::Call => write!(f, "call"),
Keyword::Cast => write!(f, "cast"),
Keyword::Constrain => write!(f, "constrain"),
Keyword::Data => write!(f, "data"),
Keyword::DecRc => write!(f, "dec_rc"),
Keyword::Div => write!(f, "div"),
Keyword::Else => write!(f, "else"),
Expand Down

0 comments on commit 74ca9d1

Please sign in to comment.