merge testnet3

This commit is contained in:
collin 2022-05-25 14:02:10 -04:00
commit 8d79193474
74 changed files with 1370 additions and 1561 deletions

View File

@ -21,7 +21,18 @@ jobs:
- name: Generate asts
run: |
cargo -q run -p leo-test-framework --bin tgc
# This currently has to be on testnet3 to work:
cd compiler/parser
cargo -q install --path . --example parser
# To ensure full file tests,
# just do compiler tests and remove expectation: Fail tests
cd ../../tests/compiler
find . -type f -exec grep -q 'expectation *: *Fail' {} \; -delete
find . -name '*.leo' -execdir parser {} \; > /dev/null
# Show how many there are:
echo "Counts (.leo / .json):"
find . -name '*.leo' -print | wc -l
find . -name '*.json' -print | wc -l
# Pull the latest release from the leo-acl2-bin repo, and put it into the
# repo/acl2 directory. After it's done, unpack the tgz file locally.
@ -29,7 +40,7 @@ jobs:
run: |
mkdir acl2 && cd acl2;
wget $( curl -s https://api.github.com/repos/AleoHQ/leo-acl2-bin/releases/latest \
| jq -r '.assets[0].browser_download_url' )
| jq -r '.assets[].browser_download_url|scan("^.*leo-acl2--v.*\\.tgz$")' )
echo "Unpacking $(ls):"
tar -xvzf $(ls)
@ -37,28 +48,31 @@ jobs:
# Run theorem generation and checking using the prepared ASTs and the pulled and unzipped leo-acl2 tarball.
- name: Run tgc over ASTs
run: |
canonicalization_errors=();
type_inference_errors=();
num_dirs=0;
for dir in `ls tmp/tgc`;
parsing_errors=();
num_cases=0;
# Note that PWD gets reset at the beginning of each the step
# to /home/runner/work/leo/leo
acl2dir="${PWD}"/acl2
cd tests/compiler;
for tc in `find ${PWD} -name '*.leo' -print`;
do
cd tmp/tgc/$dir; # enter the directory
num_dirs=$((num_dirs + 1));
./../../../acl2/tgc canonicalization initial_ast.json canonicalization_ast.json canonicalization-theorem.lisp > canonicalization_result.out || canonicalization_errors+=("$dir");
./../../../acl2/tgc type-inference canonicalization_ast.json type_inferenced_ast.json type-inference-theorem.lisp > type_inference_result.out || type_inference_errors+=("$dir");
cd ../../..
cd "${tc%/*}"; # enter the directory
leofile="${tc##*/}";
jsonfile="${leofile%.leo}.json";
num_cases=$((num_cases + 1));
"$acl2dir"/tgc parsing "$leofile" "$jsonfile" parsing-theorem.lisp > parsing_result.out || parsing_errors+=("$tc");
done;
echo "----------------"
echo "Ran tgc in ${num_dirs} directories."
echo "Ran tgc on ${num_cases} programs."
echo "----------------"
if [ ${#canonicalization_errors[@]} -eq 0 ]; then
echo "Canonicalization - Success!"
if [ ${#parsing_errors[@]} -eq 0 ]; then
echo "Parsing - Total Success!"
else
echo "Canonicalization Failures (total: ${#canonicalization_errors[@]}):"
for dir in ${canonicalization_errors[@]};
echo "Parsing Failures (total: ${#parsing_errors[@]}):"
for tc in ${parsing_errors[@]};
do
echo $dir
echo $tc
done;
#echo "Attaching logs:"
@ -69,24 +83,7 @@ jobs:
#done;
fi
echo "----------------"
if [ ${#type_inference_errors[@]} -eq 0 ]; then
echo "Type Inference - Success!"
else
echo "Type Inference Failures (total: ${#type_inference_errors[@]}):"
for dir in ${type_inference_errors[@]};
do
echo $dir
done;
#echo "Attaching logs:"
#for dir in ${type_inference_errors[@]};
#do
# cat tmp/tgc/$dir/type_inference_result.out
#done;
fi
if [[ ${#canonicalization_errors[@]} -ne 0 || ${#type_inference_errors[@]} -ne 0 ]]; then
if [[ ${#parsing_errors[@]} -ne 0 ]]; then
echo "----------------"
echo "Exiting with status 1 due to at least one tgc error."
exit 1

3
.gitignore vendored
View File

@ -18,3 +18,6 @@ sccache*/
*~
\#*\#
.\#*
# code coverage scripts
*.bat

8
Cargo.lock generated
View File

@ -2006,9 +2006,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.5.5"
version = "1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
dependencies = [
"aho-corasick",
"memchr",
@ -2023,9 +2023,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-syntax"
version = "0.6.25"
version = "0.6.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
[[package]]
name = "remove_dir_all"

View File

@ -21,18 +21,21 @@ use crate::Char;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum ValueExpression {
// todo: deserialize values here
/// An address literal, e.g., `aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8`.
/// An address literal, e.g., `aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8s7pyjh9`.
Address(String, #[serde(with = "leo_span::span_json")] Span),
/// A boolean literal, either `true` or `false`.
Boolean(String, #[serde(with = "leo_span::span_json")] Span),
/// A field literal, e.g., `42field`.
/// That is, a signed number followed by the keyword `field`.
/// A signed number followed by the keyword `field`.
Field(String, #[serde(with = "leo_span::span_json")] Span),
/// A group literal, either product or affine.
/// For example, `42group` or `(12, 52)group`.
Group(Box<GroupValue>),
/// An integer literal, e.g., `42`.
Integer(IntegerType, String, #[serde(with = "leo_span::span_json")] Span),
/// A scalar literal, e.g. `1scalar`.
/// An unsigned number followed by the keyword `scalar`.
Scalar(String, #[serde(with = "leo_span::span_json")] Span),
/// A string literal, e.g., `"foobar"`.
String(Vec<Char>, #[serde(with = "leo_span::span_json")] Span),
}
@ -44,8 +47,9 @@ impl fmt::Display for ValueExpression {
Address(address, _) => write!(f, "{}", address),
Boolean(boolean, _) => write!(f, "{}", boolean),
Field(field, _) => write!(f, "{}", field),
Integer(type_, value, _) => write!(f, "{}{}", value, type_),
Group(group) => write!(f, "{}", group),
Integer(type_, value, _) => write!(f, "{}{}", value, type_),
Scalar(scalar, _) => write!(f, "{}", scalar),
String(string, _) => {
for character in string.iter() {
write!(f, "{}", character)?;
@ -60,7 +64,12 @@ impl Node for ValueExpression {
fn span(&self) -> Span {
use ValueExpression::*;
match &self {
Address(_, span) | Boolean(_, span) | Field(_, span) | Integer(_, _, span) | String(_, span) => *span,
Address(_, span)
| Boolean(_, span)
| Field(_, span)
| Integer(_, _, span)
| Scalar(_, span)
| String(_, span) => *span,
Group(group) => match &**group {
GroupValue::Single(_, span) => *span,
GroupValue::Tuple(tuple) => tuple.span,
@ -71,9 +80,12 @@ impl Node for ValueExpression {
fn set_span(&mut self, new_span: Span) {
use ValueExpression::*;
match self {
Address(_, span) | Boolean(_, span) | Field(_, span) | Integer(_, _, span) | String(_, span) => {
*span = new_span
}
Address(_, span)
| Boolean(_, span)
| Field(_, span)
| Integer(_, _, span)
| Scalar(_, span)
| String(_, span) => *span = new_span,
Group(group) => match &mut **group {
GroupValue::Single(_, span) => *span = new_span,
GroupValue::Tuple(tuple) => tuple.span = new_span,

View File

@ -34,7 +34,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
}
pub fn reduce_type(&mut self, type_: &Type, span: &Span) -> Result<Type> {
self.reducer.reduce_type(type_, type_.clone(), span)
self.reducer.reduce_type(type_, *type_, span)
}
// Expressions
@ -126,7 +126,6 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
Statement::Conditional(conditional) => Statement::Conditional(self.reduce_conditional(conditional)?),
Statement::Iteration(iteration) => Statement::Iteration(Box::new(self.reduce_iteration(iteration)?)),
Statement::Console(console) => Statement::Console(self.reduce_console(console)?),
Statement::Expression(expression) => Statement::Expression(self.reduce_expression_statement(expression)?),
Statement::Block(block) => Statement::Block(self.reduce_block(block)?),
};
@ -241,11 +240,6 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
self.reducer.reduce_console(console_function_call, function)
}
pub fn reduce_expression_statement(&mut self, expression: &ExpressionStatement) -> Result<ExpressionStatement> {
let inner_expression = self.reduce_expression(&expression.expression)?;
self.reducer.reduce_expression_statement(expression, inner_expression)
}
pub fn reduce_block(&mut self, block: &Block) -> Result<Block> {
let mut statements = vec![];
for statement in block.statements.iter() {

View File

@ -232,17 +232,6 @@ pub trait ReconstructingReducer {
})
}
fn reduce_expression_statement(
&mut self,
expression_statement: &ExpressionStatement,
expression: Expression,
) -> Result<ExpressionStatement> {
Ok(ExpressionStatement {
expression,
span: expression_statement.span,
})
}
fn reduce_block(&mut self, block: &Block, statements: Vec<Statement>) -> Result<Block> {
Ok(Block {
statements,

View File

@ -92,10 +92,6 @@ pub trait StatementVisitor<'a> {
Default::default()
}
fn visit_expression_statement(&mut self, _input: &'a ExpressionStatement) -> VisitResult {
Default::default()
}
fn visit_block(&mut self, _input: &'a Block) -> VisitResult {
Default::default()
}

View File

@ -91,7 +91,6 @@ impl<'a, V: ExpressionVisitor<'a> + StatementVisitor<'a>> VisitorDirector<'a, V>
Statement::Conditional(stmt) => self.visit_conditional(stmt),
Statement::Iteration(stmt) => self.visit_iteration(stmt),
Statement::Console(stmt) => self.visit_console(stmt),
Statement::Expression(stmt) => self.visit_expression_statement(stmt),
Statement::Block(stmt) => self.visit_block(stmt),
}
}
@ -144,12 +143,6 @@ impl<'a, V: ExpressionVisitor<'a> + StatementVisitor<'a>> VisitorDirector<'a, V>
}
}
pub fn visit_expression_statement(&mut self, input: &'a ExpressionStatement) {
if let VisitResult::VisitChildren = self.visitor.visit_expression_statement(input) {
self.visit_expression(&input.expression);
}
}
pub fn visit_block(&mut self, input: &'a Block) {
if let VisitResult::VisitChildren = self.visitor.visit_block(input) {
input.statements.iter().for_each(|stmt| self.visit_statement(stmt));

View File

@ -1,38 +0,0 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Node};
use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::fmt;
/// An expression statement `expr;`.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct ExpressionStatement {
/// The expression to evaluate purely for its side-effects.
pub expression: Expression,
/// The span excluding the semicolon.
pub span: Span,
}
impl fmt::Display for ExpressionStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{};", self.expression)
}
}
crate::simple_node_impl!(ExpressionStatement);

View File

@ -29,9 +29,6 @@ pub use return_statement::*;
pub mod iteration;
pub use iteration::*;
pub mod expression;
pub use expression::*;
pub mod definition;
pub use definition::*;

View File

@ -36,13 +36,20 @@ pub enum Statement {
Iteration(Box<IterationStatement>),
/// A console logging statement.
Console(ConsoleStatement),
/// An expression statement turning an expression into a statement,
/// using the expression only for its side-effects.
Expression(ExpressionStatement),
/// A block statement.
Block(Block),
}
impl Statement {
/// Returns a dummy statement made from an empty block `{}`.
pub fn dummy(span: Span) -> Self {
Self::Block(Block {
statements: Vec::new(),
span,
})
}
}
impl fmt::Display for Statement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
@ -52,7 +59,6 @@ impl fmt::Display for Statement {
Statement::Conditional(x) => x.fmt(f),
Statement::Iteration(x) => x.fmt(f),
Statement::Console(x) => x.fmt(f),
Statement::Expression(x) => x.fmt(f),
Statement::Block(x) => x.fmt(f),
}
}
@ -68,7 +74,6 @@ impl Node for Statement {
Conditional(n) => n.span(),
Iteration(n) => n.span(),
Console(n) => n.span(),
Expression(n) => n.span(),
Block(n) => n.span(),
}
}
@ -82,7 +87,6 @@ impl Node for Statement {
Conditional(n) => n.set_span(span),
Iteration(n) => n.set_span(span),
Console(n) => n.set_span(span),
Expression(n) => n.set_span(span),
Block(n) => n.set_span(span),
}
}

View File

@ -20,7 +20,7 @@ use serde::{Deserialize, Serialize};
use std::fmt;
/// Explicit type used for defining a variable or expression type
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Type {
// Data types
/// The `address` type.
@ -31,6 +31,8 @@ pub enum Type {
Field,
/// The `group` type.
Group,
/// The `scalar` type.
Scalar,
/// An integer type.
IntegerType(IntegerType),
@ -47,10 +49,11 @@ impl Type {
///
pub fn eq_flat(&self, other: &Self) -> bool {
match (self, other) {
(Type::Address, Type::Address) => true,
(Type::Boolean, Type::Boolean) => true,
(Type::Field, Type::Field) => true,
(Type::Group, Type::Group) => true,
(Type::Address, Type::Address)
| (Type::Boolean, Type::Boolean)
| (Type::Field, Type::Field)
| (Type::Group, Type::Group)
| (Type::Scalar, Type::Scalar) => true,
(Type::IntegerType(left), Type::IntegerType(right)) => left.eq(right),
_ => false,
}
@ -64,6 +67,7 @@ impl fmt::Display for Type {
Type::Boolean => write!(f, "bool"),
Type::Field => write!(f, "field"),
Type::Group => write!(f, "group"),
Type::Scalar => write!(f, "scalar"),
Type::IntegerType(ref integer_type) => write!(f, "{}", integer_type),
Type::Err => write!(f, "error"),
}

View File

@ -31,6 +31,7 @@ const INT_TYPES: &[Token] = &[
Token::U128,
Token::Field,
Token::Group,
Token::Scalar,
];
impl ParserContext<'_> {
@ -164,7 +165,7 @@ impl ParserContext<'_> {
/// Returns an [`Expression`] AST node if the next tokens represent a
/// binary addition or subtraction expression.
///
/// Otherwise, tries to parse the next token using [`parse_mul_div_pow_expression`].
/// Otherwise, tries to parse the next token using [`parse_multiplicative_expression`].
pub fn parse_additive_expression(&mut self) -> Result<Expression> {
self.parse_bin_expr(&[Token::Add, Token::Minus], Self::parse_multiplicative_expression)
}
@ -295,6 +296,11 @@ impl ParserContext<'_> {
assert_no_whitespace("group")?;
Expression::Value(ValueExpression::Group(Box::new(GroupValue::Single(value, full_span))))
}
// Literal followed by `scalar` e.g., `42scalar`.
Some(Token::Scalar) => {
assert_no_whitespace("scalar")?;
Expression::Value(ValueExpression::Scalar(value, full_span))
}
// Literal followed by other type suffix, e.g., `42u8`.
Some(suffix) => {
assert_no_whitespace(&suffix.to_string())?;

View File

@ -70,11 +70,11 @@ impl ParserContext<'_> {
value,
})))
} else {
// Error on `expr;` but recover as an empty block `{}`.
self.expect(&Token::Semicolon)?;
Ok(Statement::Expression(ExpressionStatement {
span: expr.span(),
expression: expr,
}))
let span = expr.span() + self.prev_token.span;
self.emit_err(ParserError::expr_stmts_disallowed(span));
Ok(Statement::dummy(span))
}
}
@ -140,7 +140,6 @@ impl ParserContext<'_> {
// Parse iteration range.
let start = self.parse_expression()?;
self.expect(&Token::DotDot)?;
let inclusive = self.eat(&Token::Assign);
self.disallow_circuit_construction = true;
let stop = self.parse_conditional_expression()?;
self.disallow_circuit_construction = false;
@ -153,7 +152,7 @@ impl ParserContext<'_> {
type_: type_.0,
start,
stop,
inclusive,
inclusive: false,
block,
})
}

View File

@ -18,6 +18,11 @@ use super::*;
use leo_errors::Result;
pub(crate) const TYPE_TOKENS: &[Token] = &[
Token::Address,
Token::Bool,
Token::Field,
Token::Group,
Token::Scalar,
Token::I8,
Token::I16,
Token::I32,
@ -28,10 +33,6 @@ pub(crate) const TYPE_TOKENS: &[Token] = &[
Token::U32,
Token::U64,
Token::U128,
Token::Field,
Token::Group,
Token::Address,
Token::Bool,
];
impl ParserContext<'_> {
@ -58,10 +59,11 @@ impl ParserContext<'_> {
let span = self.expect_any(TYPE_TOKENS)?;
Ok((
match &self.prev_token.token {
Token::Field => Type::Field,
Token::Group => Type::Group,
Token::Address => Type::Address,
Token::Bool => Type::Boolean,
Token::Field => Type::Field,
Token::Group => Type::Group,
Token::Scalar => Type::Scalar,
x => Type::IntegerType(Self::token_to_int_type(x).expect("invalid int type")),
},
span,

View File

@ -15,7 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{tokenizer, ParserContext, SpannedToken};
use leo_ast::{Expression, ExpressionStatement, Statement, ValueExpression};
use leo_ast::Statement;
use leo_errors::{emitter::Handler, LeoError};
use leo_span::{
source_map::FileName,
@ -122,10 +122,7 @@ impl Namespace for ParseStatementNamespace {
create_session_if_not_set_then(|s| {
let tokenizer = tokenize(test, s)?;
if all_are_comments(&tokenizer) {
return Ok(yaml_or_fail(Statement::Expression(ExpressionStatement {
expression: Expression::Value(ValueExpression::String(Vec::new(), Default::default())),
span: Span::default(),
})));
return Ok(yaml_or_fail(Statement::dummy(Span::default())));
}
with_handler(tokenizer, |p| p.parse_statement()).map(yaml_or_fail)
})

View File

@ -395,6 +395,7 @@ impl Token {
"let" => Token::Let,
"public" => Token::Public,
"return" => Token::Return,
"scalar" => Token::Scalar,
"true" => Token::True,
"u8" => Token::U8,
"u16" => Token::U16,

View File

@ -108,6 +108,7 @@ mod tests {
let
mut
return
scalar
string
test
true
@ -158,7 +159,7 @@ mod tests {
assert_eq!(
output,
r#""test" "test{}test" "test{}" "{}test" "test{" "test}" "test{test" "test}test" "te{{}}" test_ident 12345 address bool const else false field for function group i128 i64 i32 i16 i8 if in input let mut return string test true u128 u64 u32 u16 u8 console ! != && ( ) * ** + , - -> _ . .. / : ; < <= = == > >= [ ] { { } } || ? // test
r#"'a' '😭' "test" "test{}test" "test{}" "{}test" "test{" "test}" "test{test" "test}test" "te{{}}" aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8 test_ident 12345 address bool const else false field for function group i128 i64 i32 i16 i8 if in input let mut return scalar string test true u128 u64 u32 u16 u8 console ! != && ( ) * ** + , - -> _ . .. / : ; < <= = == > >= [ ] { { } } || ? // test
/* test */ // "#
);
});

View File

@ -89,22 +89,23 @@ pub enum Token {
Arrow,
Underscore,
// Syntactic Grammr
// Syntactic Grammar
// Types
U8,
U16,
U32,
U64,
U128,
Address,
Bool,
Field,
Group,
Scalar,
I8,
I16,
I32,
I64,
I128,
Field,
Group,
Bool,
Address,
U8,
U16,
U32,
U64,
U128,
// Regular Keywords
Console,
@ -148,6 +149,7 @@ pub const KEYWORD_TOKENS: &[Token] = &[
Token::Let,
Token::Public,
Token::Return,
Token::Scalar,
Token::True,
Token::U8,
Token::U16,
@ -186,6 +188,7 @@ impl Token {
Token::Let => sym::Let,
Token::Public => sym::Public,
Token::Return => sym::Return,
Token::Scalar => sym::scalar,
Token::True => sym::True,
Token::U8 => sym::u8,
Token::U16 => sym::u16,
@ -247,20 +250,22 @@ impl fmt::Display for Token {
Arrow => write!(f, "->"),
Underscore => write!(f, "_"),
U8 => write!(f, "u8"),
U16 => write!(f, "u16"),
U32 => write!(f, "u32"),
U64 => write!(f, "u64"),
U128 => write!(f, "u128"),
Address => write!(f, "address"),
Bool => write!(f, "bool"),
Field => write!(f, "field"),
Group => write!(f, "group"),
Scalar => write!(f, "scalar"),
I8 => write!(f, "i8"),
I16 => write!(f, "i16"),
I32 => write!(f, "i32"),
I64 => write!(f, "i64"),
I128 => write!(f, "i128"),
Field => write!(f, "field"),
Group => write!(f, "group"),
Bool => write!(f, "bool"),
Address => write!(f, "address"),
U8 => write!(f, "u8"),
U16 => write!(f, "u16"),
U32 => write!(f, "u32"),
U64 => write!(f, "u64"),
U128 => write!(f, "u128"),
Console => write!(f, "console"),
Const => write!(f, "const"),
Constant => write!(f, "constant"),

View File

@ -43,7 +43,7 @@ impl<'a> TypeChecker<'a> {
match expr {
Expression::Identifier(ident) => {
if let Some(var) = self.symbol_table.lookup_variable(&ident.name) {
Some(self.assert_type(var.type_.clone(), expected, span))
Some(self.assert_type(*var.type_, expected, span))
} else {
self.handler
.emit_err(TypeCheckerError::unknown_sym("variable", ident.name, span).into());
@ -142,42 +142,51 @@ impl<'a> TypeChecker<'a> {
Some(self.assert_type(Type::IntegerType(*type_), expected, value.span()))
}
ValueExpression::Group(_) => Some(self.assert_type(Type::Group, expected, value.span())),
ValueExpression::Scalar(_, _) => Some(self.assert_type(Type::Scalar, expected, value.span())),
ValueExpression::String(_, _) => unreachable!("String types are not reachable"),
},
Expression::Binary(binary) => match binary.op {
BinaryOperation::And | BinaryOperation::Or => {
self.assert_type(Type::Boolean, expected.clone(), binary.span());
let t1 = self.compare_expr_type(&binary.left, expected.clone(), binary.left.span());
let t2 = self.compare_expr_type(&binary.right, expected.clone(), binary.right.span());
self.assert_type(Type::Boolean, expected, binary.span());
let t1 = self.compare_expr_type(&binary.left, expected, binary.left.span());
let t2 = self.compare_expr_type(&binary.right, expected, binary.right.span());
return_incorrect_type(t1, t2, expected)
}
BinaryOperation::Add | BinaryOperation::Sub => {
self.assert_arith_type(expected.clone(), binary.span());
let t1 = self.compare_expr_type(&binary.left, expected.clone(), binary.left.span());
let t2 = self.compare_expr_type(&binary.right, expected.clone(), binary.right.span());
BinaryOperation::Add => {
self.assert_field_group_scalar_int_type(expected, binary.span());
let t1 = self.compare_expr_type(&binary.left, expected, binary.left.span());
let t2 = self.compare_expr_type(&binary.right, expected, binary.right.span());
return_incorrect_type(t1, t2, expected)
}
BinaryOperation::Sub => {
self.assert_field_group_int_type(expected, binary.span());
let t1 = self.compare_expr_type(&binary.left, expected, binary.left.span());
let t2 = self.compare_expr_type(&binary.right, expected, binary.right.span());
return_incorrect_type(t1, t2, expected)
}
BinaryOperation::Mul => {
self.assert_arith_type(expected.clone(), binary.span());
self.assert_field_group_int_type(expected, binary.span());
let t1 = self.compare_expr_type(&binary.left, None, binary.left.span());
let t2 = self.compare_expr_type(&binary.right, None, binary.right.span());
// Allow `group` * `scalar` multiplication.
match (t1.as_ref(), t2.as_ref()) {
(Some(Type::Group), Some(other)) | (Some(other), Some(Type::Group)) => {
self.assert_int_type(Some(other.clone()), binary.span());
self.assert_type(*other, Some(Type::Scalar), binary.span());
Some(Type::Group)
}
_ => return_incorrect_type(t1, t2, expected),
}
}
BinaryOperation::Div => {
self.assert_field_or_int_type(expected.clone(), binary.span());
self.assert_field_int_type(expected, binary.span());
let t1 = self.compare_expr_type(&binary.left, expected.clone(), binary.left.span());
let t2 = self.compare_expr_type(&binary.right, expected.clone(), binary.right.span());
let t1 = self.compare_expr_type(&binary.left, expected, binary.left.span());
let t2 = self.compare_expr_type(&binary.right, expected, binary.right.span());
return_incorrect_type(t1, t2, expected)
}
BinaryOperation::Pow => {
@ -188,7 +197,7 @@ impl<'a> TypeChecker<'a> {
// Type A must be an int.
// Type B must be a unsigned int.
(Some(Type::IntegerType(_)), Some(Type::IntegerType(itype))) if !itype.is_signed() => {
self.assert_type(t1.clone().unwrap(), expected, binary.span());
self.assert_type(t1.unwrap(), expected, binary.span());
}
// Type A was an int.
// But Type B was not a unsigned int.
@ -221,7 +230,7 @@ impl<'a> TypeChecker<'a> {
t1
}
BinaryOperation::Eq | BinaryOperation::Ne => {
self.assert_type(Type::Boolean, expected.clone(), binary.span());
self.assert_type(Type::Boolean, expected, binary.span());
let t1 = self.compare_expr_type(&binary.left, None, binary.left.span());
let t2 = self.compare_expr_type(&binary.right, None, binary.right.span());
@ -229,20 +238,20 @@ impl<'a> TypeChecker<'a> {
return_incorrect_type(t1, t2, expected)
}
BinaryOperation::Lt | BinaryOperation::Gt | BinaryOperation::Le | BinaryOperation::Ge => {
self.assert_type(Type::Boolean, expected.clone(), binary.span());
self.assert_type(Type::Boolean, expected, binary.span());
let t1 = self.compare_expr_type(&binary.left, None, binary.left.span());
self.assert_int_type(t1.clone(), binary.left.span());
self.assert_field_scalar_int_type(t1, binary.left.span());
let t2 = self.compare_expr_type(&binary.right, None, binary.right.span());
self.assert_int_type(t2.clone(), binary.right.span());
self.assert_field_scalar_int_type(t2, binary.right.span());
return_incorrect_type(t1, t2, expected)
}
},
Expression::Unary(unary) => match unary.op {
UnaryOperation::Not => {
self.assert_type(Type::Boolean, expected.clone(), unary.span());
self.assert_type(Type::Boolean, expected, unary.span());
self.compare_expr_type(&unary.inner, expected, unary.inner.span())
}
UnaryOperation::Negate => {
@ -268,14 +277,14 @@ impl<'a> TypeChecker<'a> {
},
Expression::Ternary(ternary) => {
self.compare_expr_type(&ternary.condition, Some(Type::Boolean), ternary.condition.span());
let t1 = self.compare_expr_type(&ternary.if_true, expected.clone(), ternary.if_true.span());
let t2 = self.compare_expr_type(&ternary.if_false, expected.clone(), ternary.if_false.span());
let t1 = self.compare_expr_type(&ternary.if_true, expected, ternary.if_true.span());
let t2 = self.compare_expr_type(&ternary.if_false, expected, ternary.if_false.span());
return_incorrect_type(t1, t2, expected)
}
Expression::Call(call) => match &*call.function {
Expression::Identifier(ident) => {
if let Some(func) = self.symbol_table.lookup_fn(&ident.name) {
let ret = self.assert_type(func.output.clone(), expected, ident.span());
let ret = self.assert_type(func.output, expected, ident.span());
if func.input.len() != call.arguments.len() {
self.handler.emit_err(
@ -292,11 +301,7 @@ impl<'a> TypeChecker<'a> {
.iter()
.zip(call.arguments.iter())
.for_each(|(expected, argument)| {
self.compare_expr_type(
argument,
Some(expected.get_variable().type_.clone()),
argument.span(),
);
self.compare_expr_type(argument, Some(expected.get_variable().type_), argument.span());
});
Some(ret)

View File

@ -26,7 +26,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
let parent = self.parent.unwrap();
// Would never be None.
let func_output_type = self.symbol_table.lookup_fn(&parent).map(|f| f.output.clone());
let func_output_type = self.symbol_table.lookup_fn(&parent).map(|f| f.output);
self.compare_expr_type(&input.expression, func_output_type, input.expression.span());
VisitResult::VisitChildren
@ -51,7 +51,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
self.handler.emit_err(err);
}
self.compare_expr_type(&input.value, Some(input.type_.clone()), input.value.span());
self.compare_expr_type(&input.value, Some(input.type_), input.value.span());
});
VisitResult::VisitChildren
@ -70,7 +70,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
_ => {}
}
Some(var.type_.clone())
Some(*var.type_)
} else {
self.handler.emit_err(
TypeCheckerError::unknown_sym("variable", &input.assignee.identifier.name, input.assignee.span).into(),
@ -104,8 +104,8 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
self.handler.emit_err(err);
}
self.compare_expr_type(&input.start, Some(input.type_.clone()), input.start.span());
self.compare_expr_type(&input.stop, Some(input.type_.clone()), input.stop.span());
self.compare_expr_type(&input.start, Some(input.type_), input.start.span());
self.compare_expr_type(&input.stop, Some(input.type_), input.stop.span());
VisitResult::VisitChildren
}
@ -123,11 +123,6 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
VisitResult::VisitChildren
}
fn visit_expression_statement(&mut self, input: &'a ExpressionStatement) -> VisitResult {
self.compare_expr_type(&input.expression, None, input.span());
VisitResult::SkipChildren
}
fn visit_block(&mut self, input: &'a Block) -> VisitResult {
self.symbol_table.push_variable_scope();
// have to redo the logic here so we have scoping
@ -139,7 +134,6 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
Statement::Conditional(stmt) => self.visit_conditional(stmt),
Statement::Iteration(stmt) => self.visit_iteration(stmt),
Statement::Console(stmt) => self.visit_console(stmt),
Statement::Expression(stmt) => self.visit_expression_statement(stmt),
Statement::Block(stmt) => self.visit_block(stmt),
};
});

View File

@ -27,9 +27,7 @@ pub struct TypeChecker<'a> {
pub(crate) negate: bool,
}
const ARITHMETIC_TYPES: &[Type] = &[
Type::Field,
Type::Group,
const INT_TYPES: [Type; 10] = [
Type::IntegerType(IntegerType::I8),
Type::IntegerType(IntegerType::I16),
Type::IntegerType(IntegerType::I32),
@ -42,34 +40,34 @@ const ARITHMETIC_TYPES: &[Type] = &[
Type::IntegerType(IntegerType::U128),
];
const FIELD_AND_INT_TYPES: &[Type] = &[
Type::Field,
Type::IntegerType(IntegerType::I8),
Type::IntegerType(IntegerType::I16),
Type::IntegerType(IntegerType::I32),
Type::IntegerType(IntegerType::I64),
Type::IntegerType(IntegerType::I128),
Type::IntegerType(IntegerType::U8),
Type::IntegerType(IntegerType::U16),
Type::IntegerType(IntegerType::U32),
Type::IntegerType(IntegerType::U64),
Type::IntegerType(IntegerType::U128),
];
const fn create_type_superset<const S: usize, const A: usize, const O: usize>(
subset: [Type; S],
additional: [Type; A],
) -> [Type; O] {
let mut superset: [Type; O] = [Type::IntegerType(IntegerType::U8); O];
let mut i = 0;
while i < S {
superset[i] = subset[i];
i += 1;
}
let mut j = 0;
while j < A {
superset[i + j] = additional[j];
j += 1;
}
superset
}
const INT_TYPES: &[Type] = &[
Type::IntegerType(IntegerType::I8),
Type::IntegerType(IntegerType::I16),
Type::IntegerType(IntegerType::I32),
Type::IntegerType(IntegerType::I64),
Type::IntegerType(IntegerType::I128),
Type::IntegerType(IntegerType::U8),
Type::IntegerType(IntegerType::U16),
Type::IntegerType(IntegerType::U32),
Type::IntegerType(IntegerType::U64),
Type::IntegerType(IntegerType::U128),
];
const FIELD_INT_TYPES: [Type; 11] = create_type_superset(INT_TYPES, [Type::Field]);
const FIELD_SCALAR_INT_TYPES: [Type; 12] = create_type_superset(FIELD_INT_TYPES, [Type::Scalar]);
const FIELD_GROUP_INT_TYPES: [Type; 12] = create_type_superset(FIELD_INT_TYPES, [Type::Group]);
const FIELD_GROUP_SCALAR_INT_TYPES: [Type; 13] = create_type_superset(FIELD_GROUP_INT_TYPES, [Type::Scalar]);
impl<'a> TypeChecker<'a> {
/// Returns a new type checker given a symbol table and error handler.
pub fn new(symbol_table: &'a mut SymbolTable<'a>, handler: &'a Handler) -> Self {
Self {
symbol_table,
@ -79,47 +77,51 @@ impl<'a> TypeChecker<'a> {
}
}
/// Returns the given type if it equals the expected type or the expected type is none.
pub(crate) fn assert_type(&self, type_: Type, expected: Option<Type>, span: Span) -> Type {
if let Some(expected) = expected {
if type_ != expected {
self.handler
.emit_err(TypeCheckerError::type_should_be(type_.clone(), expected, span).into());
.emit_err(TypeCheckerError::type_should_be(type_, expected, span).into());
}
}
type_
}
pub(crate) fn assert_one_of_types(&self, type_: Option<Type>, expected: &[Type], span: Span) -> Option<Type> {
if let Some(type_) = type_.clone() {
for t in expected.iter() {
if &type_ == t {
return Some(type_);
}
/// Emits an error to the error handler if the given type is not equal to any of the expected types.
pub(crate) fn assert_one_of_types(&self, type_: Option<Type>, expected: &[Type], span: Span) {
if let Some(type_) = type_ {
if !expected.iter().any(|t: &Type| t == &type_) {
self.handler.emit_err(
TypeCheckerError::expected_one_type_of(
expected.iter().map(|t| t.to_string() + ",").collect::<String>(),
type_,
span,
)
.into(),
);
}
self.handler.emit_err(
TypeCheckerError::expected_one_type_of(
expected.iter().map(|t| t.to_string() + ",").collect::<String>(),
type_,
span,
)
.into(),
);
}
type_
}
pub(crate) fn assert_arith_type(&self, type_: Option<Type>, span: Span) -> Option<Type> {
self.assert_one_of_types(type_, ARITHMETIC_TYPES, span)
/// Emits an error to the handler if the given type is not a field or integer.
pub(crate) fn assert_field_int_type(&self, type_: Option<Type>, span: Span) {
self.assert_one_of_types(type_, &FIELD_INT_TYPES, span)
}
pub(crate) fn assert_field_or_int_type(&self, type_: Option<Type>, span: Span) -> Option<Type> {
self.assert_one_of_types(type_, FIELD_AND_INT_TYPES, span)
/// Emits an error to the handler if the given type is not a field, scalar, or integer.
pub(crate) fn assert_field_scalar_int_type(&self, type_: Option<Type>, span: Span) {
self.assert_one_of_types(type_, &FIELD_SCALAR_INT_TYPES, span)
}
pub(crate) fn assert_int_type(&self, type_: Option<Type>, span: Span) -> Option<Type> {
self.assert_one_of_types(type_, INT_TYPES, span)
/// Emits an error to the handler if the given type is not a field, group, or integer.
pub(crate) fn assert_field_group_int_type(&self, type_: Option<Type>, span: Span) {
self.assert_one_of_types(type_, &FIELD_GROUP_INT_TYPES, span)
}
/// Emits an error to the handler if the given type is not a field, group, scalar or integer.
pub(crate) fn assert_field_group_scalar_int_type(&self, type_: Option<Type>, span: Span) {
self.assert_one_of_types(type_, &FIELD_GROUP_SCALAR_INT_TYPES, span)
}
}

View File

@ -1,943 +0,0 @@
Copyright (C) 2019-2022 Aleo Systems Inc.
This file is part of the Leo library.
The Leo library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The Leo library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
--------
Lexical Grammar
---------------
<a name="ascii"></a>
```abnf
ascii = %x0-7F
```
<a name="safe-nonascii"></a>
```abnf
safe-nonascii = %x80-2029 / %x202F-2065 / %x2070-D7FF / %xE000-10FFFF
; excludes bidi embeddings/overrides/isolates
; and excludes high/low surrogates
```
<a name="character"></a>
```abnf
character = ascii / safe-nonascii
```
Go to: _[ascii](#user-content-ascii), [safe-nonascii](#user-content-safe-nonascii)_;
<a name="horizontal-tab"></a>
```abnf
horizontal-tab = %x9 ; <HT>
```
<a name="line-feed"></a>
```abnf
line-feed = %xA ; <LF>
```
<a name="carriage-return"></a>
```abnf
carriage-return = %xD ; <CR>
```
<a name="space"></a>
```abnf
space = %x20 ; <SP>
```
<a name="double-quote"></a>
```abnf
double-quote = %x22 ; "
```
<a name="single-quote"></a>
```abnf
single-quote = %x27 ; '
```
<a name="not-star"></a>
```abnf
not-star = %x0-29 / %x2B-7F / safe-nonascii ; anything but *
```
Go to: _[safe-nonascii](#user-content-safe-nonascii)_;
<a name="not-star-or-slash"></a>
```abnf
not-star-or-slash = %x0-29 / %x2B-2E / %x30-7F / safe-nonascii
; anything but * or /
```
Go to: _[safe-nonascii](#user-content-safe-nonascii)_;
<a name="not-line-feed-or-carriage-return"></a>
```abnf
not-line-feed-or-carriage-return = %x0-9 / %xB-C / %xE-7F / safe-nonascii
; anything but <LF> or <CR>
```
Go to: _[safe-nonascii](#user-content-safe-nonascii)_;
<a name="not-double-quote-or-backslash"></a>
```abnf
not-double-quote-or-backslash = %x0-21 / %x23-5B / %x5D-7F / safe-nonascii
; anything but " or \
```
Go to: _[safe-nonascii](#user-content-safe-nonascii)_;
<a name="not-single-quote-or-backslash"></a>
```abnf
not-single-quote-or-backslash = %x0-26 / %x28-5B / %x5D-7F / safe-nonascii
; anything but ' or \
```
Go to: _[safe-nonascii](#user-content-safe-nonascii)_;
<a name="line-terminator"></a>
```abnf
line-terminator = line-feed / carriage-return / carriage-return line-feed
```
Go to: _[carriage-return](#user-content-carriage-return), [line-feed](#user-content-line-feed)_;
<a name="whitespace"></a>
```abnf
whitespace = space / horizontal-tab / line-terminator
```
Go to: _[horizontal-tab](#user-content-horizontal-tab), [line-terminator](#user-content-line-terminator), [space](#user-content-space)_;
<a name="comment"></a>
```abnf
comment = block-comment / end-of-line-comment
```
Go to: _[block-comment](#user-content-block-comment), [end-of-line-comment](#user-content-end-of-line-comment)_;
<a name="block-comment"></a>
```abnf
block-comment = "/*" rest-of-block-comment
```
Go to: _[rest-of-block-comment](#user-content-rest-of-block-comment)_;
<a name="rest-of-block-comment"></a>
```abnf
rest-of-block-comment = "*" rest-of-block-comment-after-star
/ not-star rest-of-block-comment
```
Go to: _[not-star](#user-content-not-star), [rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star), [rest-of-block-comment](#user-content-rest-of-block-comment)_;
<a name="rest-of-block-comment-after-star"></a>
```abnf
rest-of-block-comment-after-star = "/"
/ "*" rest-of-block-comment-after-star
/ not-star-or-slash rest-of-block-comment
```
Go to: _[not-star-or-slash](#user-content-not-star-or-slash), [rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star), [rest-of-block-comment](#user-content-rest-of-block-comment)_;
<a name="end-of-line-comment"></a>
```abnf
end-of-line-comment = "//" *not-line-feed-or-carriage-return
```
<a name="keyword"></a>
```abnf
keyword = %s"address"
/ %s"bool"
/ %s"console"
/ %s"const"
/ %s"constant"
/ %s"else"
/ %s"field"
/ %s"for"
/ %s"function"
/ %s"group"
/ %s"i8"
/ %s"i16"
/ %s"i32"
/ %s"i64"
/ %s"i128"
/ %s"if"
/ %s"in"
/ %s"let"
/ %s"public"
/ %s"return"
/ %s"u8"
/ %s"u16"
/ %s"u32"
/ %s"u64"
/ %s"u128"
```
<a name="uppercase-letter"></a>
```abnf
uppercase-letter = %x41-5A ; A-Z
```
<a name="lowercase-letter"></a>
```abnf
lowercase-letter = %x61-7A ; a-z
```
<a name="letter"></a>
```abnf
letter = uppercase-letter / lowercase-letter
```
Go to: _[lowercase-letter](#user-content-lowercase-letter), [uppercase-letter](#user-content-uppercase-letter)_;
<a name="decimal-digit"></a>
```abnf
decimal-digit = %x30-39 ; 0-9
```
<a name="octal-digit"></a>
```abnf
octal-digit = %x30-37 ; 0-7
```
<a name="hexadecimal-digit"></a>
```abnf
hexadecimal-digit = decimal-digit / "a" / "b" / "c" / "d" / "e" / "f"
```
Go to: _[decimal-digit](#user-content-decimal-digit)_;
<a name="identifier"></a>
```abnf
identifier = letter *( letter / decimal-digit / "_" )
; but not a keyword or a boolean literal or aleo1...
```
Go to: _[letter](#user-content-letter)_;
<a name="numeral"></a>
```abnf
numeral = 1*decimal-digit
```
<a name="unsigned-literal"></a>
```abnf
unsigned-literal = numeral ( %s"u8" / %s"u16" / %s"u32" / %s"u64" / %s"u128" )
```
Go to: _[numeral](#user-content-numeral)_;
<a name="signed-literal"></a>
```abnf
signed-literal = numeral ( %s"i8" / %s"i16" / %s"i32" / %s"i64" / %s"i128" )
```
Go to: _[numeral](#user-content-numeral)_;
<a name="field-literal"></a>
```abnf
field-literal = numeral %s"field"
```
Go to: _[numeral](#user-content-numeral)_;
<a name="product-group-literal"></a>
```abnf
product-group-literal = numeral %s"group"
```
Go to: _[numeral](#user-content-numeral)_;
<a name="boolean-literal"></a>
```abnf
boolean-literal = %s"true" / %s"false"
```
<a name="address-literal"></a>
```abnf
address-literal = %s"aleo1" 58( lowercase-letter / decimal-digit )
```
<a name="single-quote-escape"></a>
```abnf
single-quote-escape = "\" single-quote ; \'
```
Go to: _[single-quote](#user-content-single-quote)_;
<a name="double-quote-escape"></a>
```abnf
double-quote-escape = "\" double-quote ; \"
```
Go to: _[double-quote](#user-content-double-quote)_;
<a name="backslash-escape"></a>
```abnf
backslash-escape = "\\"
```
<a name="line-feed-escape"></a>
```abnf
line-feed-escape = %s"\n"
```
<a name="carriage-return-escape"></a>
```abnf
carriage-return-escape = %s"\r"
```
<a name="horizontal-tab-escape"></a>
```abnf
horizontal-tab-escape = %s"\t"
```
<a name="null-character-escape"></a>
```abnf
null-character-escape = "\0"
```
<a name="simple-character-escape"></a>
```abnf
simple-character-escape = single-quote-escape
/ double-quote-escape
/ backslash-escape
/ line-feed-escape
/ carriage-return-escape
/ horizontal-tab-escape
/ null-character-escape
```
Go to: _[backslash-escape](#user-content-backslash-escape), [carriage-return-escape](#user-content-carriage-return-escape), [double-quote-escape](#user-content-double-quote-escape), [horizontal-tab-escape](#user-content-horizontal-tab-escape), [line-feed-escape](#user-content-line-feed-escape), [null-character-escape](#user-content-null-character-escape), [single-quote-escape](#user-content-single-quote-escape)_;
<a name="ascii-character-escape"></a>
```abnf
ascii-character-escape = %s"\x" octal-digit hexadecimal-digit
```
Go to: _[hexadecimal-digit](#user-content-hexadecimal-digit), [octal-digit](#user-content-octal-digit)_;
<a name="unicode-character-escape"></a>
```abnf
unicode-character-escape = %s"\u{" 1*6hexadecimal-digit "}"
```
<a name="string-literal"></a>
```abnf
string-literal = double-quote *string-literal-element double-quote
```
Go to: _[double-quote](#user-content-double-quote)_;
<a name="string-literal-element"></a>
```abnf
string-literal-element = not-double-quote-or-backslash
/ simple-character-escape
/ ascii-character-escape
/ unicode-character-escape
```
Go to: _[ascii-character-escape](#user-content-ascii-character-escape), [not-double-quote-or-backslash](#user-content-not-double-quote-or-backslash), [simple-character-escape](#user-content-simple-character-escape), [unicode-character-escape](#user-content-unicode-character-escape)_;
<a name="integer-literal"></a>
```abnf
integer-literal = unsigned-literal
/ signed-literal
```
Go to: _[signed-literal](#user-content-signed-literal), [unsigned-literal](#user-content-unsigned-literal)_;
<a name="numeric-literal"></a>
```abnf
numeric-literal = integer-literal
/ field-literal
/ product-group-literal
```
Go to: _[field-literal](#user-content-field-literal), [integer-literal](#user-content-integer-literal), [product-group-literal](#user-content-product-group-literal)_;
<a name="atomic-literal"></a>
```abnf
atomic-literal = numeric-literal
/ boolean-literal
/ address-literal
/ string-literal
```
Go to: _[address-literal](#user-content-address-literal), [boolean-literal](#user-content-boolean-literal), [numeric-literal](#user-content-numeric-literal), [string-literal](#user-content-string-literal)_;
<a name="symbol"></a>
```abnf
symbol = "!" / "&&" / "||"
/ "==" / "!="
/ "<" / "<=" / ">" / ">="
/ "+" / "-" / "*" / "/" / "**"
/ "="
/ "(" / ")"
/ "[" / "]"
/ "{" / "}"
/ "," / "." / ".." / ";" / ":" / "?"
/ "->" / "_"
/ %s")group"
```
<a name="token"></a>
```abnf
token = keyword
/ identifier
/ atomic-literal
/ numeral
/ symbol
```
Go to: _[atomic-literal](#user-content-atomic-literal), [identifier](#user-content-identifier), [keyword](#user-content-keyword), [numeral](#user-content-numeral), [symbol](#user-content-symbol)_;
<a name="lexeme"></a>
```abnf
lexeme = token / comment / whitespace
```
Go to: _[comment](#user-content-comment), [token](#user-content-token), [whitespace](#user-content-whitespace)_;
--------
Syntactic Grammar
-----------------
<a name="unsigned-type"></a>
```abnf
unsigned-type = %s"u8" / %s"u16" / %s"u32" / %s"u64" / %s"u128"
```
<a name="signed-type"></a>
```abnf
signed-type = %s"i8" / %s"i16" / %s"i32" / %s"i64" / %s"i128"
```
<a name="integer-type"></a>
```abnf
integer-type = unsigned-type / signed-type
```
Go to: _[signed-type](#user-content-signed-type), [unsigned-type](#user-content-unsigned-type)_;
<a name="field-type"></a>
```abnf
field-type = %s"field"
```
<a name="group-type"></a>
```abnf
group-type = %s"group"
```
<a name="arithmetic-type"></a>
```abnf
arithmetic-type = integer-type / field-type / group-type
```
Go to: _[field-type](#user-content-field-type), [group-type](#user-content-group-type), [integer-type](#user-content-integer-type)_;
<a name="boolean-type"></a>
```abnf
boolean-type = %s"bool"
```
<a name="address-type"></a>
```abnf
address-type = %s"address"
```
<a name="primitive-type"></a>
```abnf
primitive-type = boolean-type / arithmetic-type / address-type
```
Go to: _[address-type](#user-content-address-type), [arithmetic-type](#user-content-arithmetic-type), [boolean-type](#user-content-boolean-type)_;
<a name="type"></a>
```abnf
type = primitive-type
```
Go to: _[primitive-type](#user-content-primitive-type)_;
<a name="group-coordinate"></a>
```abnf
group-coordinate = ( [ "-" ] numeral ) / "+" / "-" / "_"
```
Go to: _[numeral](#user-content-numeral)_;
<a name="affine-group-literal"></a>
```abnf
affine-group-literal = "(" group-coordinate "," group-coordinate %s")group"
```
Go to: _[group-coordinate](#user-content-group-coordinate)_;
<a name="literal"></a>
```abnf
literal = atomic-literal / affine-group-literal
```
Go to: _[affine-group-literal](#user-content-affine-group-literal), [atomic-literal](#user-content-atomic-literal)_;
<a name="group-literal"></a>
```abnf
group-literal = product-group-literal / affine-group-literal
```
Go to: _[affine-group-literal](#user-content-affine-group-literal), [product-group-literal](#user-content-product-group-literal)_;
<a name="primary-expression"></a>
```abnf
primary-expression = identifier
/ literal
/ "(" expression ")"
/ function-call
```
Go to: _[expression](#user-content-expression), [function-call](#user-content-function-call), [identifier](#user-content-identifier), [literal](#user-content-literal)_;
<a name="function-call"></a>
```abnf
function-call = identifier function-arguments
```
Go to: _[function-arguments](#user-content-function-arguments), [identifier](#user-content-identifier)_;
<a name="function-arguments"></a>
```abnf
function-arguments = "(" [ expression *( "," expression ) [ "," ] ] ")"
```
Go to: _[expression](#user-content-expression)_;
<a name="unary-expression"></a>
```abnf
unary-expression = primary-expression
/ "!" unary-expression
/ "-" unary-expression
```
Go to: _[primary-expression](#user-content-primary-expression), [unary-expression](#user-content-unary-expression)_;
<a name="exponential-expression"></a>
```abnf
exponential-expression = unary-expression
/ unary-expression "**" exponential-expression
```
Go to: _[exponential-expression](#user-content-exponential-expression), [unary-expression](#user-content-unary-expression)_;
<a name="multiplicative-expression"></a>
```abnf
multiplicative-expression = exponential-expression
/ multiplicative-expression "*" exponential-expression
/ multiplicative-expression "/" exponential-expression
```
Go to: _[exponential-expression](#user-content-exponential-expression), [multiplicative-expression](#user-content-multiplicative-expression)_;
<a name="additive-expression"></a>
```abnf
additive-expression = multiplicative-expression
/ additive-expression "+" multiplicative-expression
/ additive-expression "-" multiplicative-expression
```
Go to: _[additive-expression](#user-content-additive-expression), [multiplicative-expression](#user-content-multiplicative-expression)_;
<a name="ordering-expression"></a>
```abnf
ordering-expression = additive-expression
/ additive-expression "<" additive-expression
/ additive-expression ">" additive-expression
/ additive-expression "<=" additive-expression
/ additive-expression ">=" additive-expression
```
Go to: _[additive-expression](#user-content-additive-expression)_;
<a name="equality-expression"></a>
```abnf
equality-expression = ordering-expression
/ ordering-expression "==" ordering-expression
/ ordering-expression "!=" ordering-expression
```
Go to: _[ordering-expression](#user-content-ordering-expression)_;
<a name="conjunctive-expression"></a>
```abnf
conjunctive-expression = equality-expression
/ conjunctive-expression "&&" equality-expression
```
Go to: _[conjunctive-expression](#user-content-conjunctive-expression), [equality-expression](#user-content-equality-expression)_;
<a name="disjunctive-expression"></a>
```abnf
disjunctive-expression = conjunctive-expression
/ disjunctive-expression "||" conjunctive-expression
```
Go to: _[conjunctive-expression](#user-content-conjunctive-expression), [disjunctive-expression](#user-content-disjunctive-expression)_;
<a name="binary-expression"></a>
```abnf
binary-expression = disjunctive-expression
```
Go to: _[disjunctive-expression](#user-content-disjunctive-expression)_;
<a name="conditional-expression"></a>
```abnf
conditional-expression = binary-expression
/ binary-expression "?" expression ":" expression
```
Go to: _[binary-expression](#user-content-binary-expression), [expression](#user-content-expression)_;
<a name="expression"></a>
```abnf
expression = conditional-expression
```
Go to: _[conditional-expression](#user-content-conditional-expression)_;
<a name="statement"></a>
```abnf
statement = return-statement
/ variable-declaration
/ constant-declaration
/ conditional-statement
/ loop-statement
/ assignment-statement
/ console-statement
/ block
```
Go to: _[assignment-statement](#user-content-assignment-statement), [block](#user-content-block), [conditional-statement](#user-content-conditional-statement), [console-statement](#user-content-console-statement), [constant-declaration](#user-content-constant-declaration), [loop-statement](#user-content-loop-statement), [return-statement](#user-content-return-statement), [variable-declaration](#user-content-variable-declaration)_;
<a name="block"></a>
```abnf
block = "{" *statement "}"
```
<a name="return-statement"></a>
```abnf
return-statement = %s"return" expression ";"
```
Go to: _[expression](#user-content-expression)_;
<a name="variable-declaration"></a>
```abnf
variable-declaration = %s"let" identifier ":" type "=" expression ";"
```
Go to: _[expression](#user-content-expression), [identifier](#user-content-identifier), [type](#user-content-type)_;
<a name="constant-declaration"></a>
```abnf
constant-declaration = %s"const" identifier ":" type "=" expression ";"
```
Go to: _[expression](#user-content-expression), [identifier](#user-content-identifier), [type](#user-content-type)_;
<a name="branch"></a>
```abnf
branch = %s"if" expression block
```
Go to: _[block](#user-content-block), [expression](#user-content-expression)_;
<a name="conditional-statement"></a>
```abnf
conditional-statement = branch
/ branch %s"else" block
/ branch %s"else" conditional-statement
```
Go to: _[block](#user-content-block), [branch](#user-content-branch), [conditional-statement](#user-content-conditional-statement)_;
<a name="loop-statement"></a>
```abnf
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), [type](#user-content-type)_;
<a name="assignment-operator"></a>
```abnf
assignment-operator = "="
```
<a name="assignment-statement"></a>
```abnf
assignment-statement = expression assignment-operator expression ";"
```
Go to: _[assignment-operator](#user-content-assignment-operator), [expression](#user-content-expression)_;
<a name="console-statement"></a>
```abnf
console-statement = %s"console" "." console-call ";"
```
Go to: _[console-call](#user-content-console-call)_;
<a name="console-call"></a>
```abnf
console-call = assert-call
/ print-call
```
Go to: _[assert-call](#user-content-assert-call), [print-call](#user-content-print-call)_;
<a name="assert-call"></a>
```abnf
assert-call = %s"assert" "(" expression ")"
```
Go to: _[expression](#user-content-expression)_;
<a name="print-function"></a>
```abnf
print-function = %s"error" / %s"log"
```
<a name="print-arguments"></a>
```abnf
print-arguments = "(" string-literal *( "," expression ) [ "," ] ")"
```
Go to: _[string-literal](#user-content-string-literal)_;
<a name="print-call"></a>
```abnf
print-call = print-function print-arguments
```
Go to: _[print-arguments](#user-content-print-arguments), [print-function](#user-content-print-function)_;
<a name="function-declaration"></a>
```abnf
function-declaration = %s"function" identifier
"(" [ function-parameters ] ")" "->" type
block
```
Go to: _[block](#user-content-block), [function-parameters](#user-content-function-parameters), [identifier](#user-content-identifier), [type](#user-content-type)_;
<a name="function-parameters"></a>
```abnf
function-parameters = function-parameter *( "," function-parameter ) [ "," ]
```
Go to: _[function-parameter](#user-content-function-parameter)_;
<a name="function-parameter"></a>
```abnf
function-parameter = [ %s"public" / %s"constant" / %s"const" ]
identifier ":" type
```
Go to: _[identifier](#user-content-identifier), [type](#user-content-type)_;
<a name="declaration"></a>
```abnf
declaration = function-declaration
```
Go to: _[function-declaration](#user-content-function-declaration)_;
<a name="file"></a>
```abnf
file = *declaration
```
--------
Format String Grammar
---------------------
<a name="not-brace"></a>
```abnf
not-brace = %x0-7A / %x7C / %x7E-10FFFF ; anything but { or }
```
<a name="format-string-container"></a>
```abnf
format-string-container = "{}"
```
<a name="format-string-open-brace"></a>
```abnf
format-string-open-brace = "{{"
```
<a name="format-string-close-brace"></a>
```abnf
format-string-close-brace = "}}"
```
<a name="format-string-element"></a>
```abnf
format-string-element = not-brace
/ format-string-container
/ format-string-open-brace
/ format-string-close-brace
```
Go to: _[format-string-close-brace](#user-content-format-string-close-brace), [format-string-container](#user-content-format-string-container), [format-string-open-brace](#user-content-format-string-open-brace), [not-brace](#user-content-not-brace)_;
<a name="format-string"></a>
```abnf
format-string = *format-string-element
```
--------
Input Grammar
-------------
<a name="input-type"></a>
```abnf
input-type = type
```
Go to: _[type](#user-content-type)_;
<a name="input-expression"></a>
```abnf
input-expression = literal
```
Go to: _[literal](#user-content-literal)_;
<a name="input-item"></a>
```abnf
input-item = identifier ":" input-type "=" input-expression ";"
```
Go to: _[identifier](#user-content-identifier), [input-expression](#user-content-input-expression), [input-type](#user-content-input-type)_;
<a name="input-title"></a>
```abnf
input-title = "[" identifier "]"
```
Go to: _[identifier](#user-content-identifier)_;
<a name="input-section"></a>
```abnf
input-section = input-title *input-item
```
Go to: _[input-title](#user-content-input-title)_;
<a name="input-file"></a>
```abnf
input-file = *input-section

View File

@ -90,6 +90,7 @@ keyword = %s"address"
/ %s"let"
/ %s"public"
/ %s"return"
/ %s"scalar"
/ %s"u8"
/ %s"u16"
/ %s"u32"
@ -121,6 +122,8 @@ field-literal = numeral %s"field"
product-group-literal = numeral %s"group"
scalar-literal = numeral %s"scalar"
boolean-literal = %s"true" / %s"false"
address-literal = %s"aleo1" 58( lowercase-letter / decimal-digit )
@ -164,6 +167,7 @@ integer-literal = unsigned-literal
numeric-literal = integer-literal
/ field-literal
/ product-group-literal
/ scalar-literal
atomic-literal = numeric-literal
/ boolean-literal
@ -205,7 +209,9 @@ field-type = %s"field"
group-type = %s"group"
arithmetic-type = integer-type / field-type / group-type
scalar-type = %s"scalar"
arithmetic-type = integer-type / field-type / group-type / scalar-type
boolean-type = %s"bool"
@ -358,7 +364,7 @@ input-expression = literal
input-item = identifier ":" input-type "=" input-expression ";"
input-title = "[" identifier "]"
input-title = "[" ( %s"public" / %s"private" / %s"constant" / %s"const" ) "]"
input-section = input-title *input-item

View File

@ -358,4 +358,12 @@ create_messages!(
msg: "Unicode bidi override code point encountered.",
help: None,
}
/// Previously, expression statements were allowed, but not anymore.
@formatted
expr_stmts_disallowed {
args: (),
msg: "Expression statements are no longer supported.",
help: None,
}
);

View File

@ -207,7 +207,7 @@ fn set_panic_hook() {
fn main() {
set_panic_hook();
handle_error(create_session_if_not_set_then(|_| run_with_args(Opt::from_args())));
create_session_if_not_set_then(|_| handle_error(run_with_args(Opt::from_args())));
}
/// Run command with custom build arguments.

View File

@ -134,6 +134,7 @@ symbols! {
prelude,
Public,
Return: "return",
scalar,
Star: "*",
std,
Struct: "struct",

View File

@ -45,27 +45,32 @@ generated instead. A PR should contain changes to expectations as well as to tes
Here is the list of all possible configuration options for compiler and parser tests.
#### namespace
### namespace
```
```yaml
- Mandatory: yes
- Namespace: all
- Values: Compile / Parse
- Values: ...
```
Only two values are supported: `Parse` and `Compile`. The former is meant to be a parser test, the latter
is a full compiler test.
Several values are supported, but they vary depending on the directory you are in.
Besides the `Parse` value,
there are actually additional possible values for this field:
`ParseStatement`, `ParseExpression`, and `Token`.
Each one of them allows testing Leo parser on different levels - lexer tokens or just expressions/statements.
Parser Directory namespaces:
Compiler tests always include complete Leo programs.
- `Parse` - Test a file to check that it is a valid Leo program.
- `ParseExpression` - Test a file line by line to check that each line is a valid Leo expression.
- `ParseStatement` - Test a file consuming multiple lines till a blank line to check that it contains a valid Leo statement.
- `Serialize` - Test a file to check that it can be serialized to JSON.
- `Input` - Test an input file to check that it is a valid Leo input file.
- `Token` - Test a file line by line to check that it contains zero or more valid Leo parser tokens.
Compiler Directory namespaces:
- `Compiler` - Test a file to check that it is a valid Leo program, and it can be compiled without errors.
### expectation
```
```yaml
- Mandatory: yes
- Namespace: all
- Values: Pass / Fail
@ -77,7 +82,7 @@ you'll know that something went wrong and the test or the compiler/parser needs
### input_file (Compile)
```
```yaml
- Mandatory: no
- Namespace: Compile
- Values: <input file path>, ...
@ -87,7 +92,7 @@ This setting allows using one or more input files for the Leo program.
The program will be run with every provided input.
See this example:
```
```yaml
/*
namespace: Compile
expectation: Pass

View File

@ -5,5 +5,5 @@ input_file: inputs/one.in
*/
function main(a: group) -> group {
return 1u8 * a;
return 1scalar * a;
}

View File

@ -0,0 +1,10 @@
/*
namespace: Compile
expectation: Pass
input_file:
- inputs/scalars.in
*/
function main(a: scalar, b: scalar, c: scalar) -> bool {
return a + b == c;
}

View File

@ -0,0 +1,14 @@
/*
namespace: Compile
expectation: Pass
input_file:
- inputs/scalars.in
*/
function main(a: scalar, b: scalar) -> bool {
let c: bool = a > b;
let d: bool = a < b;
let e: bool = a >= b;
let f: bool = a <= b;
return f;
}

View File

@ -0,0 +1,10 @@
/*
namespace: Compile
expectation: Pass
input_file:
- inputs/scalars.in
*/
function main(a: scalar, b: scalar, c: scalar) -> bool {
return a / b != c;
}

View File

@ -0,0 +1,12 @@
/*
namespace: Compile
expectation: Pass
input_file:
- inputs/scalars.in
*/
function main(a: scalar, b: scalar) -> bool {
let c: bool = a == b;
let d: bool = a != b;
return d;
}

View File

@ -0,0 +1,15 @@
/*
namespace: Compile
expectation: Pass
input_file:
- inputs/scalar_group.in
*/
function main(a: scalar, b: group, c: scalar) -> bool {
let d: group = 1group * a;
let e: group = a * 1group;
let f: group = b * a;
let g: group = a * b;
return a * g == d;
}

View File

@ -0,0 +1,7 @@
[main]
a: scalar = 1scalar;
b: group = 1group;
c: scalar = 2scalar;
[registers]
r: bool = false;

View File

@ -0,0 +1,7 @@
[main]
a: scalar = 1scalar;
b: scalar = 1scalar;
c: scalar = 2scalar;
[registers]
r: bool = false;

View File

@ -0,0 +1,10 @@
/*
namespace: Compile
expectation: Pass
input_file:
- inputs/scalars.in
*/
function main(a: scalar, b: scalar, c: scalar) -> bool {
return a * b == c;
}

View File

@ -0,0 +1,8 @@
/*
namespace: Compile
expectation: Fail
*/
function main() {
const f = 1 scalar;
}

View File

@ -0,0 +1,11 @@
/*
namespace: Compile
expectation: Pass
input_file:
- inputs/scalars.in
*/
function main(a: scalar) -> bool {
const s: scalar = 1scalar;
return s + a == 0scalar;
}

View File

@ -0,0 +1,10 @@
/*
namespace: Compile
expectation: Pass
input_file:
- inputs/scalars.in
*/
function main(a: scalar, b: scalar, c: scalar) -> bool {
return b == 1scalar ? a == 1scalar : c == 2scalar;
}

View File

@ -15,15 +15,5 @@ function main(k: bool) -> bool {
forward = forward + x;
}
let reverse_inclusive: u32 = 0u32;
for a: u32 in 10u32..=0u32 {
reverse_inclusive = reverse_inclusive + a;
}
let forward_inclusive: u32 = 0u32;
for b: u32 in 0u32..=10u32 {
forward_inclusive = forward_inclusive + b;
}
return (reverse == forward) && (reverse_inclusive == forward_inclusive) && k;
return (reverse == forward) && k;
}

View File

@ -0,0 +1,32 @@
/*
namespace: Compile
expectation: Fail
input_file: inputs/dummy.in
# inclusive loops are currently disallowed
*/
function main(k: bool) -> bool {
let reverse: u32 = 0u32;
for i: u32 in 9u32..0u32 {
reverse = reverse + i;
}
let forward: u32 = 0u32;
for x: u32 in 0u32..10u32 {
forward = forward + x;
}
let reverse_inclusive: u32 = 0u32;
for a: u32 in 10u32..=0u32 {
reverse_inclusive = reverse_inclusive + a;
}
let forward_inclusive: u32 = 0u32;
for b: u32 in 0u32..=10u32 {
forward_inclusive = forward_inclusive + b;
}
return (reverse == forward) && (reverse_inclusive == forward_inclusive) && k;
}

View File

@ -2,4 +2,4 @@
namespace: Compile
expectation: Fail
outputs:
- "Error [ETYC0372003]: Unknown function `my_function`\n --> compiler-test:4:5\n |\n 4 | my_function();\n | ^^^^^^^^^^^\nError [ETYC0372003]: Unknown function `my_function`\n --> compiler-test:4:5\n |\n 4 | my_function();\n | ^^^^^^^^^^^"
- "Error [EPAR0370043]: Expression statements are no longer supported.\n --> compiler-test:4:5\n |\n 4 | my_function();\n | ^^^^^^^^^^^^^^"

View File

@ -2,4 +2,4 @@
namespace: Compile
expectation: Fail
outputs:
- "Error [ETYC0372007]: Expected one type from `i8,i16,i32,i64,i128,u8,u16,u32,u64,u128,`, but got `group`\n --> compiler-test:4:12\n |\n 4 | return (_, _)group * a;\n | ^^^^^^^^^^^^^^^\nError [ETYC0372007]: Expected one type from `i8,i16,i32,i64,i128,u8,u16,u32,u64,u128,`, but got `group`\n --> compiler-test:4:12\n |\n 4 | return (_, _)group * a;\n | ^^^^^^^^^^^^^^^"
- "Error [ETYC0372002]: Found type `group` but type `scalar` was expected\n --> compiler-test:4:12\n |\n 4 | return (_, _)group * a;\n | ^^^^^^^^^^^^^^^\nError [ETYC0372002]: Found type `group` but type `scalar` was expected\n --> compiler-test:4:12\n |\n 4 | return (_, _)group * a;\n | ^^^^^^^^^^^^^^^"

View File

@ -3,6 +3,6 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 4a7d722c26d55d9c1c3067f6d2ef891b2afde9cee26a1043ac78ae2f6ce2e8c1
initial_ast: 0c31dfc043a0f27d955558a8c97370a490309e59c4de6f228b491a02475b6384
symbol_table: 8e39b2bdad6276a42437b673faa0d1dd4f762a9778de1a1e2c8f8edbe5002be4
- initial_input_ast: 1c07a704862cbf7d7938c51d6d840c9ee713f3b6f661a60cca2a81ef3e55efa2
initial_ast: da7d4b5638893ec9b4b7320749934b632d179d7a99c6efcae3897609f666e419
symbol_table: ac787ea8268badd26320c55d7d1b808ca7bfdaac3994570a28e605d637f1cdaf

View File

@ -0,0 +1,8 @@
---
namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 4f141316ffe2f84865d36d0d28d361fdaa90bacf05ff62678d32f901a235ed74
initial_ast: fd4126b8ea19b5afd542aa1c1ad269656d3bf24297470cbdb64b675184f6e698
symbol_table: 892d93d278cb7a474cdf2dfd4a40294a748165ebeeb47cba6dbee3f31d7fd586

View File

@ -0,0 +1,8 @@
---
namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 85349bd16d49ff31c5ed3aeacf84ee6278d4d951409f8b055849eb41481e612e
initial_ast: f9d6d5d94f9aead249bf86205884b49eff222937842973864758c01757d3eafa
symbol_table: 240729bf3dd32b0ff548d132bc74bc91e42a8677f98d5fa1e388259e6a407d95

View File

@ -0,0 +1,8 @@
---
namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 2fdded6208cca2d992178f1ebce1ad848f09f0e7bc5b5a01ee767fafd992737f
initial_ast: c20c79fbafd514aadf1887dea23f564f5e9bbd7c26caf9408bf664a495bfd6aa
symbol_table: eef6184d8de08329af65525b860dea76d00957bbd099b98cb35cc9e22a5c568c

View File

@ -0,0 +1,8 @@
---
namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 33bfdc8b1c15b79c4df536c93be684108ac3f031e23b2a4359f5cdc780ebe6e9
initial_ast: 73e323d6a21198a304ce5691a6cd8a7c1bd449fff01afad7ea83aa57c31a3554
symbol_table: 08cd46bf33b7d8cc59bb80d5716911598c0479cd25e30e00a1b47b175d8e7c0f

View File

@ -0,0 +1,8 @@
---
namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: cf06fc39ca04a486855a4df808362d7a950ecd6fee1bde05bc28011c33404726
initial_ast: 504a536d2f70bff90e1e941b0c30fd95195757c69326e9d168a224c3f9590de5
symbol_table: cb5c8eb4006c52c0092effc2219dbd03b90ab1baf39f345f838ada8a57d1158c

View File

@ -0,0 +1,8 @@
---
namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 4f141316ffe2f84865d36d0d28d361fdaa90bacf05ff62678d32f901a235ed74
initial_ast: c2fe013362376acd540235900ae220eef966bb7a870e6bac2efdcdb66bf96aaa
symbol_table: 1c43e99020a8214e8a0a8ff037a79dc12b597c0801642f5a564e8e4b3e42b679

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- "Error [EPAR0370005]: expected -> -- got '{'\n --> compiler-test:3:17\n |\n 3 | function main() {\n | ^"

View File

@ -0,0 +1,8 @@
---
namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: f074f67a7d4028112cee3c14d6fa831ac71e0776db4f4f793df9dbfc6bd921c3
initial_ast: d6a1be88337def873777e4296959ced20e923c27736200993a3e86992d15eb6e
symbol_table: 85a8380cbcefab3e365d6d3f7acbb54125afedb9b8ff98e4513b147ffe0ccf14

View File

@ -0,0 +1,8 @@
---
namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: 33bfdc8b1c15b79c4df536c93be684108ac3f031e23b2a4359f5cdc780ebe6e9
initial_ast: 0d139bfef33401468cd0ee0591fc2fbb5ddfcc977e4006e6ae8013c73434bbf4
symbol_table: 3044db73279e2416a04d470427a0f319f13ac1dfbe36706b238e1fa2fb068538

View File

@ -3,6 +3,6 @@ namespace: Compile
expectation: Pass
outputs:
- output:
- initial_input_ast: bddb7d656b6cfdeadae66e437c61090a2f14112e48fe4e23ea0e39e1ce03fed0
initial_ast: 66baa9f7e32bb00b0c047250c97ff2710a128e9db63d0a7c0459f7673147e124
symbol_table: 3f85b29e75222f03e70b83cbc2399746f23dbbeabd857acaa486db9e8076c03c
- initial_input_ast: 7f054d619f362422dce83ca5563d462fe3206845a29de38bb3721f3cd2c69c11
initial_ast: 6b833755871962eb67f0a281ef1edd82bf84b0c9f03154f0b7b0330c554826d4
symbol_table: bcf9d66217a3cbfc92d16af68089c9644a316cfb072e3bfd6bd76b5ccea0fc18

View File

@ -0,0 +1,5 @@
---
namespace: Compile
expectation: Fail
outputs:
- "Error [EPAR0370009]: unexpected string: expected 'expression', got '='\n --> compiler-test:15:26\n |\n 15 | for a: u32 in 10u32..=0u32 {\n | ^"

View File

@ -0,0 +1,634 @@
---
namespace: ParseExpression
expectation: Pass
outputs:
- Value:
Scalar:
- "123"
- span:
lo: 0
hi: 9
- Value:
Scalar:
- "123"
- span:
lo: 0
hi: 9
- Value:
Scalar:
- "456"
- span:
lo: 0
hi: 9
- Value:
Scalar:
- "87377802873778028737780287377802873778028737780287377802873778028737780287377802"
- span:
lo: 0
hi: 86
- Value:
Scalar:
- "8737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802"
- span:
lo: 0
hi: 406
- Value:
Scalar:
- "340130024"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "158951116"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "155529659"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "642023166"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "228481736"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "469712960"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "929437719"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "721072814"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "363254789"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "906732565"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "288246391"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "724940549"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "487101620"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "261373583"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "891163927"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "743967544"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "8372586"
- span:
lo: 0
hi: 13
- Value:
Scalar:
- "461793278"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "806307045"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "122764546"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "356336181"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "158370903"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "774460877"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "557174131"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "492401267"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "893445620"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "957757048"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "721540649"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "390746493"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "211251725"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "938266114"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "156985870"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "703831126"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "729964155"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "988151305"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "320872435"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "719287167"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "152289486"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "740067975"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "728627816"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "385008978"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "553967635"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "71980713"
- span:
lo: 0
hi: 14
- Value:
Scalar:
- "519444716"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "116499965"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "717422268"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "18966279"
- span:
lo: 0
hi: 14
- Value:
Scalar:
- "22458638"
- span:
lo: 0
hi: 14
- Value:
Scalar:
- "857282620"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "920675898"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "762235516"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "469018377"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "199986521"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "536679358"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "591399452"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "83083158"
- span:
lo: 0
hi: 14
- Value:
Scalar:
- "599449051"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "445442318"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "585486590"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "209278800"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "873568117"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "664470940"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "465262783"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "605652874"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "376803940"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "965247040"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "598474509"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "845119918"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "648159133"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "669051032"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "800600261"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "434689764"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "520060080"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "804659385"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "537828058"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "716600292"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "387020273"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "199375617"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "680337189"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "818479931"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "893693281"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "87377802"
- span:
lo: 0
hi: 14
- Value:
Scalar:
- "84699261"
- span:
lo: 0
hi: 14
- Value:
Scalar:
- "292826090"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "569171405"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "387436237"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "150682190"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "888770419"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "824696431"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "765659803"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "270163693"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "427940240"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "504997332"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "337808338"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "907200008"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "757177889"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "696697188"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "41376051"
- span:
lo: 0
hi: 14
- Value:
Scalar:
- "496293518"
- span:
lo: 0
hi: 15
- Value:
Scalar:
- "251218820"
- span:
lo: 0
hi: 15

View File

@ -1,127 +1,5 @@
---
namespace: Parse
expectation: Pass
expectation: Fail
outputs:
- name: ""
expected_input: []
functions:
"{\"name\":\"x\",\"span\":\"{\\\"lo\\\":11,\\\"hi\\\":12}\"}":
identifier: "{\"name\":\"x\",\"span\":\"{\\\"lo\\\":11,\\\"hi\\\":12}\"}"
input:
- Variable:
identifier: "{\"name\":\"y\",\"span\":\"{\\\"lo\\\":22,\\\"hi\\\":23}\"}"
mode: Constant
type_:
IntegerType: U32
span:
lo: 22
hi: 23
output:
IntegerType: U8
core_mapping: ~
block:
statements:
- Conditional:
condition:
Binary:
left:
Identifier: "{\"name\":\"y\",\"span\":\"{\\\"lo\\\":45,\\\"hi\\\":46}\"}"
right:
Value:
Integer:
- U32
- "5"
- span:
lo: 49
hi: 53
op: Lt
span:
lo: 45
hi: 53
block:
statements:
- Expression:
expression:
Call:
function:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"lo\\\":64,\\\"hi\\\":65}\"}"
arguments:
- Binary:
left:
Identifier: "{\"name\":\"y\",\"span\":\"{\\\"lo\\\":66,\\\"hi\\\":67}\"}"
right:
Value:
Integer:
- U32
- "1"
- span:
lo: 68
hi: 72
op: Add
span:
lo: 66
hi: 72
span:
lo: 64
hi: 73
span:
lo: 64
hi: 73
span:
lo: 54
hi: 80
next: ~
span:
lo: 42
hi: 80
span:
lo: 36
hi: 82
span:
lo: 2
hi: 82
"{\"name\":\"main\",\"span\":\"{\\\"lo\\\":93,\\\"hi\\\":97}\"}":
identifier: "{\"name\":\"main\",\"span\":\"{\\\"lo\\\":93,\\\"hi\\\":97}\"}"
input:
- Variable:
identifier: "{\"name\":\"y\",\"span\":\"{\\\"lo\\\":98,\\\"hi\\\":99}\"}"
mode: Private
type_: Boolean
span:
lo: 98
hi: 99
output: Boolean
core_mapping: ~
block:
statements:
- Expression:
expression:
Call:
function:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"lo\\\":121,\\\"hi\\\":122}\"}"
arguments:
- Value:
Integer:
- U32
- "1"
- span:
lo: 123
hi: 127
span:
lo: 121
hi: 128
span:
lo: 121
hi: 128
- Return:
expression:
Identifier: "{\"name\":\"y\",\"span\":\"{\\\"lo\\\":141,\\\"hi\\\":142}\"}"
span:
lo: 134
hi: 142
span:
lo: 115
hi: 145
span:
lo: 84
hi: 145
- "Error [EPAR0370043]: Expression statements are no longer supported.\n --> test:5:9\n |\n 5 | x(y+1u32);\n | ^^^^^^^^^^\nError [EPAR0370043]: Expression statements are no longer supported.\n --> test:10:5\n |\n 10 | x(1u32);\n | ^^^^^^^^"

View File

@ -1,71 +1,5 @@
---
namespace: Parse
expectation: Pass
expectation: Fail
outputs:
- name: ""
expected_input: []
functions:
"{\"name\":\"inf\",\"span\":\"{\\\"lo\\\":11,\\\"hi\\\":14}\"}":
identifier: "{\"name\":\"inf\",\"span\":\"{\\\"lo\\\":11,\\\"hi\\\":14}\"}"
input: []
output:
IntegerType: U8
core_mapping: ~
block:
statements:
- Expression:
expression:
Call:
function:
Identifier: "{\"name\":\"inf\",\"span\":\"{\\\"lo\\\":29,\\\"hi\\\":32}\"}"
arguments: []
span:
lo: 29
hi: 34
span:
lo: 29
hi: 34
span:
lo: 23
hi: 37
span:
lo: 2
hi: 37
"{\"name\":\"main\",\"span\":\"{\\\"lo\\\":48,\\\"hi\\\":52}\"}":
identifier: "{\"name\":\"main\",\"span\":\"{\\\"lo\\\":48,\\\"hi\\\":52}\"}"
input:
- Variable:
identifier: "{\"name\":\"y\",\"span\":\"{\\\"lo\\\":53,\\\"hi\\\":54}\"}"
mode: Private
type_: Boolean
span:
lo: 53
hi: 54
output: Boolean
core_mapping: ~
block:
statements:
- Expression:
expression:
Call:
function:
Identifier: "{\"name\":\"inf\",\"span\":\"{\\\"lo\\\":76,\\\"hi\\\":79}\"}"
arguments: []
span:
lo: 76
hi: 81
span:
lo: 76
hi: 81
- Return:
expression:
Identifier: "{\"name\":\"y\",\"span\":\"{\\\"lo\\\":94,\\\"hi\\\":95}\"}"
span:
lo: 87
hi: 95
span:
lo: 70
hi: 98
span:
lo: 39
hi: 98
- "Error [EPAR0370043]: Expression statements are no longer supported.\n --> test:4:5\n |\n 4 | inf();\n | ^^^^^^\nError [EPAR0370043]: Expression statements are no longer supported.\n --> test:8:5\n |\n 8 | inf();\n | ^^^^^^"

View File

@ -125,12 +125,6 @@ outputs:
hi: 6
block:
statements:
- Expression:
expression:
Identifier: "{\"name\":\"expr\",\"span\":\"{\\\"lo\\\":9,\\\"hi\\\":13}\"}"
span:
lo: 9
hi: 13
- Return:
expression:
Value:
@ -138,15 +132,15 @@ outputs:
- U8
- "0"
- span:
lo: 22
hi: 25
lo: 16
hi: 19
span:
lo: 15
hi: 25
lo: 9
hi: 19
span:
lo: 7
hi: 28
hi: 22
next: ~
span:
lo: 0
hi: 28
hi: 22

View File

@ -25,6 +25,7 @@ outputs:
- "Error [EPAR0370009]: unexpected string: expected 'ident', got ','\n --> test:1:10\n |\n 1 | let (x,y,,) = ();\n | ^"
- "Error [EPAR0370009]: unexpected string: expected 'ident', got ','\n --> test:1:6\n |\n 1 | let (,x,y) = ();\n | ^"
- "Error [EPAR0370009]: unexpected string: expected 'ident', got ','\n --> test:1:8\n |\n 1 | let (x,,y) = ();\n | ^"
<<<<<<< HEAD
- "Error [EPAR0370005]: expected 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'field', 'group', 'address', 'bool' -- got '['\n --> test:1:8\n |\n 1 | let x: [u8; (2,,)] = [[0,0], [0,0]];\n | ^"
- "Error [EPAR0370005]: expected 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'field', 'group', 'address', 'bool' -- got 'const'\n --> test:1:8\n |\n 1 | let x: const = expr;\n | ^^^^^"
- "Error [EPAR0370005]: expected 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'field', 'group', 'address', 'bool' -- got 'let'\n --> test:1:10\n |\n 1 | const x: let = expr;\n | ^^^"
@ -32,16 +33,32 @@ outputs:
- "Error [EPAR0370009]: unexpected string: expected 'ident', got '<eof>'\n --> test:1:1\n |\n 1 | let\n | ^^^"
- "Error [EPAR0370005]: expected : -- got '<eof>'\n --> test:1:5\n |\n 1 | let x\n | ^"
- "Error [EPAR0370005]: expected 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'field', 'group', 'address', 'bool' -- got '<eof>'\n --> test:1:6\n |\n 1 | let x:\n | ^"
=======
- "Error [EPAR0370005]: expected 'address', 'bool', 'field', 'group', 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'char', 'scalar' -- got '['\n --> test:1:8\n |\n 1 | let x: [u8; (2,,)] = [[0,0], [0,0]];\n | ^"
- "Error [EPAR0370005]: expected 'address', 'bool', 'field', 'group', 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'char', 'scalar' -- got 'const'\n --> test:1:8\n |\n 1 | let x: const = expr;\n | ^^^^^"
- "Error [EPAR0370005]: expected 'address', 'bool', 'field', 'group', 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'char', 'scalar' -- got 'let'\n --> test:1:10\n |\n 1 | const x: let = expr;\n | ^^^"
- "Error [EPAR0370005]: expected 'address', 'bool', 'field', 'group', 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'char', 'scalar' -- got 'mut'\n --> test:1:8\n |\n 1 | let x: mut = expr;\n | ^^^"
- "Error [EPAR0370009]: unexpected string: expected 'ident', got '<eof>'\n --> test:1:1\n |\n 1 | let\n | ^^^"
- "Error [EPAR0370005]: expected : -- got '<eof>'\n --> test:1:5\n |\n 1 | let x\n | ^"
- "Error [EPAR0370005]: expected 'address', 'bool', 'field', 'group', 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'char', 'scalar' -- got '<eof>'\n --> test:1:6\n |\n 1 | let x:\n | ^"
>>>>>>> 0bf4a923a29cda1c3ed947f1cef81f726e451331
- "Error [EPAR0370005]: expected : -- got '='\n --> test:1:7\n |\n 1 | let x = (a, y]);\n | ^"
- "Error [EPAR0370009]: unexpected string: expected 'ident', got '='\n --> test:1:5\n |\n 1 | let = 1u8;\n | ^"
- "Error [EPAR0370009]: unexpected string: expected 'ident', got ';'\n --> test:1:4\n |\n 1 | let;\n | ^"
- "Error [EPAR0370005]: expected : -- got '1'\n --> test:1:7\n |\n 1 | let x 1u8;\n | ^"
- "Error [EPAR0370005]: expected = -- got ';'\n --> test:1:10\n |\n 1 | let x: u8;\n | ^"
- "Error [EPAR0370005]: expected = -- got '<eof>'\n --> test:1:8\n |\n 1 | let x: u8\n | ^^"
<<<<<<< HEAD
- "Error [EPAR0370005]: expected 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'field', 'group', 'address', 'bool' -- got '='\n --> test:1:8\n |\n 1 | let x: = 1;\n | ^"
- "Error [EPAR0370005]: expected 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'field', 'group', 'address', 'bool' -- got '['\n --> test:1:8\n |\n 1 | let x: [u8] = 1;\n | ^"
- "Error [EPAR0370005]: expected 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'field', 'group', 'address', 'bool' -- got '['\n --> test:1:8\n |\n 1 | let x: [u8;\n | ^"
- "Error [EPAR0370005]: expected 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'field', 'group', 'address', 'bool' -- got '['\n --> test:1:8\n |\n 1 | let x: [u8; 1u8] = [1,\n | ^"
=======
- "Error [EPAR0370005]: expected 'address', 'bool', 'field', 'group', 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'char', 'scalar' -- got '='\n --> test:1:8\n |\n 1 | let x: = 1;\n | ^"
- "Error [EPAR0370005]: expected 'address', 'bool', 'field', 'group', 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'char', 'scalar' -- got '['\n --> test:1:8\n |\n 1 | let x: [u8] = 1;\n | ^"
- "Error [EPAR0370005]: expected 'address', 'bool', 'field', 'group', 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'char', 'scalar' -- got '['\n --> test:1:8\n |\n 1 | let x: [u8;\n | ^"
- "Error [EPAR0370005]: expected 'address', 'bool', 'field', 'group', 'i8', 'i16', 'i32', 'i64', 'i128', 'u8', 'u16', 'u32', 'u64', 'u128', 'char', 'scalar' -- got '['\n --> test:1:8\n |\n 1 | let x: [u8; 1u8] = [1,\n | ^"
>>>>>>> 0bf4a923a29cda1c3ed947f1cef81f726e451331
- "Error [EPAR0370009]: unexpected string: expected 'expression', got ']'\n --> test:1:15\n |\n 1 | let dbg: u8 = ];\n | ^"
- "Error [EPAR0370026]: Could not lex the following content: `🦀: u8 = 0;`."
- "Error [EPAR0370035]: do not put parens around single variable names\n --> test:1:6\n |\n 1 | let (x) = ...;\n | ^\nError [EPAR0370005]: expected : -- got '='\n --> test:1:9\n |\n 1 | let (x) = ...;\n | ^"

View File

@ -1,36 +1,7 @@
---
namespace: ParseStatement
expectation: Pass
expectation: Fail
outputs:
- Expression:
expression:
Identifier: "{\"name\":\"expr\",\"span\":\"{\\\"lo\\\":0,\\\"hi\\\":4}\"}"
span:
lo: 0
hi: 4
- Expression:
expression:
Binary:
left:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"lo\\\":0,\\\"hi\\\":1}\"}"
right:
Identifier: "{\"name\":\"y\",\"span\":\"{\\\"lo\\\":2,\\\"hi\\\":3}\"}"
op: Add
span:
lo: 0
hi: 3
span:
lo: 0
hi: 3
- Expression:
expression:
Call:
function:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"lo\\\":0,\\\"hi\\\":1}\"}"
arguments: []
span:
lo: 0
hi: 3
span:
lo: 0
hi: 3
- "Error [EPAR0370043]: Expression statements are no longer supported.\n --> test:1:1\n |\n 1 | expr;\n | ^^^^^"
- "Error [EPAR0370043]: Expression statements are no longer supported.\n --> test:1:1\n |\n 1 | x+y;\n | ^^^^"
- "Error [EPAR0370043]: Expression statements are no longer supported.\n --> test:1:1\n |\n 1 | x();\n | ^^^^"

View File

@ -40,7 +40,7 @@ outputs:
- "Error [EPAR0370005]: expected : -- got '='\n --> test:1:7\n |\n 1 | let x = a true b;\n | ^"
- "Error [EPAR0370005]: expected : -- got '='\n --> test:1:7\n |\n 1 | let x = a false b;\n | ^"
- "Error [EPAR0370005]: expected : -- got '='\n --> test:1:7\n |\n 1 | let x = a 0 b;\n | ^"
- "did not consume all input: '=' @ 1:3-4\n'b' @ 1:4-5\n';' @ 1:5-6\n"
- "Error [EPAR0370043]: Expression statements are no longer supported.\n --> test:1:1\n |\n 1 | x;=b;\n | ^^"
- "Error [EPAR0370009]: unexpected string: expected 'int or ident', got '='\n --> test:1:3\n |\n 1 | x.=b;\n | ^"
- "Error [EPAR0370005]: expected ; -- got ','\n --> test:1:2\n |\n 1 | x,=b; // 43\n | ^"
- "Error [EPAR0370005]: expected ; -- got '['\n --> test:1:2\n |\n 1 | x[=b;\n | ^"
@ -57,3 +57,8 @@ outputs:
- "Error [EPAR0370009]: unexpected string: expected 'expression', got '='\n --> test:1:4\n |\n 1 | x<==b;\n | ^"
- "Error [EPAR0370005]: expected ; -- got '..'\n --> test:1:2\n |\n 1 | x..=b;\n | ^^"
- "Error [EPAR0370021]: Expected more characters to lex but found none."
- "Error [EPAR0370043]: Expression statements are no longer supported.\n --> test:1:1\n |\n 1 | x==b;\n | ^^^^^"
- "Error [EPAR0370043]: Expression statements are no longer supported.\n --> test:1:1\n |\n 1 | x!=b;\n | ^^^^^"
- "Error [EPAR0370043]: Expression statements are no longer supported.\n --> test:1:1\n |\n 1 | x>=b;\n | ^^^^^"
- "Error [EPAR0370043]: Expression statements are no longer supported.\n --> test:1:1\n |\n 1 | x<=b;\n | ^^^^^"
- "Error [EPAR0370043]: Expression statements are no longer supported.\n --> test:1:1\n |\n 1 | x>=b;\n | ^^^^^"

View File

@ -176,76 +176,6 @@ outputs:
span:
lo: 0
hi: 4
- Expression:
expression:
Binary:
left:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"lo\\\":0,\\\"hi\\\":1}\"}"
right:
Identifier: "{\"name\":\"b\",\"span\":\"{\\\"lo\\\":3,\\\"hi\\\":4}\"}"
op: Eq
span:
lo: 0
hi: 4
span:
lo: 0
hi: 4
- Expression:
expression:
Binary:
left:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"lo\\\":0,\\\"hi\\\":1}\"}"
right:
Identifier: "{\"name\":\"b\",\"span\":\"{\\\"lo\\\":3,\\\"hi\\\":4}\"}"
op: Ne
span:
lo: 0
hi: 4
span:
lo: 0
hi: 4
- Expression:
expression:
Binary:
left:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"lo\\\":0,\\\"hi\\\":1}\"}"
right:
Identifier: "{\"name\":\"b\",\"span\":\"{\\\"lo\\\":3,\\\"hi\\\":4}\"}"
op: Ge
span:
lo: 0
hi: 4
span:
lo: 0
hi: 4
- Expression:
expression:
Binary:
left:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"lo\\\":0,\\\"hi\\\":1}\"}"
right:
Identifier: "{\"name\":\"b\",\"span\":\"{\\\"lo\\\":3,\\\"hi\\\":4}\"}"
op: Le
span:
lo: 0
hi: 4
span:
lo: 0
hi: 4
- Expression:
expression:
Binary:
left:
Identifier: "{\"name\":\"x\",\"span\":\"{\\\"lo\\\":0,\\\"hi\\\":1}\"}"
right:
Identifier: "{\"name\":\"b\",\"span\":\"{\\\"lo\\\":3,\\\"hi\\\":4}\"}"
op: Ge
span:
lo: 0
hi: 4
span:
lo: 0
hi: 4
- Assign:
operation: Assign
assignee:

View File

@ -1,5 +1,5 @@
/*
namespace: Token
namespace: ParseExpression
expectation: Fail
*/

View File

@ -0,0 +1,114 @@
/*
namespace: ParseExpression
expectation: Pass
*/
123scalar
123scalar
456scalar
87377802873778028737780287377802873778028737780287377802873778028737780287377802scalar
8737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802873778028737780287377802scalar
340130024scalar
158951116scalar
155529659scalar
642023166scalar
228481736scalar
469712960scalar
929437719scalar
721072814scalar
363254789scalar
906732565scalar
288246391scalar
724940549scalar
487101620scalar
261373583scalar
891163927scalar
743967544scalar
8372586scalar
461793278scalar
806307045scalar
122764546scalar
356336181scalar
158370903scalar
774460877scalar
557174131scalar
492401267scalar
893445620scalar
957757048scalar
721540649scalar
390746493scalar
211251725scalar
938266114scalar
156985870scalar
703831126scalar
729964155scalar
988151305scalar
320872435scalar
719287167scalar
152289486scalar
740067975scalar
728627816scalar
385008978scalar
553967635scalar
71980713scalar
519444716scalar
116499965scalar
717422268scalar
18966279scalar
22458638scalar
857282620scalar
920675898scalar
762235516scalar
469018377scalar
199986521scalar
536679358scalar
591399452scalar
83083158scalar
599449051scalar
445442318scalar
585486590scalar
209278800scalar
873568117scalar
664470940scalar
465262783scalar
605652874scalar
376803940scalar
965247040scalar
598474509scalar
845119918scalar
648159133scalar
669051032scalar
800600261scalar
434689764scalar
520060080scalar
804659385scalar
537828058scalar
716600292scalar
387020273scalar
199375617scalar
680337189scalar
818479931scalar
893693281scalar
87377802scalar
84699261scalar
292826090scalar
569171405scalar
387436237scalar
150682190scalar
888770419scalar
824696431scalar
765659803scalar
270163693scalar
427940240scalar
504997332scalar
337808338scalar
907200008scalar
757177889scalar
696697188scalar
41376051scalar
496293518scalar
251218820scalar

View File

@ -1,6 +1,6 @@
/*
namespace: Parse
expectation: Pass
expectation: Fail
*/
function x(constant y: u32) -> u8 {
@ -12,4 +12,4 @@ function x(constant y: u32) -> u8 {
function main(y: bool) -> bool {
x(1u32);
return y;
}
}

View File

@ -1,6 +1,6 @@
/*
namespace: Parse
expectation: Pass
expectation: Fail
*/
function inf() -> u8 {
@ -10,4 +10,4 @@ function inf() -> u8 {
function main(y: bool) -> bool {
inf();
return y;
}
}

View File

@ -16,6 +16,5 @@ if (x) {} else {}
if x+y {} else if x+z {} else {}
if x+y {
expr;
return 0u8;
}
}

View File

@ -1,10 +1,10 @@
/*
namespace: ParseStatement
expectation: Pass
expectation: Fail
*/
expr;
x+y;
x();
x();

View File

@ -113,3 +113,13 @@ x<==b;
x..=b;
x&=b;
x==b;
x!=b;
x>=b;
x<=b;
x>=b;

View File

@ -20,16 +20,6 @@ let x: u8 = a > b;
x_=b;
x==b;
x!=b;
x>=b;
x<=b;
x>=b;
xconsole=b;
xconst=b;

View File

@ -0,0 +1,82 @@
# Leo Test Framework
This directory includes the code for the Leo Test Framework.
## How it works
You would first create a rust test file inside the folder of some part of the compiler, as the test framework tests are run by the rust test framework.
### Namespaces
Then you would create a `struct` that represents a `Namespace` where you have to implement the following:
#### Parse Type
Each `namespace` must have a function, `parse_type` that returns a `ParseType`. There are several kinds of `ParseTypes`:
- Line - Parses the File line one by one.
- ContinuousLines - Parses lines continuously as one item until an empty line is encountered.
- Whole - Parses the whole file.
#### Run Test
Each `namespace` must have a function, that runs and dictates how you want the tests for that namespace to work. To make running a test possible you are given information about the test file, like its name, content, path, etc. It allows you to return any type of output to be written to an expectation file as long as it's serializable.
### Runner
Then you would create a `struct` that represents a `Runner` where you have to implement the following:
#### Resolve Namespace
Each test file only needs one runner that represents the namespace resolution to which type of test should be run with a given string.
i.e.
```rust
struct ParseTestRunner;
impl Runner for ParseTestRunner {
fn resolve_namespace(&self, name: &str) -> Option<Box<dyn Namespace>> {
Some(match name {
"Parse" => Box::new(ParseNamespace),
"ParseExpression" => Box::new(ParseExpressionNamespace),
"ParseStatement" => Box::new(ParseStatementNamespace),
"Serialize" => Box::new(SerializeNamespace),
"Input" => Box::new(InputNamespace),
"Token" => Box::new(TokenNamespace),
_ => return None,
})
}
}
```
### Rust test Function
A rust test function that calls the framework over the runner, as well as the name of the directory, is the last thing necessary.
i.e.
```rust
#[test]
pub fn parser_tests() {
// The second argument indicates the directory where tests(.leo files)
// would be found(tests/parser).
leo_test_framework::run_tests(&ParseTestRunner, "parser");
}
```
### Clearing Expectations
To do so you can simply remove the corresponding `.out` file in the `tests/expectations` directory. Doing so will cause the output to be regenerated. There is an easier way to mass change them as well discussed in the next section.
### Test Framework Environment Variables
To make several aspects of the test framework easier to work with there are several environment variables:
- `TEST_FILTER` - runs all tests that contain the specified name.
- `CLEAR_LEO_TEST_EXPECTATIONS` - which if set clears all current expectations and regenerates them all.
To set environment variables please look at your Shell(bash/powershell/cmd/fish/etc) specific implementation for doing so
**NOTE**: Don't forget to clear the environment variable after running it with that setting, or set a temporary env variable if your shell supports it.

View File

@ -22,6 +22,7 @@
//! To regenerate the tests after a syntax change or failing test, delete the [`tests/expectations/`]
//! directory and run the [`parser_tests()`] test in [`parser/src/test.rs`].
#![cfg(not(doctest))] // Don't doctest the markdown.
#![doc = include_str!("../README.md")]
pub mod error;