1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00

refactor experimentation with simple identifier list

This commit is contained in:
schaeff 2018-01-22 21:58:34 +01:00
parent 0c9923d15d
commit 56ef08597a
4 changed files with 94 additions and 117 deletions

View file

@ -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)
},
}
}

View file

@ -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))])
);

View file

@ -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]

View file

@ -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(