simplify pest ast, add tests for from_ast
This commit is contained in:
parent
b901055077
commit
a634b1cf80
4 changed files with 196 additions and 15 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
),
|
||||
}),
|
||||
|
|
|
@ -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))]
|
||||
|
|
Loading…
Reference in a new issue