refactor experimentation with simple identifier list
This commit is contained in:
parent
0c9923d15d
commit
56ef08597a
4 changed files with 94 additions and 117 deletions
12
src/absy.rs
12
src/absy.rs
|
@ -145,7 +145,7 @@ pub enum Statement<T: Field> {
|
|||
Condition(Expression<T>, Expression<T>),
|
||||
For(String, T, T, Vec<Statement<T>>),
|
||||
Compiler(String, Expression<T>),
|
||||
MultipleDefinition(Expression<T>, Expression<T>),
|
||||
MultipleDefinition(Vec<String>, Expression<T>),
|
||||
}
|
||||
|
||||
impl<T: Field> Statement<T> {
|
||||
|
@ -177,8 +177,14 @@ impl<T: Field> fmt::Display for Statement<T> {
|
|||
write!(f, "\tendfor")
|
||||
}
|
||||
Statement::Compiler(ref lhs, ref rhs) => write!(f, "# {} = {}", lhs, rhs),
|
||||
Statement::MultipleDefinition(ref lhs, ref rhs) => {
|
||||
write!(f, "{} = {}", lhs, rhs)
|
||||
Statement::MultipleDefinition(ref ids, ref rhs) => {
|
||||
for (i, id) in ids.iter().enumerate() {
|
||||
try!(write!(f, "{}", id));
|
||||
if i < ids.len() - 1 {
|
||||
try!(write!(f, ", "));
|
||||
}
|
||||
}
|
||||
write!(f, " = {}", rhs)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -620,44 +620,33 @@ impl Flattener {
|
|||
}
|
||||
}
|
||||
ref s @ Statement::Compiler(..) => statements_flattened.push(s.clone()),
|
||||
Statement::MultipleDefinition(ref e1, ref e2) => {
|
||||
match *e1 {
|
||||
Expression::List(ref exprs) => {
|
||||
match *e2 {
|
||||
FunctionCall(..) => {
|
||||
let expr_subbed = e2.apply_substitution(&self.substitution);
|
||||
let rhs = self.flatten_expression(
|
||||
functions_flattened,
|
||||
arguments_flattened,
|
||||
statements_flattened,
|
||||
expr_subbed,
|
||||
);
|
||||
Statement::MultipleDefinition(ref ids, ref e2) => {
|
||||
match *e2 {
|
||||
FunctionCall(..) => {
|
||||
let expr_subbed = e2.apply_substitution(&self.substitution);
|
||||
let rhs = self.flatten_expression(
|
||||
functions_flattened,
|
||||
arguments_flattened,
|
||||
statements_flattened,
|
||||
expr_subbed,
|
||||
);
|
||||
|
||||
match rhs {
|
||||
Expression::List(rhslis) => {
|
||||
let rhslist = rhslis.clone();
|
||||
for (i, exp) in exprs.into_iter().enumerate() {
|
||||
match *exp {
|
||||
Expression::Identifier(ref id) => {
|
||||
let var = self.use_variable(&id);
|
||||
// handle return of function call
|
||||
let var_to_replace = self.get_latest_var_substitution(&id);
|
||||
if !(var == var_to_replace) && self.variables.contains(&var_to_replace) && !self.substitution.contains_key(&var_to_replace){
|
||||
self.substitution.insert(var_to_replace.clone().to_string(),var.clone());
|
||||
}
|
||||
statements_flattened.push(Statement::Definition(var, rhslist[i].clone()));
|
||||
},
|
||||
_ => panic!("Only identifiers can be on the left side of a definition")
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => panic!("")
|
||||
match rhs {
|
||||
Expression::List(rhslist) => {
|
||||
for (i, id) in ids.into_iter().enumerate() {
|
||||
let var = self.use_variable(&id);
|
||||
// handle return of function call
|
||||
let var_to_replace = self.get_latest_var_substitution(&id);
|
||||
if !(var == var_to_replace) && self.variables.contains(&var_to_replace) && !self.substitution.contains_key(&var_to_replace){
|
||||
self.substitution.insert(var_to_replace.clone().to_string(),var.clone());
|
||||
}
|
||||
statements_flattened.push(Statement::Definition(var, rhslist[i].clone()));
|
||||
}
|
||||
},
|
||||
_ => panic!("")
|
||||
_ => panic!("rhs should flatten to a List, semantics failed")
|
||||
}
|
||||
},
|
||||
_ => panic!("")
|
||||
_ => panic!("rhs should be a function call")
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -784,12 +773,10 @@ mod multiple_definition {
|
|||
let arguments_flattened = vec![];
|
||||
let mut statements_flattened = vec![];
|
||||
let statement = Statement::MultipleDefinition(
|
||||
Expression::List(
|
||||
vec![
|
||||
Expression::Identifier("a".to_string()),
|
||||
Expression::Identifier("b".to_string())
|
||||
]
|
||||
),
|
||||
vec![
|
||||
"a".to_string(),
|
||||
"b".to_string()
|
||||
],
|
||||
Expression::FunctionCall("foo".to_string(), vec![])
|
||||
);
|
||||
|
||||
|
@ -830,12 +817,10 @@ mod multiple_definition {
|
|||
let arguments_flattened = vec![];
|
||||
let mut statements_flattened = vec![];
|
||||
let statement = Statement::MultipleDefinition(
|
||||
Expression::List(
|
||||
vec![
|
||||
Expression::Identifier("a".to_string()),
|
||||
Expression::Identifier("b".to_string())
|
||||
]
|
||||
),
|
||||
vec![
|
||||
"a".to_string(),
|
||||
"b".to_string()
|
||||
],
|
||||
Expression::FunctionCall("dup".to_string(), vec![Expression::Number(FieldPrime::from(2))])
|
||||
);
|
||||
|
||||
|
|
|
@ -792,17 +792,14 @@ fn parse_function_call<T: Field>(
|
|||
}
|
||||
|
||||
// parse an expression list starting with an identifier
|
||||
fn parse_expression_list1<T: Field>(
|
||||
fn parse_identifier_list1<T: Field>(
|
||||
head: String,
|
||||
input: String,
|
||||
pos: Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
) -> Result<(Vec<String>, String, Position), Error<T>> {
|
||||
let mut res = Vec::new();
|
||||
res.push(Expression::Identifier(head));
|
||||
match parse_comma_separated_list_rec(input, pos, &mut res) {
|
||||
Ok((list, s1, p1)) => Ok((Expression::List(list), s1, p1)),
|
||||
Err(err) => Err(err)
|
||||
}
|
||||
res.push(head);
|
||||
parse_comma_separated_identifier_list_rec(input, pos, &mut res)
|
||||
}
|
||||
|
||||
// parse an expression list
|
||||
|
@ -811,7 +808,7 @@ fn parse_expression_list<T: Field>(
|
|||
pos: Position,
|
||||
) -> Result<(Expression<T>, String, Position), Error<T>> {
|
||||
let mut res = Vec::new();
|
||||
match parse_comma_separated_list_rec(input, pos, &mut res) {
|
||||
match parse_comma_separated_expression_list_rec(input, pos, &mut res) {
|
||||
Ok((list, s1, p1)) => Ok((Expression::List(list), s1, p1)),
|
||||
Err(err) => Err(err)
|
||||
}
|
||||
|
@ -891,7 +888,7 @@ fn parse_statement1<T: Field>(
|
|||
},
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
(Token::Comma, s1, p1) => match parse_expression_list1(ide, s1, p1) { // if we find a comma, parse the rest of the destructure
|
||||
(Token::Comma, s1, p1) => match parse_identifier_list1(ide, s1, p1) { // if we find a comma, parse the rest of the destructure
|
||||
Ok((e2, s2, p2)) => match next_token(&s2, &p2) { // then we should have an equal sign
|
||||
(Token::Eq, s3, p3) => match parse_expr(&s3, &p3) {
|
||||
Ok((e4, s4, p4)) => {
|
||||
|
@ -1445,7 +1442,7 @@ pub fn parse_program<T: Field>(file: File) -> Result<Prog<T>, Error<T>> {
|
|||
Ok(Prog { functions })
|
||||
}
|
||||
|
||||
fn parse_comma_separated_list_rec<T: Field>(
|
||||
fn parse_comma_separated_expression_list_rec<T: Field>(
|
||||
input: String,
|
||||
pos: Position,
|
||||
mut acc: &mut Vec<Expression<T>>
|
||||
|
@ -1454,14 +1451,35 @@ fn parse_comma_separated_list_rec<T: Field>(
|
|||
Ok((e1, s1, p1)) => {
|
||||
acc.push(e1);
|
||||
match next_token::<FieldPrime>(&s1, &p1) {
|
||||
(Token::Comma, s2, p2) => parse_comma_separated_list_rec(s2, p2, &mut acc),
|
||||
(_, _, _) => Ok((acc.to_vec(), s1, p1)),
|
||||
(Token::Comma, s2, p2) => parse_comma_separated_expression_list_rec(s2, p2, &mut acc),
|
||||
(..) => Ok((acc.to_vec(), s1, p1)),
|
||||
}
|
||||
},
|
||||
Err(err) => Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_comma_separated_identifier_list_rec<T: Field>(
|
||||
input: String,
|
||||
pos: Position,
|
||||
mut acc: &mut Vec<String>
|
||||
) -> Result<(Vec<String>, String, Position), Error<T>> {
|
||||
match next_token(&input, &pos) {
|
||||
(Token::Ide(id), s1, p1) => {
|
||||
acc.push(id);
|
||||
match next_token::<FieldPrime>(&s1, &p1) {
|
||||
(Token::Comma, s2, p2) => parse_comma_separated_identifier_list_rec(s2, p2, &mut acc),
|
||||
(..) => Ok((acc.to_vec(), s1, p1)),
|
||||
}
|
||||
},
|
||||
(t1, _, p1) => Err(Error {
|
||||
expected: vec![Token::Ide(String::from("ide"))],
|
||||
got: t1,
|
||||
pos: p1,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
@ -1651,18 +1669,7 @@ mod tests {
|
|||
pos: Position
|
||||
) -> Result<(Vec<Expression<T>>, String, Position), Error<T>> {
|
||||
let mut res = Vec::new();
|
||||
parse_comma_separated_list_rec(input, pos, &mut res)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn comma_separated_list1() {
|
||||
let pos = Position { line: 45, col: 121 };
|
||||
let string = String::from("b, c");
|
||||
let expr = Expression::List::<FieldPrime>(vec![Expression::Identifier(String::from("a")),Expression::Identifier(String::from("b")),Expression::Identifier(String::from("c"))]);
|
||||
assert_eq!(
|
||||
Ok((expr, String::from(""), pos.col(string.len() as isize))),
|
||||
parse_expression_list1(String::from("a"), string, pos)
|
||||
)
|
||||
parse_comma_separated_expression_list_rec(input, pos, &mut res)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -115,51 +115,30 @@ impl Checker {
|
|||
self.level -= 1;
|
||||
Ok(())
|
||||
},
|
||||
Statement::MultipleDefinition(e1, e2) => {
|
||||
match e1 {
|
||||
// left side has to be a List
|
||||
Expression::List(ref values) => {
|
||||
let mut identifiers = Vec::new();
|
||||
let all_identifiers = values.into_iter().fold(true, |acc, x| {
|
||||
match x.clone() {
|
||||
Expression::Identifier(i) => {
|
||||
identifiers.push(i);
|
||||
acc && true
|
||||
},
|
||||
_ => false
|
||||
}
|
||||
});
|
||||
match all_identifiers {
|
||||
// All elements of the left side have to be identifiers
|
||||
true => {
|
||||
match e2 {
|
||||
// Right side has to be a function call
|
||||
Expression::FunctionCall(id, arguments) => {
|
||||
match self.find_function(id, arguments) {
|
||||
// the function has to be defined
|
||||
Some(f) => {
|
||||
if f.return_count == values.len() {
|
||||
// the return count has to match the left side
|
||||
for id in identifiers {
|
||||
self.scope.insert(Symbol {
|
||||
id: id.to_string(),
|
||||
level: self.level
|
||||
});
|
||||
}
|
||||
return Ok(())
|
||||
}
|
||||
Err(format!("{:?} returns {} values but left side is of size {}", f.id, f.return_count, values.len()))
|
||||
},
|
||||
None => Err(format!("Function definition for function ??? with ??? argument(s) not found."))
|
||||
}
|
||||
},
|
||||
_ => Err(format!("{:?} should be a FunctionCall", e2))
|
||||
}
|
||||
Statement::MultipleDefinition(ids, rhs) => {
|
||||
// All elements of the left side have to be identifiers
|
||||
match rhs {
|
||||
// Right side has to be a function call
|
||||
Expression::FunctionCall(fun_id, arguments) => {
|
||||
match self.find_function(fun_id, arguments) {
|
||||
// the function has to be defined
|
||||
Some(f) => {
|
||||
if f.return_count == ids.len() {
|
||||
// the return count has to match the left side
|
||||
for id in ids {
|
||||
self.scope.insert(Symbol {
|
||||
id: id.to_string(),
|
||||
level: self.level
|
||||
});
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
Err(format!("{:?} returns {} values but left side is of size {}", f.id, f.return_count, ids.len()))
|
||||
},
|
||||
_ => Err(format!("{:?} should be a List of Identifiers", e1))
|
||||
None => Err(format!("Function definition for function ??? with ??? argument(s) not found."))
|
||||
}
|
||||
},
|
||||
_ => Err(format!("{:?} should be a List", e1))
|
||||
_ => Err(format!("{:?} should be a FunctionCall", rhs))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -412,7 +391,7 @@ mod tests {
|
|||
// c = foo()
|
||||
// should fail
|
||||
let bar_statements: Vec<Statement<FieldPrime>> = vec![Statement::MultipleDefinition(
|
||||
Expression::List(vec![Expression::Identifier("c".to_string())]),
|
||||
vec!["c".to_string()],
|
||||
Expression::FunctionCall("foo".to_string(), vec![])
|
||||
)];
|
||||
|
||||
|
@ -442,7 +421,7 @@ mod tests {
|
|||
// c = foo()
|
||||
// should fail
|
||||
let bar_statements: Vec<Statement<FieldPrime>> = vec![Statement::MultipleDefinition(
|
||||
Expression::List(vec![Expression::Identifier("c".to_string())]),
|
||||
vec!["c".to_string()],
|
||||
Expression::FunctionCall("foo".to_string(), vec![])
|
||||
)];
|
||||
|
||||
|
@ -491,7 +470,7 @@ mod tests {
|
|||
// should pass
|
||||
let bar_statements: Vec<Statement<FieldPrime>> = vec![
|
||||
Statement::MultipleDefinition(
|
||||
Expression::List(vec![Expression::Identifier("a".to_string()), Expression::Identifier("b".to_string())]),
|
||||
vec!["a".to_string(), "b".to_string()],
|
||||
Expression::FunctionCall("foo".to_string(), vec![])
|
||||
),
|
||||
Statement::Return(
|
||||
|
|
Loading…
Reference in a new issue