1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

simplify pest ast, add tests for from_ast

This commit is contained in:
schaeff 2019-08-28 18:11:58 +02:00
parent b901055077
commit a634b1cf80
4 changed files with 196 additions and 15 deletions

View file

@ -530,7 +530,7 @@ impl<'ast> From<pest::Type<'ast>> for Type {
pest::BasicType::Boolean(_) => Type::Boolean,
};
t.size
t.dimensions
.into_iter()
.map(|s| match s {
pest::Expression::Constant(c) => match c {
@ -668,4 +668,186 @@ mod tests {
assert_eq!(absy::Module::<FieldPrime>::from(ast), expected);
}
mod types {
use super::*;
/// Helper method to generate the ast for `def main(private {ty} a) -> (): return` which we use to check ty
fn wrap(ty: types::Type) -> absy::Module<'static, FieldPrime> {
absy::Module {
functions: vec![absy::FunctionDeclaration {
id: "main",
symbol: absy::FunctionSymbol::Here(
absy::Function {
arguments: vec![absy::Parameter::private(
absy::Variable::new("a", ty.clone()).into(),
)
.into()],
statements: vec![absy::Statement::Return(
absy::ExpressionList {
expressions: vec![],
}
.into(),
)
.into()],
signature: absy::Signature::new().inputs(vec![ty]),
}
.into(),
),
}
.into()],
imports: vec![],
}
}
#[test]
fn array() {
let vectors = vec![
("field", types::Type::FieldElement),
("bool", types::Type::Boolean),
(
"field[2]",
types::Type::Array(box types::Type::FieldElement, 2),
),
(
"field[2][3]",
types::Type::Array(box Type::Array(box types::Type::FieldElement, 2), 3),
),
(
"bool[2][3]",
types::Type::Array(box Type::Array(box types::Type::Boolean, 2), 3),
),
];
for (ty, expected) in vectors {
let source = format!("def main(private {} a) -> (): return", ty);
let expected = wrap(expected);
let ast = pest::generate_ast(&source).unwrap();
assert_eq!(absy::Module::<FieldPrime>::from(ast), expected);
}
}
}
mod postfix {
use super::*;
fn wrap(expression: absy::Expression<'static, FieldPrime>) -> absy::Module<FieldPrime> {
absy::Module {
functions: vec![absy::FunctionDeclaration {
id: "main",
symbol: absy::FunctionSymbol::Here(
absy::Function {
arguments: vec![],
statements: vec![absy::Statement::Return(
absy::ExpressionList {
expressions: vec![expression.into()],
}
.into(),
)
.into()],
signature: absy::Signature::new(),
}
.into(),
),
}
.into()],
imports: vec![],
}
}
#[test]
fn success() {
// we basically accept `()?[]*` : an optional call at first, then only array accesses
let vectors = vec![
("a", absy::Expression::Identifier("a").into()),
(
"a[3]",
absy::Expression::Select(
box absy::Expression::Identifier("a").into(),
box absy::RangeOrExpression::Expression(
absy::Expression::FieldConstant(FieldPrime::from(3)).into(),
)
.into(),
),
),
(
"a[3][4]",
absy::Expression::Select(
box absy::Expression::Select(
box absy::Expression::Identifier("a").into(),
box absy::RangeOrExpression::Expression(
absy::Expression::FieldConstant(FieldPrime::from(3)).into(),
)
.into(),
)
.into(),
box absy::RangeOrExpression::Expression(
absy::Expression::FieldConstant(FieldPrime::from(4)).into(),
)
.into(),
),
),
(
"a(3)[4]",
absy::Expression::Select(
box absy::Expression::FunctionCall(
"a",
vec![absy::Expression::FieldConstant(FieldPrime::from(3)).into()],
)
.into(),
box absy::RangeOrExpression::Expression(
absy::Expression::FieldConstant(FieldPrime::from(4)).into(),
)
.into(),
),
),
(
"a(3)[4][5]",
absy::Expression::Select(
box absy::Expression::Select(
box absy::Expression::FunctionCall(
"a",
vec![absy::Expression::FieldConstant(FieldPrime::from(3)).into()],
)
.into(),
box absy::RangeOrExpression::Expression(
absy::Expression::FieldConstant(FieldPrime::from(4)).into(),
)
.into(),
)
.into(),
box absy::RangeOrExpression::Expression(
absy::Expression::FieldConstant(FieldPrime::from(5)).into(),
)
.into(),
),
),
];
for (source, expected) in vectors {
let source = format!("def main() -> (): return {}", source);
let expected = wrap(expected);
let ast = pest::generate_ast(&source).unwrap();
assert_eq!(absy::Module::<FieldPrime>::from(ast), expected);
}
}
#[test]
#[should_panic]
fn call_array_element() {
// a call after an array access should be rejected
let source = "def main() -> (): return a[2](3)";
let ast = pest::generate_ast(&source).unwrap();
absy::Module::<FieldPrime>::from(ast);
}
#[test]
#[should_panic]
fn call_call_result() {
// a call after a call should be rejected
let source = "def main() -> (): return a(2)(3)";
let ast = pest::generate_ast(&source).unwrap();
absy::Module::<FieldPrime>::from(ast);
}
}
}

View file

@ -505,7 +505,9 @@ impl<'ast, T: Field> fmt::Debug for Expression<'ast, T> {
f.debug_list().entries(exprs.iter()).finish()?;
write!(f, "]")
}
Expression::Select(ref array, ref index) => write!(f, "{}[{}]", array, index),
Expression::Select(ref array, ref index) => {
write!(f, "Select({:?}, {:?})", array, index)
}
Expression::Or(ref lhs, ref rhs) => write!(f, "{} || {}", lhs, rhs),
}
}

View file

@ -691,7 +691,7 @@ impl<'ast> Checker<'ast> {
pos: Some(pos),
message: format!(
"Expected spread operator to apply on field element array, found {}",
"Expected spread operator to apply on array, found {}",
e.get_type()
),
}),

View file

@ -9,8 +9,8 @@ extern crate lazy_static;
pub use ast::{
Access, ArrayAccess, ArrayInitializerExpression, ArrayType, AssertionStatement, Assignee,
AssignmentStatement, BasicType, BinaryExpression, BinaryOperator, CallAccess,
ConstantExpression, DefinitionStatement, Expression, File, FromExpression, Function,
AssignmentStatement, BasicType, BinaryExpression, BinaryOperator, BooleanType, CallAccess,
ConstantExpression, DefinitionStatement, Expression, FieldType, File, FromExpression, Function,
IdentifierExpression, ImportDirective, ImportSource, InlineArrayExpression, IterationStatement,
MultiAssignmentStatement, Parameter, PostfixExpression, Range, RangeOrExpression,
ReturnStatement, Span, Spread, SpreadOrExpression, Statement, TernaryExpression, ToExpression,
@ -193,36 +193,33 @@ mod ast {
#[derive(Debug, FromPest, PartialEq, Clone)]
#[pest_ast(rule(Rule::ty))]
pub enum Type<'ast> {
Basic(BasicType<'ast>),
Basic(BasicType),
Array(ArrayType<'ast>),
}
#[derive(Debug, FromPest, PartialEq, Clone)]
#[pest_ast(rule(Rule::ty_basic))]
pub enum BasicType<'ast> {
pub enum BasicType {
Field(FieldType),
Boolean(BooleanType<'ast>),
Boolean(BooleanType),
}
#[derive(Debug, FromPest, PartialEq, Clone)]
#[pest_ast(rule(Rule::ty_field))]
pub struct FieldType {}
pub struct FieldType;
#[derive(Debug, FromPest, PartialEq, Clone)]
#[pest_ast(rule(Rule::ty_array))]
pub struct ArrayType<'ast> {
pub ty: BasicType<'ast>,
pub size: Vec<Expression<'ast>>,
pub ty: BasicType,
pub dimensions: Vec<Expression<'ast>>,
#[pest_ast(outer())]
pub span: Span<'ast>,
}
#[derive(Debug, FromPest, PartialEq, Clone)]
#[pest_ast(rule(Rule::ty_bool))]
pub struct BooleanType<'ast> {
#[pest_ast(outer())]
pub span: Span<'ast>,
}
pub struct BooleanType;
#[derive(Debug, FromPest, PartialEq, Clone)]
#[pest_ast(rule(Rule::parameter))]