mirror of
https://github.com/powdr-labs/powdr.git
synced 2026-04-20 03:03:25 -04:00
Array literals in expressions.
This commit is contained in:
@@ -589,6 +589,7 @@ impl<T: FieldElement> ASMPILConverter<T> {
|
||||
Expression::Number(value) => vec![(value, AffineExpressionComponent::Constant)],
|
||||
Expression::String(_) => panic!(),
|
||||
Expression::Tuple(_) => panic!(),
|
||||
Expression::ArrayLiteral(_) => panic!(),
|
||||
Expression::MatchExpression(_, _) => panic!(),
|
||||
Expression::FreeInput(expr) => {
|
||||
vec![(1.into(), AffineExpressionComponent::FreeInput(*expr))]
|
||||
|
||||
@@ -433,6 +433,7 @@ impl<T: Display, Ref: Display> Display for Expression<T, Ref> {
|
||||
Expression::String(value) => write!(f, "\"{value}\""), // TODO quote?
|
||||
Expression::Tuple(items) => write!(f, "({})", format_expressions(items)),
|
||||
Expression::LambdaExpression(lambda) => write!(f, "{}", lambda),
|
||||
Expression::ArrayLiteral(array) => write!(f, "{array}"),
|
||||
Expression::BinaryOperation(left, op, right) => write!(f, "({left} {op} {right})"),
|
||||
Expression::UnaryOperation(op, exp) => write!(f, "{op}{exp}"),
|
||||
Expression::FunctionCall(fun_call) => write!(f, "{fun_call}"),
|
||||
@@ -504,6 +505,12 @@ impl<T: Display, Ref: Display> Display for LambdaExpression<T, Ref> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Display, Ref: Display> Display for ArrayLiteral<T, Ref> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
write!(f, "[{}]", self.items.iter().format(", "))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for BinaryOperator {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
write!(
|
||||
|
||||
@@ -66,6 +66,7 @@ pub enum Expression<T, Ref = ShiftedPolynomialReference<T>> {
|
||||
String(String),
|
||||
Tuple(Vec<Expression<T, Ref>>),
|
||||
LambdaExpression(LambdaExpression<T, Ref>),
|
||||
ArrayLiteral(ArrayLiteral<T, Ref>),
|
||||
BinaryOperation(
|
||||
Box<Expression<T, Ref>>,
|
||||
BinaryOperator,
|
||||
@@ -271,6 +272,11 @@ pub struct LambdaExpression<T, Ref = ShiftedPolynomialReference<T>> {
|
||||
pub body: Box<Expression<T, Ref>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct ArrayLiteral<T, Ref = ShiftedPolynomialReference<T>> {
|
||||
pub items: Vec<Expression<T, Ref>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
||||
pub enum UnaryOperator {
|
||||
Plus,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::{iter::once, ops::ControlFlow};
|
||||
|
||||
use super::{
|
||||
ArrayExpression, Expression, FunctionCall, FunctionDefinition, LambdaExpression, MatchArm,
|
||||
PilStatement,
|
||||
ArrayExpression, ArrayLiteral, Expression, FunctionCall, FunctionDefinition, LambdaExpression,
|
||||
MatchArm, PilStatement,
|
||||
};
|
||||
|
||||
/// Visits `expr` and all of its sub-expressions and returns true if `f` returns true on any of them.
|
||||
@@ -111,6 +111,7 @@ where
|
||||
previsit_expression(e, f)?
|
||||
}
|
||||
Expression::Tuple(items)
|
||||
| Expression::ArrayLiteral(ArrayLiteral { items })
|
||||
| Expression::FunctionCall(FunctionCall {
|
||||
id: _,
|
||||
arguments: items,
|
||||
@@ -152,6 +153,7 @@ where
|
||||
previsit_expression_mut(e.as_mut(), f)?
|
||||
}
|
||||
Expression::Tuple(items)
|
||||
| Expression::ArrayLiteral(ArrayLiteral { items })
|
||||
| Expression::FunctionCall(FunctionCall {
|
||||
arguments: items, ..
|
||||
}) => items
|
||||
@@ -190,6 +192,7 @@ where
|
||||
postvisit_expression_mut(e.as_mut(), f)?
|
||||
}
|
||||
Expression::Tuple(items)
|
||||
| Expression::ArrayLiteral(ArrayLiteral { items })
|
||||
| Expression::FunctionCall(FunctionCall {
|
||||
arguments: items, ..
|
||||
}) => items
|
||||
|
||||
@@ -311,6 +311,7 @@ impl<'a, T: FieldElement> Exporter<'a, T> {
|
||||
Expression::FunctionCall(_) => panic!("No function calls allowed here."),
|
||||
Expression::String(_) => panic!("Strings not allowed here."),
|
||||
Expression::Tuple(_) => panic!("Tuples not allowed here"),
|
||||
Expression::ArrayLiteral(_) => panic!("Array literals not allowed here"),
|
||||
Expression::MatchExpression(_, _) => {
|
||||
panic!("No match expressions allowed here.")
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@ impl<'a, T: FieldElement> Evaluator<'a, T> {
|
||||
Expression::Number(n) => *n,
|
||||
Expression::String(_) => panic!(),
|
||||
Expression::Tuple(_) => panic!(),
|
||||
Expression::ArrayLiteral(_) => panic!(),
|
||||
Expression::BinaryOperation(left, op, right) => {
|
||||
evaluate_binary_operation(self.evaluate(left), *op, self.evaluate(right))
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ mod test {
|
||||
SelectedExpressions,
|
||||
};
|
||||
use number::GoldilocksField;
|
||||
use parser_util::UnwrapErrToStderr;
|
||||
use std::fs;
|
||||
use test_log::test;
|
||||
|
||||
@@ -115,11 +116,7 @@ mod test {
|
||||
));
|
||||
|
||||
let input = fs::read_to_string(file).unwrap();
|
||||
parse(Some(name), &input).unwrap_or_else(|err| {
|
||||
eprintln!("Parse error during test:");
|
||||
err.output_to_stderr();
|
||||
panic!();
|
||||
})
|
||||
parse(Some(name), &input).unwrap_err_to_stderr()
|
||||
}
|
||||
|
||||
fn parse_asm_file(name: &str) -> ASMProgram<GoldilocksField> {
|
||||
@@ -129,11 +126,7 @@ mod test {
|
||||
));
|
||||
|
||||
let input = fs::read_to_string(file).unwrap();
|
||||
parse_asm(Some(name), &input).unwrap_or_else(|err| {
|
||||
eprintln!("Parse error during test:");
|
||||
err.output_to_stderr();
|
||||
panic!();
|
||||
})
|
||||
parse_asm(Some(name), &input).unwrap_err_to_stderr()
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -195,6 +188,7 @@ mod test {
|
||||
mod display {
|
||||
use number::GoldilocksField;
|
||||
|
||||
use parser_util::UnwrapErrToStderr;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use crate::parse;
|
||||
@@ -248,5 +242,15 @@ public out = y(%last_row);"#;
|
||||
);
|
||||
assert_eq!(input.trim(), printed.trim());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_literals() {
|
||||
let input = r#"let x = [[1], [2], [(3 + 7)]];"#;
|
||||
let printed = format!(
|
||||
"{}",
|
||||
parse::<GoldilocksField>(Some("input"), input).unwrap_err_to_stderr()
|
||||
);
|
||||
assert_eq!(input.trim(), printed.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,6 +457,7 @@ Term: Box<Expression<T>> = {
|
||||
FieldElement => Box::new(Expression::Number(<>)),
|
||||
StringLiteral => Box::new(Expression::String(<>)),
|
||||
MatchExpression,
|
||||
"[" <items:ExpressionList> "]" => Box::new(Expression::ArrayLiteral(ArrayLiteral{items})),
|
||||
"(" <head:Expression> "," <tail:ExpressionList> ")" => { let mut list = vec![head]; list.extend(tail); Box::new(Expression::Tuple(list)) },
|
||||
"(" <BoxedExpression> ")",
|
||||
"${" <BoxedExpression> "}" => Box::new(Expression::FreeInput(<>))
|
||||
|
||||
@@ -57,3 +57,24 @@ pub fn handle_parse_error<'a>(
|
||||
message: format!("{err}"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience trait that outputs parser errors to stderr and panics.
|
||||
/// Should be used mostly in tests.
|
||||
pub trait UnwrapErrToStderr {
|
||||
type Inner;
|
||||
fn unwrap_err_to_stderr(self) -> Self::Inner;
|
||||
}
|
||||
|
||||
impl<'a, T> UnwrapErrToStderr for Result<T, ParseError<'a>> {
|
||||
type Inner = T;
|
||||
|
||||
fn unwrap_err_to_stderr(self) -> Self::Inner {
|
||||
match self {
|
||||
Ok(r) => r,
|
||||
Err(err) => {
|
||||
err.output_to_stderr();
|
||||
panic!("Parse error.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ use std::path::{Path, PathBuf};
|
||||
use analysis::MacroExpander;
|
||||
use ast::parsed::utils::postvisit_expression_mut;
|
||||
use ast::parsed::{
|
||||
self, ArrayExpression, BinaryOperator, FunctionDefinition, LambdaExpression, MatchArm,
|
||||
MatchPattern, PilStatement, PolynomialName, UnaryOperator,
|
||||
self, ArrayExpression, ArrayLiteral, BinaryOperator, FunctionDefinition, LambdaExpression,
|
||||
MatchArm, MatchPattern, PilStatement, PolynomialName, UnaryOperator,
|
||||
};
|
||||
use number::{DegreeType, FieldElement};
|
||||
|
||||
@@ -521,6 +521,11 @@ impl<T: FieldElement> PILContext<T> {
|
||||
PExpression::Number(n) => Expression::Number(n),
|
||||
PExpression::String(value) => Expression::String(value),
|
||||
PExpression::Tuple(items) => Expression::Tuple(self.process_expressions(items)),
|
||||
PExpression::ArrayLiteral(ArrayLiteral { items }) => {
|
||||
Expression::ArrayLiteral(ArrayLiteral {
|
||||
items: self.process_expressions(items),
|
||||
})
|
||||
}
|
||||
PExpression::LambdaExpression(LambdaExpression { params, body }) => {
|
||||
Expression::LambdaExpression(LambdaExpression {
|
||||
params,
|
||||
@@ -618,6 +623,7 @@ impl<T: FieldElement> PILContext<T> {
|
||||
Number(n) => Some(*n),
|
||||
String(_) => None,
|
||||
Tuple(_) => None,
|
||||
ArrayLiteral(_) => None,
|
||||
LambdaExpression(_) => None,
|
||||
BinaryOperation(left, op, right) => self.evaluate_binary_operation(left, *op, right),
|
||||
UnaryOperation(op, value) => self.evaluate_unary_operation(*op, value),
|
||||
|
||||
Reference in New Issue
Block a user