Merge branch 'testnet3' into improve-parser-tests

This commit is contained in:
0rphon 2022-03-08 00:57:32 -08:00
commit 39ea7a3ceb
46 changed files with 327 additions and 648 deletions

12
Cargo.lock generated
View File

@ -240,9 +240,9 @@ dependencies = [
[[package]]
name = "clap"
version = "3.1.2"
version = "3.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5177fac1ab67102d8989464efd043c6ff44191b1557ec1ddd489b4f7e1447e77"
checksum = "ced1892c55c910c1219e98d6fc8d71f6bddba7905866ce740066d8bfea859312"
dependencies = [
"atty",
"bitflags",
@ -250,7 +250,7 @@ dependencies = [
"os_str_bytes",
"strsim 0.10.0",
"termcolor",
"textwrap 0.14.2",
"textwrap 0.15.0",
]
[[package]]
@ -1071,7 +1071,7 @@ version = "1.5.3"
dependencies = [
"ansi_term",
"assert_cmd",
"clap 3.1.2",
"clap 3.1.5",
"color-backtrace",
"colored",
"console",
@ -2220,9 +2220,9 @@ dependencies = [
[[package]]
name = "textwrap"
version = "0.14.2"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
[[package]]
name = "thiserror"

View File

@ -550,9 +550,7 @@ impl ReconstructingReducer for Canonicalizer {
for (index, character) in string.iter().enumerate() {
let col_start = span.col_start + index + 1 + col_adder; // account for open quote
let bytes = span.content.clone().into_bytes();
let col_stop: usize;
if bytes[col_start - 1] == b'\\' {
let col_stop = if bytes[col_start - 1] == b'\\' {
let mut width = 0;
match bytes[col_start] {
@ -569,10 +567,10 @@ impl ReconstructingReducer for Canonicalizer {
_ => width += 1,
}
col_adder += width;
col_stop = col_start + 1 + width;
col_start + 1 + width
} else {
col_stop = col_start + 1;
}
col_start + 1
};
elements.push(SpreadOrExpression::Expression(Expression::Value(
ValueExpression::Char(CharValue {

View File

@ -20,45 +20,12 @@ use serde::{ser::SerializeSeq, Deserialize, Serialize, Serializer};
use smallvec::{smallvec, SmallVec};
use std::{fmt, ops::Deref};
/// A single array dimension.
#[derive(Clone, Deserialize, Debug, PartialEq, Eq, Hash)]
pub enum Dimension {
/// The dimension is `_`, that is unspecified and syntactically unknown.
Unspecified,
/// The dimension was specified, e.g., `5` elements.
Number(PositiveNumber),
}
impl fmt::Display for Dimension {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Unspecified => write!(f, "_"),
Self::Number(num) => write!(f, "{}", num),
}
}
}
impl Dimension {
/// } Returns `Some(n)` unless the dimension is [`Unspecified`].
pub fn as_specified(&self) -> Option<&PositiveNumber> {
match self {
Self::Unspecified => None,
Self::Number(n) => Some(n),
}
}
/// Returns true if the dimension is known to be zero.
fn is_zero(&self) -> bool {
self.as_specified().filter(|n| n.is_zero()).is_some()
}
}
/// Specifies array dimensions for array [`Type`]s or in array initializer [`Expression`]s.
#[derive(Clone, Deserialize, Debug, PartialEq, Eq, Hash)]
pub struct ArrayDimensions(pub SmallVec<[Dimension; 1]>);
pub struct ArrayDimensions(pub SmallVec<[PositiveNumber; 1]>);
impl Deref for ArrayDimensions {
type Target = [Dimension];
type Target = [PositiveNumber];
fn deref(&self) -> &Self::Target {
&*self.0
@ -67,22 +34,17 @@ impl Deref for ArrayDimensions {
impl ArrayDimensions {
/// Returns a single-dimensional array dimension.
pub fn single(dim: Dimension) -> Self {
pub fn single(dim: PositiveNumber) -> Self {
Self(smallvec![dim])
}
/// Returns true if the dimensions are not [`Unspecified`].
pub fn is_specified(&self) -> bool {
!self.contains(&Dimension::Unspecified)
}
/// Returns `true` if there is an array dimension equal to zero.
pub fn is_zero(&self) -> bool {
self.iter().any(|d| d.is_zero())
}
/// Attempts to remove the first dimension from the array, or returns `None` if it doesn't.
pub fn remove_first(&mut self) -> Option<Dimension> {
pub fn remove_first(&mut self) -> Option<PositiveNumber> {
if self.is_empty() {
None
} else {
@ -91,12 +53,12 @@ impl ArrayDimensions {
}
/// Attempts to remove the last dimension from the array, or returns `None` if it doesn't.
pub fn remove_last(&mut self) -> Option<Dimension> {
pub fn remove_last(&mut self) -> Option<PositiveNumber> {
self.0.pop()
}
}
/// Custom Serializer for ArrayDimensios is required to ignore internal ArrayDimension nodes in the AST.
/// Custom Serializer for ArrayDimensions is required to ignore internal ArrayDimension nodes in the AST.
impl Serialize for ArrayDimensions {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -104,10 +66,7 @@ impl Serialize for ArrayDimensions {
{
let mut seq = serializer.serialize_seq(Some(self.0.len()))?;
for dim in self.0.iter() {
match dim {
Dimension::Number(num) => seq.serialize_element(&num)?,
Dimension::Unspecified => seq.serialize_element(&PositiveNumber { value: "0".into() })?,
}
seq.serialize_element(&dim)?;
}
seq.end()
}

View File

@ -88,32 +88,28 @@ impl TryFrom<(Type, Expression)> for InputValue {
}
if let Some(dimension) = array_init.dimensions.remove_first() {
if let Some(number) = dimension.as_specified() {
let size = number.value.parse::<usize>().unwrap();
let mut values = Vec::with_capacity(size);
let size = dimension.value.parse::<usize>().unwrap();
let mut values = Vec::with_capacity(size);
// For when Dimensions are specified in a canonical way: [[u8; 3], 2];
// Else treat as math notation: [u8; (2, 3)];
if array_init.dimensions.len() == 0 {
for _ in 0..size {
values.push(InputValue::try_from((*type_.clone(), *array_init.element.clone()))?);
}
// Faking canonical array init is relatively easy: instead of using a straightforward
// recursion, with each iteration we manually modify ArrayInitExpression cutting off
// dimension by dimension.
} else {
for _ in 0..size {
values.push(InputValue::try_from((
Type::Array(type_.clone(), array_init.dimensions.clone()),
Expression::ArrayInit(array_init.clone()),
))?);
}
};
Self::Array(values)
// For when Dimensions are specified in a canonical way: [[u8; 3], 2];
// Else treat as math notation: [u8; (2, 3)];
if array_init.dimensions.len() == 0 {
for _ in 0..size {
values.push(InputValue::try_from((*type_.clone(), *array_init.element.clone()))?);
}
// Faking canonical array init is relatively easy: instead of using a straightforward
// recursion, with each iteration we manually modify ArrayInitExpression cutting off
// dimension by dimension.
} else {
unreachable!("dimensions must be specified");
}
for _ in 0..size {
values.push(InputValue::try_from((
Type::Array(type_.clone(), array_init.dimensions.clone()),
Expression::ArrayInit(array_init.clone()),
))?);
}
};
Self::Array(values)
} else {
unreachable!("dimensions are checked for zero");
}
@ -132,14 +128,10 @@ impl TryFrom<(Type, Expression)> for InputValue {
Self::Tuple(elements)
}
(Type::Array(element_type, dimensions), Expression::ArrayInline(array_inline)) => {
(Type::Array(element_type, _dimensions), Expression::ArrayInline(array_inline)) => {
let mut elements = Vec::with_capacity(array_inline.elements.len());
let span = array_inline.span().clone();
if !dimensions.is_specified() {
return Err(InputError::array_dimensions_must_be_specified(&span).into());
}
for element in array_inline.elements.into_iter() {
if let SpreadOrExpression::Expression(value_expression) = element {
elements.push(Self::try_from((*element_type.clone(), value_expression))?);

View File

@ -89,11 +89,6 @@ impl Type {
let mut left_dims = left_dims.to_owned();
let mut right_dims = right_dims.to_owned();
// Unable to compare arrays with unspecified sizes.
if !left_dims.is_specified() || !right_dims.is_specified() {
return false;
}
// Remove the first element from both dimensions.
let left_first = left_dims.remove_first();
let right_first = right_dims.remove_first();

View File

@ -82,7 +82,7 @@ impl<'a> Compiler<'a> {
program_string,
)?;
// Write the AST snapshot post parsing.
ast.to_json_file_without_keys(self.output_directory.clone(), "inital_ast.json", &["span"])?;
ast.to_json_file_without_keys(self.output_directory.clone(), "initial_ast.json", &["span"])?;
// Canonicalize the AST.
ast = leo_ast_passes::Canonicalizer::do_pass(Default::default(), ast.into_repr())?;

View File

@ -114,11 +114,9 @@ impl ParserContext<'_> {
let (args, _, span) = self.parse_paren_comma_list(|p| {
Ok(if let Some(ident) = p.eat_identifier() {
Some(ident.name)
} else if let Some((int, _)) = p.eat_int() {
Some(Symbol::intern(&int.value))
} else {
let token = p.expect_any()?;
p.emit_err(ParserError::unexpected_str(&token.token, "ident or int", &token.span));
p.emit_err(ParserError::unexpected_str(&token.token, "ident", &token.span));
None
})
})?;
@ -363,7 +361,7 @@ impl ParserContext<'_> {
///
/// Returns a [`FunctionInput`] AST node if the next tokens represent a function parameter.
///
pub fn parse_function_parameters(&mut self) -> Result<FunctionInput> {
pub fn parse_function_parameters(&mut self, first: bool) -> Result<FunctionInput> {
let const_ = self.eat(Token::Const);
let mutable = self.eat(Token::Mut);
let reference = self.eat(Token::Ampersand);
@ -376,7 +374,9 @@ impl ParserContext<'_> {
self.expect_ident()?
};
if name.name == sym::SelfLower {
if let Some(mutable) = &mutable {
if !first {
return Err(ParserError::parser_self_outside_first_argument().into());
} else if let Some(mutable) = &mutable {
self.emit_err(ParserError::mut_self_parameter(&(&mutable.span + &name.span)));
return Ok(Self::build_ref_self(name, mutable));
} else if let Some(reference) = &reference {
@ -433,7 +433,12 @@ impl ParserContext<'_> {
let name = self.expect_ident()?;
// Parse parameters.
let (inputs, ..) = self.parse_paren_comma_list(|p| p.parse_function_parameters().map(Some))?;
let mut first = true;
let (inputs, ..) = self.parse_paren_comma_list(|p| {
let param = p.parse_function_parameters(first).map(Some);
first = false;
param
})?;
// Parse return type.
let output = if self.eat(Token::Arrow).is_some() {

View File

@ -59,12 +59,12 @@ impl ParserContext<'_> {
/// Returns an [`ArrayDimensions`] AST node if the next tokens represent dimensions for an array type.
pub fn parse_array_dimensions(&mut self) -> Result<ArrayDimensions> {
Ok(if let Some(dim) = self.parse_array_dimension() {
Ok(if let Some((dim, _)) = self.eat_int() {
ArrayDimensions(smallvec![dim])
} else {
let mut had_item_err = false;
let (dims, _, span) = self.parse_paren_comma_list(|p| {
Ok(if let Some(dim) = p.parse_array_dimension() {
Ok(if let Some((dim, _)) = p.eat_int() {
Some(dim)
} else {
let token = p.expect_any()?;
@ -80,17 +80,6 @@ impl ParserContext<'_> {
})
}
/// Parses a basic array dimension, i.e., an integer or `_`.
fn parse_array_dimension(&mut self) -> Option<Dimension> {
if let Some((int, _)) = self.eat_int() {
Some(Dimension::Number(int))
} else if self.eat(Token::Underscore).is_some() {
Some(Dimension::Unspecified)
} else {
None
}
}
/// Returns a [`(Type, Span)`] tuple of AST nodes if the next token represents a type.
/// Also returns the span of the parsed token.
pub fn parse_type(&mut self) -> Result<(Type, Span)> {

View File

@ -63,9 +63,9 @@ impl Token {
///
/// Returns a `char` if a character can be eaten, otherwise returns [`None`].
///
fn eat_char(input_tendril: StrTendril, escaped: bool, hex: bool, unicode: bool) -> Option<Char> {
fn eat_char(input_tendril: StrTendril, escaped: bool, hex: bool, unicode: bool) -> Result<Char> {
if input_tendril.is_empty() {
return None;
return Err(ParserError::lexer_empty_input_tendril().into());
}
if escaped {
@ -73,19 +73,21 @@ impl Token {
let escaped = &string[1..string.len()];
if escaped.len() != 1 {
return None;
} else {
return match escaped.chars().next().unwrap() {
'0' => Some(Char::Scalar(0 as char)),
't' => Some(Char::Scalar(9 as char)),
'n' => Some(Char::Scalar(10 as char)),
'r' => Some(Char::Scalar(13 as char)),
'\"' => Some(Char::Scalar(34 as char)),
'\'' => Some(Char::Scalar(39 as char)),
'\\' => Some(Char::Scalar(92 as char)),
_ => None,
return Err(ParserError::lexer_escaped_char_incorrect_length(escaped).into());
} else if let Some(character) = escaped.chars().next() {
return match character {
'0' => Ok(Char::Scalar(0 as char)),
't' => Ok(Char::Scalar(9 as char)),
'n' => Ok(Char::Scalar(10 as char)),
'r' => Ok(Char::Scalar(13 as char)),
'\"' => Ok(Char::Scalar(34 as char)),
'\'' => Ok(Char::Scalar(39 as char)),
'\\' => Ok(Char::Scalar(92 as char)),
_ => return Err(ParserError::lexer_expected_valid_escaped_char(character).into()),
};
};
} else {
return Err(ParserError::lexer_unclosed_escaped_char().into());
}
}
if hex {
@ -93,46 +95,50 @@ impl Token {
let hex_string = &string[2..string.len()];
if hex_string.len() != 2 {
return None;
return Err(ParserError::lexer_escaped_hex_incorrect_length(hex_string).into());
} else if let Ok(ascii_number) = u8::from_str_radix(hex_string, 16) {
// According to RFC, we allow only values less than 128.
if ascii_number > 127 {
return None;
return Err(ParserError::lexer_expected_valid_hex_char(ascii_number).into());
} else {
return Some(Char::Scalar(ascii_number as char));
return Ok(Char::Scalar(ascii_number as char));
}
}
}
if unicode {
let string = input_tendril.to_string();
if &string[string.len() - 1..] != "}" {
return None;
if string.find('}').is_none() {
return Err(ParserError::lexer_unclosed_escaped_unicode_char(string).into());
}
let unicode_number = &string[3..string.len() - 1];
let len = unicode_number.len();
if !(1..=6).contains(&len) {
return None;
return Err(ParserError::lexer_invalid_escaped_unicode_length(unicode_number).into());
} else if let Ok(hex) = u32::from_str_radix(unicode_number, 16) {
if let Some(character) = std::char::from_u32(hex) {
// scalar
return Some(Char::Scalar(character));
return Ok(Char::Scalar(character));
} else if hex <= 0x10FFFF {
return Some(Char::NonScalar(hex));
return Ok(Char::NonScalar(hex));
} else {
return Err(ParserError::lexer_invalid_character_exceeded_max_value(unicode_number).into());
}
}
}
if input_tendril.to_string().chars().count() != 1 {
return None;
// If char doesn't close.
return Err(ParserError::lexer_char_not_closed(&input_tendril[0..]).into());
} else if let Some(character) = input_tendril.to_string().chars().next() {
return Some(Char::Scalar(character));
// If its a simple char.
return Ok(Char::Scalar(character));
}
// 0rphon: should be impossible to hit if function is used correctly
panic!();
None
Err(ParserError::lexer_invalid_char(input_tendril.to_string()).into())
}
///
@ -150,18 +156,12 @@ impl Token {
return Err(ParserError::lexer_eat_integer_leading_zero(String::from_utf8_lossy(input)).into());
}
let mut i = 1;
let mut is_hex = false;
while i < input.len() {
if i == 1 && input[0] == b'0' && input[i] == b'x' {
is_hex = true;
i += 1;
continue;
return Err(ParserError::lexer_hex_number_provided(&input_tendril[0..3]).into());
}
if is_hex {
if !input[i].is_ascii_hexdigit() {
break;
}
} else if !input[i].is_ascii_digit() {
if !input[i].is_ascii_digit() {
break;
}
@ -171,7 +171,7 @@ impl Token {
}
/// Returns the number of bytes in an emoji via a bit mask.
fn utf8_byte_count(byte: u8) -> u8 {
fn utf8_byte_count(byte: u8) -> usize {
let mut mask = 0x80;
let mut result = 0;
while byte & mask > 0 {
@ -204,7 +204,7 @@ impl Token {
x if x.is_ascii_whitespace() => return Ok((1, Token::WhiteSpace)),
b'"' => {
let mut i = 1;
let mut len: u8 = 1;
let mut len = 1;
let mut start = 1;
let mut in_escape = false;
let mut escaped = false;
@ -217,7 +217,7 @@ impl Token {
// If it's an emoji get the length.
if input[i] & 0x80 > 0 {
len = Self::utf8_byte_count(input[i]);
i += (len as usize) - 1;
i += len - 1;
}
if !in_escape {
@ -255,26 +255,17 @@ impl Token {
}
if !in_escape {
match Self::eat_char(
let character = Self::eat_char(
input_tendril.subtendril(start as u32, len as u32),
escaped,
hex,
unicode,
) {
Some(character) => {
len = 1;
escaped = false;
hex = false;
unicode = false;
string.push(character.into());
}
None => {
return Err(ParserError::lexer_expected_valid_escaped_char(
input_tendril.subtendril(start as u32, len as u32),
)
.into())
}
}
)?;
len = 1;
escaped = false;
hex = false;
unicode = false;
string.push(character.into());
}
i += 1;
@ -295,14 +286,27 @@ impl Token {
let mut in_escape = false;
let mut escaped = false;
let mut hex = false;
let mut unicode = false;
let mut escaped_unicode = false;
let mut unicode_char = false;
let mut end = false;
while i < input.len() {
if !in_escape {
if input[i] & 0x80 > 0 && !unicode_char {
i += Self::utf8_byte_count(input[i]);
unicode_char = true;
continue;
} else if input[i] & 0x80 > 0 && unicode_char {
i += Self::utf8_byte_count(input[i]);
return Err(ParserError::lexer_invalid_char(&input_tendril[0..i]).into());
} else if !in_escape || unicode_char {
if input[i] == b'\'' {
end = true;
break;
} else if unicode_char {
return Err(ParserError::lexer_invalid_char(
&input_tendril[0..input_tendril[1..].find('\'').unwrap_or(i + 1)],
)
.into());
} else if input[i] == b'\\' {
in_escape = true;
}
@ -311,7 +315,7 @@ impl Token {
hex = true;
} else if input[i] == b'u' {
if input[i + 1] == b'{' {
unicode = true;
escaped_unicode = true;
} else {
return Err(ParserError::lexer_expected_valid_escaped_char(input[i]).into());
}
@ -329,10 +333,13 @@ impl Token {
return Err(ParserError::lexer_char_not_closed(String::from_utf8_lossy(&input[0..i])).into());
}
return match Self::eat_char(input_tendril.subtendril(1, (i - 1) as u32), escaped, hex, unicode) {
Some(character) => Ok((i + 1, Token::CharLit(character))),
None => Err(ParserError::lexer_invalid_char(String::from_utf8_lossy(&input[0..i - 1])).into()),
};
let character = Self::eat_char(
input_tendril.subtendril(1, (i - 1) as u32),
escaped,
hex,
escaped_unicode,
)?;
return Ok((i + 1, Token::CharLit(character)));
}
x if x.is_ascii_digit() => {
return Self::eat_integer(&input_tendril);

View File

@ -58,7 +58,7 @@ pub(crate) fn tokenize(path: &str, input: StrTendril) -> Result<Vec<SpannedToken
path,
input.subtendril(
line_start as u32,
input[line_start..].find('\n').unwrap_or_else(|| input.len()) as u32,
input[line_start..].find('\n').unwrap_or(input.len()) as u32,
),
),
)

View File

@ -654,16 +654,6 @@ integer = [ "-" ] natural
Go to: _[natural](#user-content-natural)_;
An untyped literal is just an integer.
<a name="untyped-literal"></a>
```abnf
untyped-literal = integer
```
Go to: _[integer](#user-content-integer)_;
Unsigned literals are naturals followed by unsigned types.
<a name="unsigned-literal"></a>
@ -849,8 +839,7 @@ as defined by the following rule.
<a name="atomic-literal"></a>
```abnf
atomic-literal = untyped-literal
/ unsigned-literal
atomic-literal = unsigned-literal
/ signed-literal
/ field-literal
/ product-group-literal
@ -860,7 +849,7 @@ atomic-literal = untyped-literal
/ string-literal
```
Go to: _[address-literal](#user-content-address-literal), [boolean-literal](#user-content-boolean-literal), [character-literal](#user-content-character-literal), [field-literal](#user-content-field-literal), [product-group-literal](#user-content-product-group-literal), [signed-literal](#user-content-signed-literal), [string-literal](#user-content-string-literal), [unsigned-literal](#user-content-unsigned-literal), [untyped-literal](#user-content-untyped-literal)_;
Go to: _[address-literal](#user-content-address-literal), [boolean-literal](#user-content-boolean-literal), [character-literal](#user-content-character-literal), [field-literal](#user-content-field-literal), [product-group-literal](#user-content-product-group-literal), [signed-literal](#user-content-signed-literal), [string-literal](#user-content-string-literal), [unsigned-literal](#user-content-unsigned-literal)_;
After defining the (mostly) alphanumeric tokens above,
@ -1013,34 +1002,24 @@ An array type consists of an element type
and an indication of dimensions.
There is either a single dimension,
or a tuple of one or more dimensions.
Each dimension is either a natural or is unspecified.
Each dimension is a natural.
<a name="array-type"></a>
```abnf
array-type = "[" type ";" array-type-dimensions "]"
array-type = "[" type ";" array-dimensions "]"
```
Go to: _[array-type-dimensions](#user-content-array-type-dimensions), [type](#user-content-type)_;
Go to: _[array-dimensions](#user-content-array-dimensions), [type](#user-content-type)_;
<a name="array-type-dimension"></a>
<a name="array-dimensions"></a>
```abnf
array-type-dimension = natural / "_"
array-dimensions = natural / "(" natural *( "," natural ) ")"
```
Go to: _[natural](#user-content-natural)_;
<a name="array-type-dimensions"></a>
```abnf
array-type-dimensions = array-type-dimension
/ "(" array-type-dimension
*( "," array-type-dimension ) [","] ")"
```
Go to: _[array-type-dimension](#user-content-array-type-dimension)_;
The keyword `Self` denotes the enclosing circuit type.
It is only allowed inside a circuit type declaration.
@ -1214,19 +1193,10 @@ Go to: _[expression](#user-content-expression)_;
<a name="array-repeat-construction"></a>
```abnf
array-repeat-construction = "[" expression ";" array-expression-dimensions "]"
array-repeat-construction = "[" expression ";" array-dimensions "]"
```
Go to: _[array-expression-dimensions](#user-content-array-expression-dimensions), [expression](#user-content-expression)_;
<a name="array-expression-dimensions"></a>
```abnf
array-expression-dimensions = natural
/ "(" natural *( "," natural ) ")"
```
Go to: _[natural](#user-content-natural)_;
Go to: _[array-dimensions](#user-content-array-dimensions), [expression](#user-content-expression)_;
<a name="array-construction"></a>
@ -1511,7 +1481,7 @@ and just one initializing expression.
<a name="variable-declaration"></a>
```abnf
variable-declaration = %s"let" identifier-or-identifiers [ ":" type ]
variable-declaration = %s"let" identifier-or-identifiers ":" type
"=" expression ";"
```
@ -1520,7 +1490,7 @@ Go to: _[expression](#user-content-expression), [identifier-or-identifiers](#use
<a name="constant-declaration"></a>
```abnf
constant-declaration = %s"const" identifier-or-identifiers [ ":" type ]
constant-declaration = %s"const" identifier-or-identifiers ":" type
"=" expression ";"
```
@ -1566,11 +1536,12 @@ The body is a block.
<a name="loop-statement"></a>
```abnf
loop-statement = %s"for" identifier %s"in" expression ".." [ "=" ] expression
loop-statement = %s"for" identifier ":" type
%s"in" expression ".." [ "=" ] expression
block
```
Go to: _[block](#user-content-block), [expression](#user-content-expression), [identifier](#user-content-identifier)_;
Go to: _[block](#user-content-block), [expression](#user-content-expression), [identifier](#user-content-identifier), [type](#user-content-type)_;
An assignment statement is straightforward.

View File

@ -461,10 +461,6 @@ natural = 1*decimal-digit
integer = [ "-" ] natural
; An untyped literal is just an integer.
untyped-literal = integer
; Unsigned literals are naturals followed by unsigned types.
unsigned-literal = natural ( %s"u8" / %s"u16" / %s"u32" / %s"u64" / %s"u128" )
@ -552,8 +548,7 @@ string-literal-element = not-double-quote-or-backslash
; (in the sense that they are tokens, without whitespace allowed in them),
; as defined by the following rule.
atomic-literal = untyped-literal
/ unsigned-literal
atomic-literal = unsigned-literal
/ signed-literal
/ field-literal
/ product-group-literal
@ -650,15 +645,11 @@ tuple-type = "(" [ type 1*( "," type ) ] ")"
; and an indication of dimensions.
; There is either a single dimension,
; or a tuple of one or more dimensions.
; Each dimension is either a natural or is unspecified.
; Each dimension is a natural.
array-type = "[" type ";" array-type-dimensions "]"
array-type = "[" type ";" array-dimensions "]"
array-type-dimension = natural / "_"
array-type-dimensions = array-type-dimension
/ "(" array-type-dimension
*( "," array-type-dimension ) [","] ")"
array-dimensions = natural / "(" natural *( "," natural ) ")"
; The keyword `Self` denotes the enclosing circuit type.
; It is only allowed inside a circuit type declaration.
@ -756,10 +747,7 @@ array-inline-construction = "["
array-inline-element = expression / "..." expression
array-repeat-construction = "[" expression ";" array-expression-dimensions "]"
array-expression-dimensions = natural
/ "(" natural *( "," natural ) ")"
array-repeat-construction = "[" expression ";" array-dimensions "]"
array-construction = array-inline-construction / array-repeat-construction
@ -918,10 +906,10 @@ return-statement = %s"return" expression ";"
; in all cases, there is just one optional type
; and just one initializing expression.
variable-declaration = %s"let" identifier-or-identifiers [ ":" type ]
variable-declaration = %s"let" identifier-or-identifiers ":" type
"=" expression ";"
constant-declaration = %s"const" identifier-or-identifiers [ ":" type ]
constant-declaration = %s"const" identifier-or-identifiers ":" type
"=" expression ";"
identifier-or-identifiers = identifier
@ -943,7 +931,8 @@ conditional-statement = branch
; that goes from a starting value (inclusive) to an ending value (exclusive).
; The body is a block.
loop-statement = %s"for" identifier %s"in" expression ".." [ "=" ] expression
loop-statement = %s"for" identifier ":" type
%s"in" expression ".." [ "=" ] expression
block
; An assignment statement is straightforward.

View File

@ -1,6 +1,5 @@
[main]
a: u32 = 1;
b: u32 = 2;
y: bool = true;
[registers]
r0: u32 = 0;
r0: bool = false;

View File

@ -1,5 +1,11 @@
// The 'hello-world' main function.
function main(a: u32, b: u32) -> u32 {
let c: u32 = a + b;
return c;
type str = [char; _];
function main(y: bool) -> bool {
let s = "abc";
return (first_el(s) == 'a') == y;
}
function first_el(s: str) -> char {
return s[0];
}

View File

@ -312,12 +312,4 @@ create_errors!(
msg: format!("Tried to assign to static member `{}`", member),
help: None,
}
/// For when arrays with unspecified size are used in main.
@formatted
input_array_size_must_be_specified {
args: (),
msg: "arrays in main function input must have known size",
help: None,
}
);

View File

@ -46,14 +46,6 @@ create_errors!(
help: None,
}
/// For when [`ArrayDimensions`] are not specified.
@formatted
array_dimensions_must_be_specified {
args: (),
msg: "array dimensions must be specified",
help: None,
}
/// For when array init is using spread.
@formatted
array_spread_is_not_allowed {

View File

@ -236,23 +236,23 @@ create_errors!(
@backtraced
lexer_eat_integer_leading_zero {
args: (input: impl Display),
msg: format!("Tried to eat integer but found a leading zero on {}.", input),
msg: format!("Tried to eat integer but found a leading zero on `{}`.", input),
help: None,
}
/// When an integer is started with a leading zero.
@backtraced
lexer_expected_valid_escaped_char {
lexer_expected_valid_escaped_char {
args: (input: impl Display),
msg: format!("Expected a valid escape character but found {}.", input),
msg: format!("Expected a valid escape character but found `{}`.", input),
help: None,
}
}
/// When a string is not properly closed.
@backtraced
lexer_string_not_closed {
args: (input: impl Display),
msg: format!("Expected a closed string but found {}.", input),
msg: format!("Expected a closed string but found `{}`.", input),
help: None,
}
@ -260,7 +260,7 @@ create_errors!(
@backtraced
lexer_char_not_closed {
args: (input: impl Display),
msg: format!("Expected a closed char but found {}.", input),
msg: format!("Expected a closed char but found `{}`.", input),
help: None,
}
@ -268,7 +268,7 @@ create_errors!(
@backtraced
lexer_invalid_char {
args: (input: impl Display),
msg: format!("Expected valid character but found {}.", input),
msg: format!("Expected valid character but found `{}`.", input),
help: None,
}
@ -284,7 +284,7 @@ create_errors!(
@backtraced
lexer_block_comment_does_not_close_before_eof {
args: (input: impl Display),
msg: format!("Block comment does not close with content: {}.", input),
msg: format!("Block comment does not close with content: `{}`.", input),
help: None,
}
@ -292,7 +292,78 @@ create_errors!(
@backtraced
could_not_lex {
args: (input: impl Display),
msg: format!("Could not lex the following content: {}.", input),
msg: format!("Could not lex the following content: `{}`.", input),
help: None,
}
/// When a escaped character was given more than one char to escape.
@backtraced
lexer_escaped_char_incorrect_length {
args: (input: impl Display),
msg: format!("Could not lex the following escaped char due to being given more than one char: `{}`.", input),
help: None,
}
/// When a escape was given but no following character
@backtraced
lexer_unclosed_escaped_char {
args: (),
msg: "There was no escaped character following the escape char symbol `\\`.",
help: None,
}
/// When a escaped hex was given more than two chars to escape.
@backtraced
lexer_escaped_hex_incorrect_length {
args: (input: impl Display),
msg: format!("Could not lex the following escaped hex due to being given more than two chars: `{}`.", input),
help: None,
}
/// When a valid hex character was expected.
@backtraced
lexer_expected_valid_hex_char {
args: (input: impl Display),
msg: format!("Expected a valid hex character but found `{}`.", input),
help: None,
}
/// When a escaped unicode char was given but no following closing symbol.
@backtraced
lexer_unclosed_escaped_unicode_char {
args: (input: impl Display),
msg: format!("There was no closing `}}` after a escaped unicode `{}`.", input),
help: None,
}
/// When a escaped unicode char was given but it had an incorrect length.
@backtraced
lexer_invalid_escaped_unicode_length {
args: (input: impl Display),
msg: format!("The escaped unicode char `{}` is not within valid length of [1, 6].", input),
help: None,
}
/// When a escaped unicode char was given but exceeded maximum value.
@backtraced
lexer_invalid_character_exceeded_max_value {
args: (input: impl Display),
msg: format!("The escaped unicode char `{}` is greater than 0x10FFFF.", input),
help: None,
}
/// When a hex number is provided.
@backtraced
lexer_hex_number_provided {
args: (input: impl Display),
msg: format!("A hex number `{}..` was provided but hex is not allowed.", input),
help: None,
}
/// When a function recieved a self argument outside the first argument.
@backtraced
parser_self_outside_first_argument {
args: (),
msg: "A function received a self argument as not the first argument.",
help: None,
}
);

View File

@ -1,9 +0,0 @@
/*
namespace: Compile
expectation: Fail
*/
function main() {
let x: [u8; _] = [1u8,2];
let z: bool = x == [1u8,2,3]; // array size mismatch
}

View File

@ -1,11 +0,0 @@
/*
namespace: Compile
expectation: Pass
input_file: input/dummy.in
*/
function main(y: bool) -> bool {
let d: [u8; _] = [1,2,3,4];
return d == [1,2,3,4];
}

View File

@ -1,13 +0,0 @@
/*
namespace: Compile
expectation: Pass
input_file: input/dummy.in
*/
function main(y: bool) -> bool {
return (first_el([1,2,3,4]) == 1) == y;
}
function first_el(arr: [u8; _]) -> u8 {
return arr[0];
}

View File

@ -1,7 +0,0 @@
[main]
y: bool = true;
n: bool = false;
a: [char; 11] = "hello world";
[registers]
r0: bool = false;

View File

@ -1,9 +0,0 @@
/*
namespace: Compile
expectation: Pass
input_file: input/dummy.in
*/
function main(a: [char; 11], y: bool) -> bool {
return y == (a.len() == 11);
}

View File

@ -1,17 +0,0 @@
/*
namespace: Compile
expectation: Pass
input_file: input/dummy.in
*/
function main(y: bool) -> bool {
let x = 0u8;
for i in 0..strlen("I swear to god I had something for this") {
x += 1;
}
return (x == 39) == y;
}
function strlen(str: [char; _]) -> u32 {
return str.len();
}

View File

@ -1,16 +0,0 @@
/*
namespace: Compile
expectation: Pass
input_file: input/dummy.in
*/
type str = [char; _];
function main(y: bool) -> bool {
let s = "abc";
return (first_el(s) == 'a') == y;
}
function first_el(s: str) -> char {
return s[0];
}

View File

@ -1,5 +0,0 @@
---
namespace: Compile
expectation: Fail
outputs:
- "Error [ECMP0376093]: array sizes must match for comparison; left: 2, right: 3\n --> compiler-test:5:19\n |\n 5 | let z: bool = x == [1u8,2,3]; // array size mismatch\n | ^^^^^^^^^^^^^^"

View File

@ -1,22 +0,0 @@
---
namespace: Compile
expectation: Pass
outputs:
- circuit:
num_public_variables: 0
num_private_variables: 1
num_constraints: 1
at: 042610d0fd1fe6d6ac112138f8755752f44c7d2a00f1b5960574d6da5cda393f
bt: e97756698880ab7555a959a5fb5c6b4e15bd64612aa677adbfe2d0bd91f0a83c
ct: cf1cbb66a638b4860a516671fb74850e6ccf787fe6c4c8d29e9c04efe880bd05
output:
- input_file: input/dummy.in
output:
registers:
r0:
type: bool
value: "true"
initial_ast: 71e25416f4a31045a847f29df48d5e9cce19d0df31c479761f2387eca4bb759f
imports_resolved_ast: a408ca2965d8d63856b1f95385746d5be9825b646e7f97a5fd3203638681292c
canonicalized_ast: a408ca2965d8d63856b1f95385746d5be9825b646e7f97a5fd3203638681292c
type_inferenced_ast: 88e5b982b094f07cc0337812b4965b655c020bdebfa1ad7ac8fd2ddd3c730b8b

View File

@ -1,22 +0,0 @@
---
namespace: Compile
expectation: Pass
outputs:
- circuit:
num_public_variables: 0
num_private_variables: 1
num_constraints: 1
at: 042610d0fd1fe6d6ac112138f8755752f44c7d2a00f1b5960574d6da5cda393f
bt: e97756698880ab7555a959a5fb5c6b4e15bd64612aa677adbfe2d0bd91f0a83c
ct: cf1cbb66a638b4860a516671fb74850e6ccf787fe6c4c8d29e9c04efe880bd05
output:
- input_file: input/dummy.in
output:
registers:
r0:
type: bool
value: "true"
initial_ast: d6d3ebe6a0b7f19e51d245d715706122577777a8325459df7db2c08ee5f841bd
imports_resolved_ast: 675c0542777db276ce7a39decb9dc5aacfde6b00ebfeb3982c480ed531a79be5
canonicalized_ast: 675c0542777db276ce7a39decb9dc5aacfde6b00ebfeb3982c480ed531a79be5
type_inferenced_ast: ae8cbfc3938971fc0e42fa400b1277d288ea4b7d4d8149b452fce81ae4813315

View File

@ -1,22 +0,0 @@
---
namespace: Compile
expectation: Pass
outputs:
- circuit:
num_public_variables: 0
num_private_variables: 12
num_constraints: 1
at: 336f487fe39f24aef980deaaf7d6dddcc0dbfa8f121c3470b05546c1ac13f87e
bt: ae35381db5558456a49acb22132b4930efd53b90eb2668df06c5d9c1a6b0ab9f
ct: cf1cbb66a638b4860a516671fb74850e6ccf787fe6c4c8d29e9c04efe880bd05
output:
- input_file: input/dummy.in
output:
registers:
r0:
type: bool
value: "true"
initial_ast: be4b4279f79a35306e1edf5086275a2b216e9d46d66b9bb5fbf650062b7cd263
imports_resolved_ast: c4aae9410df8034a7744ec5f1998454bacde915ddaadfab42181528f1923f742
canonicalized_ast: c4aae9410df8034a7744ec5f1998454bacde915ddaadfab42181528f1923f742
type_inferenced_ast: 0f8434f9e0430dc238602c0479a928be87101566dc0e9ae60ab9f4f1339ef313

View File

@ -1,22 +0,0 @@
---
namespace: Compile
expectation: Pass
outputs:
- circuit:
num_public_variables: 0
num_private_variables: 1
num_constraints: 1
at: 042610d0fd1fe6d6ac112138f8755752f44c7d2a00f1b5960574d6da5cda393f
bt: e97756698880ab7555a959a5fb5c6b4e15bd64612aa677adbfe2d0bd91f0a83c
ct: cf1cbb66a638b4860a516671fb74850e6ccf787fe6c4c8d29e9c04efe880bd05
output:
- input_file: input/dummy.in
output:
registers:
r0:
type: bool
value: "true"
initial_ast: cb9419739db39f806ff96983f53aa085a96238833ed754293042724dd3b29704
imports_resolved_ast: 675a67a8dae0a33a273d74ec021df0e23c5ed7cb32faf8efd2d2f087979de039
canonicalized_ast: b75d02c7cadbcd2906ad0d7b6376bbdc32ff1f26348913e2b0a84ced7496a2f6
type_inferenced_ast: 87ee95068efb0a58e18f2e3b8668db8d2ad9826b21e8b8ce6bc26f60c9fe88ca

View File

@ -1,22 +0,0 @@
---
namespace: Compile
expectation: Pass
outputs:
- circuit:
num_public_variables: 0
num_private_variables: 4
num_constraints: 5
at: e2c343f33b3c986318d821645015951a2f3fb198915bbf602e2c3e58ebfb9c73
bt: 71744948a918814d3008831b4b73101a5cf7346e6ff62d98968eb8b3b91aa343
ct: 94757fb2316d68d18fd26e96a2992b03a8db8d49d802b34201dce6f12518676b
output:
- input_file: input/dummy.in
output:
registers:
r0:
type: bool
value: "true"
initial_ast: 712ed2b7c1ddf180a39cd1bf83c7a4ca3de909a14f87250ec445ba6ae6aa6597
imports_resolved_ast: 36d9e14cf42065047dc21a5c68f45d3264dc0d38eb53355d3f9fef7bd7d512b1
canonicalized_ast: f1edababa6847e2ca24a0786bc1a0b2e66f0d60f5b11c59a24c8b1503f893092
type_inferenced_ast: c979556f787eb3190b0c4cec3d5a6baabbf64d32f7e3281c784f83262da33205

View File

@ -0,0 +1,5 @@
---
namespace: Parse
expectation: Fail
outputs:
- "Error [EPAR0370041]: A function received a self argument as not the first argument."

View File

@ -2,43 +2,41 @@
namespace: Token
expectation: Fail
outputs:
- "Error [EPAR0370028]: Expected a closed char but found '\\'."
- "Error [EPAR0370028]: Expected a closed char but found 'a."
- "Error [EPAR0370029]: Expected valid character but found ."
- "Error [EPAR0370028]: Expected a closed char but found '\\."
- "Error [EPAR0370029]: Expected valid character but found '\\x9."
- "Error [EPAR0370029]: Expected valid character but found '\\x."
- "Error [EPAR0370029]: Expected valid character but found '\\x7."
- "Error [EPAR0370029]: Expected valid character but found '\\x."
- "Error [EPAR0370029]: Expected valid character but found '\\x8."
- "Error [EPAR0370029]: Expected valid character but found '\\xc."
- "Error [EPAR0370029]: Expected valid character but found '\\xc."
- "Error [EPAR0370029]: Expected valid character but found '\\xD."
- "Error [EPAR0370029]: Expected valid character but found '\\xC."
- "Error [EPAR0370029]: Expected valid character but found '\\xe."
- "Error [EPAR0370029]: Expected valid character but found '\\x9."
- "Error [EPAR0370029]: Expected valid character but found 'abcdef."
- "Error [EPAR0370029]: Expected valid character but found '\\t\\."
- "Error [EPAR0370029]: Expected valid character but found '\\."
- "Error [EPAR0370029]: Expected valid character but found '\\."
- "Error [EPAR0370029]: Expected valid character but found '\\."
- "Error [EPAR0370029]: Expected valid character but found '\\."
- "Error [EPAR0370029]: Expected valid character but found '\\."
- "Error [EPAR0370029]: Expected valid character but found '\\."
- "Error [EPAR0370029]: Expected valid character but found '\\."
- "Error [EPAR0370029]: Expected valid character but found '\\."
- "Error [EPAR0370026]: Expected a valid escape character but found 117."
- "Error [EPAR0370029]: Expected valid character but found '\\u{bbbbb}\\u{aaaa."
- "Error [EPAR0370026]: Expected a valid escape character but found 117."
- "Error [EPAR0370026]: Expected a valid escape character but found 117."
- "Error [EPAR0370026]: Expected a valid escape character but found 117."
- "Error [EPAR0370029]: Expected valid character but found '\\u{2764."
- "Error [EPAR0370029]: Expected valid character but found '\\u{276g."
- "Error [EPAR0370026]: Expected a valid escape character but found 117."
- "Error [EPAR0370026]: Expected a valid escape character but found 117."
- "Error [EPAR0370026]: Expected a valid escape character but found 117."
- "Error [EPAR0370029]: Expected valid character but found '\\u{110000."
- "Error [EPAR0370029]: Expected valid character but found '😭😂<F09F98AD>."
- "Error [EPAR0370028]: Expected a closed char but found '\u001d<31>x 9 i32."
- "Error [EPAR0370029]: Expected valid character but found ' //#1647."
- "Error [EPAR0370029]: Expected valid character but found ' //#1651."
- "Error [EPAR0370028]: Expected a closed char but found `'\\'`."
- "Error [EPAR0370028]: Expected a closed char but found `'a`."
- "Error [EPAR0370024]: Expected more characters to lex but found none."
- "Error [EPAR0370036]: Expected a valid hex character but found `154`."
- "Error [EPAR0370035]: Could not lex the following escaped hex due to being given more than two chars: `7`."
- "Error [EPAR0370028]: Expected a closed char but found `\\x7g`."
- "Error [EPAR0370035]: Could not lex the following escaped hex due to being given more than two chars: `z`."
- "Error [EPAR0370036]: Expected a valid hex character but found `128`."
- "Error [EPAR0370036]: Expected a valid hex character but found `193`."
- "Error [EPAR0370036]: Expected a valid hex character but found `194`."
- "Error [EPAR0370036]: Expected a valid hex character but found `223`."
- "Error [EPAR0370036]: Expected a valid hex character but found `192`."
- "Error [EPAR0370036]: Expected a valid hex character but found `224`."
- "Error [EPAR0370036]: Expected a valid hex character but found `159`."
- "Error [EPAR0370028]: Expected a closed char but found `abcdefg`."
- "Error [EPAR0370033]: Could not lex the following escaped char due to being given more than one char: `t\\t`."
- "Error [EPAR0370026]: Expected a valid escape character but found `a`."
- "Error [EPAR0370026]: Expected a valid escape character but found `z`."
- "Error [EPAR0370026]: Expected a valid escape character but found `A`."
- "Error [EPAR0370026]: Expected a valid escape character but found `Z`."
- "Error [EPAR0370026]: Expected a valid escape character but found `1`."
- "Error [EPAR0370026]: Expected a valid escape character but found `9`."
- "Error [EPAR0370026]: Expected a valid escape character but found `*`."
- "Error [EPAR0370035]: Could not lex the following escaped hex due to being given more than two chars: ``."
- "Error [EPAR0370026]: Expected a valid escape character but found `117`."
- "Error [EPAR0370038]: The escaped unicode char `bbbbb}\\u{aaaa` is not within valid length of [1, 6]."
- "Error [EPAR0370026]: Expected a valid escape character but found `117`."
- "Error [EPAR0370026]: Expected a valid escape character but found `117`."
- "Error [EPAR0370026]: Expected a valid escape character but found `117`."
- "Error [EPAR0370037]: There was no closing `}` after a escaped unicode `\\u{2764z`."
- "Error [EPAR0370028]: Expected a closed char but found `\\u{276g}`."
- "Error [EPAR0370026]: Expected a valid escape character but found `117`."
- "Error [EPAR0370026]: Expected a valid escape character but found `117`."
- "Error [EPAR0370026]: Expected a valid escape character but found `117`."
- "Error [EPAR0370039]: The escaped unicode char `110000` is greater than 0x10FFFF."
- "Error [EPAR0370037]: There was no closing `}` after a escaped unicode `\\u{af🦀`."
- "Error [EPAR0370029]: Expected valid character but found `'🦀\\`."
- "Error [EPAR0370029]: Expected valid character but found `'😭😂`."

View File

@ -2,11 +2,10 @@
namespace: Token
expectation: Fail
outputs:
- "Error [EPAR0370027]: Expected a closed string but found \"Hello world!."
- "Error [EPAR0370027]: Expected a closed string but found \"\\\"."
- "Error [EPAR0370027]: Expected a closed string but found \"\\."
- "Error [EPAR0370026]: Expected a valid escape character but found \\l."
- "Error [EPAR0370027]: Expected a closed string but found \"\\uaaa\"."
- "Error [EPAR0370027]: Expected a closed string but found \"\\u\"."
- "Error [EPAR0370026]: Expected a valid escape character but found \\xFF."
- "Error [EPAR0370027]: Expected a closed string but found \"\\x\"."
- "Error [EPAR0370027]: Expected a closed string but found `\"Hello world!`."
- "Error [EPAR0370027]: Expected a closed string but found `\"\\\"`."
- "Error [EPAR0370026]: Expected a valid escape character but found `l`."
- "Error [EPAR0370027]: Expected a closed string but found `\"\\uaaa\"`."
- "Error [EPAR0370027]: Expected a closed string but found `\"\\u\"`."
- "Error [EPAR0370036]: Expected a valid hex character but found `255`."
- "Error [EPAR0370027]: Expected a closed string but found `\"\\x\"`."

View File

@ -0,0 +1,5 @@
---
namespace: Parse
expectation: Fail
outputs:
- "Error [EPAR0370009]: unexpected string: expected 'ident', got '?'\n --> test:3:6\n |\n 3 | @foo(?, bar, ?)\n | ^\nError [EPAR0370009]: unexpected string: expected 'ident', got '?'\n --> test:3:14\n |\n 3 | @foo(?, bar, ?)\n | ^\nError [EPAR0370009]: unexpected string: expected 'ident', got '123'\n --> test:8:6\n |\n 8 | @bar(123) // ints not vali\n | ^^^\nError [EPAR0370017]: \"@context(...)\" is deprecated. Did you mean @test annotation?\n --> test:14:2\n |\n 14 | @context // recovery witness\n | ^^^^^^^"

View File

@ -2,4 +2,4 @@
namespace: Parse
expectation: Fail
outputs:
- "Error [EPAR0370009]: unexpected string: expected 'ident or int', got '?'\n --> test:3:6\n |\n 3 | @foo(?, bar, ?)\n | ^\nError [EPAR0370009]: unexpected string: expected 'ident or int', got '?'\n --> test:3:14\n |\n 3 | @foo(?, bar, ?)\n | ^\nError [EPAR0370017]: \"@context(...)\" is deprecated. Did you mean @test annotation?\n --> test:8:2\n |\n 8 | @context // recovery witness\n | ^^^^^^^"
- "Error [EPAR0370009]: unexpected string: expected 'ident', got '?'\n --> test:3:6\n |\n 3 | @foo(?, bar, ?)\n | ^\nError [EPAR0370009]: unexpected string: expected 'ident', got '?'\n --> test:3:14\n |\n 3 | @foo(?, bar, ?)\n | ^\nError [EPAR0370017]: \"@context(...)\" is deprecated. Did you mean @test annotation?\n --> test:8:2\n |\n 8 | @context // recovery witness\n | ^^^^^^^"

View File

@ -1,68 +0,0 @@
---
namespace: Parse
expectation: Pass
outputs:
- name: ""
expected_input: []
import_statements: []
imports: {}
aliases: {}
circuits: {}
global_consts: {}
functions:
"{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":10,\\\"col_stop\\\":11,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function x(x: [u8; _]) {\\\"}\"}":
annotations: {}
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":10,\\\"col_stop\\\":11,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function x(x: [u8; _]) {\\\"}\"}"
input:
- Variable:
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":12,\\\"col_stop\\\":13,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function x(x: [u8; _]) {\\\"}\"}"
const_: false
mutable: true
type_:
Array:
- IntegerType: U8
- - value: "0"
span:
line_start: 3
line_stop: 3
col_start: 12
col_stop: 13
path: ""
content: "function x(x: [u8; _]) {"
const_: false
output: ~
core_mapping: ~
block:
statements:
- Return:
expression:
TupleInit:
elements: []
span:
line_start: 4
line_stop: 4
col_start: 12
col_stop: 14
path: ""
content: " return ();"
span:
line_start: 4
line_stop: 4
col_start: 5
col_stop: 14
path: ""
content: " return ();"
span:
line_start: 3
line_stop: 5
col_start: 24
col_stop: 2
path: ""
content: "function x(x: [u8; _]) {\n ...\n}"
span:
line_start: 3
line_stop: 5
col_start: 1
col_stop: 2
path: ""
content: "function x(x: [u8; _]) {\n ...\n}"

View File

@ -1513,53 +1513,6 @@ outputs:
col_stop: 14
path: ""
content: "let (x,) = ();"
- Definition:
declaration_type: Let
variable_names:
- mutable: true
identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":5,\\\"col_stop\\\":6,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"let x: [char; _] = \\\\\\\"Hello, World!\\\\\\\";\\\"}\"}"
span:
line_start: 1
line_stop: 1
col_start: 5
col_stop: 6
path: ""
content: "let x: [char; _] = \"Hello, World!\";"
parened: false
type_:
Array:
- Char
- - value: "0"
value:
Value:
String:
- - Scalar: 72
- Scalar: 101
- Scalar: 108
- Scalar: 108
- Scalar: 111
- Scalar: 44
- Scalar: 32
- Scalar: 87
- Scalar: 111
- Scalar: 114
- Scalar: 108
- Scalar: 100
- Scalar: 33
- span:
line_start: 1
line_stop: 1
col_start: 20
col_stop: 35
path: ""
content: "let x: [char; _] = \"Hello, World!\";"
span:
line_start: 1
line_stop: 1
col_start: 1
col_stop: 35
path: ""
content: "let x: [char; _] = \"Hello, World!\";"
- Definition:
declaration_type: Let
variable_names:

View File

@ -0,0 +1,7 @@
---
namespace: ParseStatement
expectation: Fail
outputs:
- "Error [EPAR0370040]: A hex number `0x4..` was provided but hex is not allowed."
- "Error [EPAR0370040]: A hex number `0xA..` was provided but hex is not allowed."
- "Error [EPAR0370040]: A hex number `0xF..` was provided but hex is not allowed."

View File

@ -0,0 +1,10 @@
/*
namespace: Parse
expectation: Fail
*/
circuit X {
function x(foo: u32, &self) {
return ();
}
}

View File

@ -9,8 +9,6 @@ expectation: Fail
''
'\
'\x9A'
'\x7'
'\x7g'
@ -46,8 +44,7 @@ expectation: Fail
'\u01000000'
'\u9999999'
'\u{110000}'
'\u{af🦀'
'🦀\n'
'😭😂😘'
'<1D>x 9 i32
' //#1647 '\u{af🦀'
' //#1651 '🦀\n'

View File

@ -8,6 +8,12 @@ function x() {
return ();
}
@bar(123) // ints not vali
function x() {
return ();
}
@context // recovery witness
function x() {
return ();

View File

@ -1,8 +0,0 @@
/*
namespace: Parse
expectation: Pass
*/
function x(x: [u8; _]) {
return ();
}

View File

@ -99,9 +99,6 @@ let (x,y,) = ();
let (x,) = ();
let x: [char; _] = "Hello, World!";
let x: [[u8; 2]; 2] = [[0,0], [0,0]];
let x: [u8; (2, 2)] = [[0,0], [0,0]];

View File

@ -0,0 +1,10 @@
/*
namespace: ParseStatement
expectation: Fail
*/
let x = 0x40u32;
let y: u32 = 0xAAu32;
let z = 0xFFu8;

View File

@ -22,7 +22,7 @@ pub fn find_tests<T: AsRef<Path>>(path: T, out: &mut Vec<(String, String)>) {
if entry.is_dir() {
find_tests(entry.as_path(), out);
continue;
} else if entry.extension().map(|x| x.to_str()).flatten().unwrap_or_default() != "leo" {
} else if entry.extension().and_then(|x| x.to_str()).unwrap_or_default() != "leo" {
continue;
}
let content = fs::read_to_string(entry.as_path()).expect("failed to read test");

View File

@ -147,7 +147,7 @@ pub fn run_tests<T: Runner>(runner: &T, expectation_category: &str) {
let mut expected_output = expectations.as_ref().map(|x| x.outputs.iter());
for (i, test) in tests.into_iter().enumerate() {
let expected_output = expected_output.as_mut().map(|x| x.next()).flatten().cloned();
let expected_output = expected_output.as_mut().and_then(|x| x.next()).cloned();
println!("running test {} @ '{}'", test_name, path.to_str().unwrap());
let output = namespace.run_test(Test {
name: test_name.clone(),