Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions ast/src/reducer/canonicalization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,20 @@ impl ReconstructingReducer for Canonicalizer {
}
}

fn reduce_string(&mut self, string: &[char], span: &Span) -> Result<Expression, ReducerError> {
let mut elements = Vec::new();
for character in string {
elements.push(SpreadOrExpression::Expression(Expression::Value(
ValueExpression::Char(*character, span.clone()),
)));
}

Ok(Expression::ArrayInline(ArrayInlineExpression {
elements,
span: span.clone(),
}))
}

fn reduce_array_init(
&mut self,
array_init: &ArrayInitExpression,
Expand Down
13 changes: 9 additions & 4 deletions ast/src/reducer/reconstructing_director.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
pub fn reduce_expression(&mut self, expression: &Expression) -> Result<Expression, ReducerError> {
let new = match expression {
Expression::Identifier(identifier) => Expression::Identifier(self.reduce_identifier(&identifier)?),
Expression::Value(value) => Expression::Value(self.reduce_value(&value)?),
Expression::Value(value) => self.reduce_value(&value)?,
Expression::Binary(binary) => Expression::Binary(self.reduce_binary(&binary)?),
Expression::Unary(unary) => Expression::Unary(self.reduce_unary(&unary)?),
Expression::Ternary(ternary) => Expression::Ternary(self.reduce_ternary(&ternary)?),
Expand Down Expand Up @@ -100,12 +100,17 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
self.reducer.reduce_group_value(group_value, new)
}

pub fn reduce_value(&mut self, value: &ValueExpression) -> Result<ValueExpression, ReducerError> {
pub fn reduce_string(&mut self, string: &[char], span: &Span) -> Result<Expression, ReducerError> {
self.reducer.reduce_string(string, span)
}

pub fn reduce_value(&mut self, value: &ValueExpression) -> Result<Expression, ReducerError> {
let new = match value {
ValueExpression::Group(group_value) => {
ValueExpression::Group(Box::new(self.reduce_group_value(&group_value)?))
Expression::Value(ValueExpression::Group(Box::new(self.reduce_group_value(&group_value)?)))
}
_ => value.clone(),
ValueExpression::String(string, span) => self.reduce_string(&string, &span)?,
_ => Expression::Value(value.clone()),
};

self.reducer.reduce_value(value, new)
Expand Down
13 changes: 8 additions & 5 deletions ast/src/reducer/reconstructing_reducer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,14 @@ pub trait ReconstructingReducer {
Ok(new)
}

fn reduce_value(
&mut self,
_value: &ValueExpression,
new: ValueExpression,
) -> Result<ValueExpression, ReducerError> {
fn reduce_string(&mut self, string: &[char], span: &Span) -> Result<Expression, ReducerError> {
Ok(Expression::Value(ValueExpression::String(
string.to_vec(),
span.clone(),
)))
}

fn reduce_value(&mut self, _value: &ValueExpression, new: Expression) -> Result<Expression, ReducerError> {
Ok(new)
}

Expand Down
8 changes: 3 additions & 5 deletions compiler/src/phases/reducing_director.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,7 @@ impl<R: ReconstructingReducer, O: CombinerOptions> CombineAstAsgDirector<R, O> {
asg: &AsgExpression,
) -> Result<AstExpression, ReducerError> {
let new = match (ast, asg) {
(AstExpression::Value(value), AsgExpression::Constant(const_)) => {
AstExpression::Value(self.reduce_value(&value, &const_)?)
}
(AstExpression::Value(value), AsgExpression::Constant(const_)) => self.reduce_value(&value, &const_)?,
(AstExpression::Binary(ast), AsgExpression::Binary(asg)) => {
AstExpression::Binary(self.reduce_binary(&ast, &asg)?)
}
Expand Down Expand Up @@ -404,7 +402,7 @@ impl<R: ReconstructingReducer, O: CombinerOptions> CombineAstAsgDirector<R, O> {
self.ast_reducer.reduce_unary(ast, inner, ast.op.clone())
}

pub fn reduce_value(&mut self, ast: &ValueExpression, asg: &AsgConstant) -> Result<ValueExpression, ReducerError> {
pub fn reduce_value(&mut self, ast: &ValueExpression, asg: &AsgConstant) -> Result<AstExpression, ReducerError> {
let mut new = ast.clone();

if self.options.type_inference_enabled() {
Expand Down Expand Up @@ -444,7 +442,7 @@ impl<R: ReconstructingReducer, O: CombinerOptions> CombineAstAsgDirector<R, O> {
}
}

self.ast_reducer.reduce_value(ast, new)
self.ast_reducer.reduce_value(ast, AstExpression::Value(new))
}

pub fn reduce_variable_ref(
Expand Down
20 changes: 14 additions & 6 deletions compiler/src/value/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,22 @@ impl<'a, F: PrimeField, G: GroupType<F>> fmt::Display for ConstrainedValue<'a, F

// Data type wrappers
ConstrainedValue::Array(ref array) => {
write!(f, "[")?;
for (i, e) in array.iter().enumerate() {
write!(f, "{}", e)?;
if i < array.len() - 1 {
write!(f, ", ")?;
if matches!(array[0], ConstrainedValue::Char(_)) {
for character in array {
write!(f, "{}", character)?;
}

Ok(())
} else {
write!(f, "[")?;
for (i, e) in array.iter().enumerate() {
write!(f, "{}", e)?;
if i < array.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, "]")
}
write!(f, "]")
}
ConstrainedValue::Tuple(ref tuple) => {
let values = tuple.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(", ");
Expand Down
13 changes: 13 additions & 0 deletions compiler/tests/canonicalization/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,16 @@ fn test_illegal_array_range_fail() {
let program = parse_program(program_string);
assert!(program.is_err());
}

#[test]
fn test_string_transformation() {
let program_string = include_str!("string_transformation.leo");
let program = parse_program(program_string).unwrap();
assert_satisfied(program);

let ast = parse_program_ast(program_string);
let expected_json = include_str!("string_transformation.json");
let expected_ast: Ast = Ast::from_json_string(expected_json).expect("Unable to parse json.");

assert_eq!(expected_ast, ast);
}
Loading