1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

add identifiers to scope in multiple definition

This commit is contained in:
schaeff 2018-01-22 18:58:11 +01:00
parent e7ca2ab9e1
commit 0c9923d15d
2 changed files with 63 additions and 4 deletions

View file

@ -0,0 +1,5 @@
def foo():
return 1, 2
def main():
a, b = foo()
return a + b

View file

@ -116,26 +116,36 @@ impl Checker {
Ok(()) Ok(())
}, },
Statement::MultipleDefinition(e1, e2) => { Statement::MultipleDefinition(e1, e2) => {
println!("{:?} = {:?}", e1, e2);
match e1 { match e1 {
// left side has to be a List
Expression::List(ref values) => { Expression::List(ref values) => {
println!("{:?}", values); let mut identifiers = Vec::new();
let all_identifiers = values.into_iter().fold(true, |acc, x| { let all_identifiers = values.into_iter().fold(true, |acc, x| {
match x.clone() { match x.clone() {
Expression::Identifier(_) => { Expression::Identifier(i) => {
identifiers.push(i);
acc && true acc && true
}, },
_ => false _ => false
} }
}); });
match all_identifiers { match all_identifiers {
// All elements of the left side have to be identifiers
true => { true => {
match e2 { match e2 {
// Right side has to be a function call
Expression::FunctionCall(id, arguments) => { Expression::FunctionCall(id, arguments) => {
println!("{:?} , {:?}", id, arguments);
match self.find_function(id, arguments) { match self.find_function(id, arguments) {
// the function has to be defined
Some(f) => { Some(f) => {
if f.return_count == values.len() { 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(()) return Ok(())
} }
Err(format!("{:?} returns {} values but left side is of size {}", f.id, f.return_count, values.len())) Err(format!("{:?} returns {} values but left side is of size {}", f.id, f.return_count, values.len()))
@ -469,4 +479,48 @@ mod tests {
let mut checker = Checker::new_with_args(HashSet::new(), 0, HashSet::new()); let mut checker = Checker::new_with_args(HashSet::new(), 0, HashSet::new());
assert_eq!(checker.check_function(bar), Err(("\"a\" is undefined".to_string()))); assert_eq!(checker.check_function(bar), Err(("\"a\" is undefined".to_string())));
} }
#[test]
fn multi_def() {
// def foo():
// return 1, 2
// def bar():
// a, b = foo()
// return a + b
//
// should pass
let bar_statements: Vec<Statement<FieldPrime>> = vec![
Statement::MultipleDefinition(
Expression::List(vec![Expression::Identifier("a".to_string()), Expression::Identifier("b".to_string())]),
Expression::FunctionCall("foo".to_string(), vec![])
),
Statement::Return(
Expression::List(vec![
Expression::Add(
box Expression::Identifier("a".to_string()),
box Expression::Identifier("b".to_string())
)]
)
)
];
let foo = FunctionDeclaration {
id: "foo".to_string(),
arg_count: 0,
return_count: 2,
};
let mut functions = HashSet::new();
functions.insert(foo);
let bar = Function {
id: "bar".to_string(),
arguments: vec![],
statements: bar_statements,
return_count: 1
};
let mut checker = Checker::new_with_args(HashSet::new(), 0, functions);
assert_eq!(checker.check_function(bar), Ok(()));
}
} }