Implement new control flow syntax
This commit is contained in:
parent
39692b3bd7
commit
574cff5cc6
@ -7,29 +7,52 @@ use crate::{AbstractTree, Expression, Result, Statement, Value, VariableMap};
|
|||||||
pub struct IfElse {
|
pub struct IfElse {
|
||||||
if_expression: Expression,
|
if_expression: Expression,
|
||||||
then_statement: Statement,
|
then_statement: Statement,
|
||||||
|
else_if_expressions: Vec<Expression>,
|
||||||
|
else_if_statements: Vec<Statement>,
|
||||||
else_statement: Option<Statement>,
|
else_statement: Option<Statement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AbstractTree for IfElse {
|
impl AbstractTree for IfElse {
|
||||||
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
fn from_syntax_node(node: Node, source: &str) -> Result<Self> {
|
||||||
let if_node = node.child(1).unwrap();
|
let if_node = node.child(0).unwrap().child(1).unwrap();
|
||||||
let if_expression = Expression::from_syntax_node(if_node, source)?;
|
let if_expression = Expression::from_syntax_node(if_node, source)?;
|
||||||
|
|
||||||
let then_node = node.child(3).unwrap();
|
let then_node = node.child(0).unwrap().child(3).unwrap();
|
||||||
let then_statement = Statement::from_syntax_node(then_node, source)?;
|
let then_statement = Statement::from_syntax_node(then_node, source)?;
|
||||||
|
|
||||||
let else_node = node.child(5);
|
let child_count = node.child_count();
|
||||||
let else_statement = if let Some(node) = else_node {
|
let mut else_if_expressions = Vec::new();
|
||||||
Some(Statement::from_syntax_node(node, source)?)
|
let mut else_if_statements = Vec::new();
|
||||||
} else {
|
let mut else_statement = None;
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
println!("{if_node:?} {then_node:?} {else_node:?}");
|
for index in 1..child_count {
|
||||||
|
let child = node.child(index);
|
||||||
|
|
||||||
|
if let Some(node) = child {
|
||||||
|
if node.kind() == "else_if" {
|
||||||
|
let expression_node = node.child(1).unwrap();
|
||||||
|
let expression = Expression::from_syntax_node(expression_node, source)?;
|
||||||
|
|
||||||
|
else_if_expressions.push(expression);
|
||||||
|
|
||||||
|
let statement_node = node.child(3).unwrap();
|
||||||
|
let statement = Statement::from_syntax_node(statement_node, source)?;
|
||||||
|
|
||||||
|
else_if_statements.push(statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
if node.kind() == "else" {
|
||||||
|
let else_node = node.child(2).unwrap();
|
||||||
|
else_statement = Some(Statement::from_syntax_node(else_node, source)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(IfElse {
|
Ok(IfElse {
|
||||||
if_expression,
|
if_expression,
|
||||||
then_statement,
|
then_statement,
|
||||||
|
else_if_expressions,
|
||||||
|
else_if_statements,
|
||||||
else_statement,
|
else_statement,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -39,10 +62,24 @@ impl AbstractTree for IfElse {
|
|||||||
|
|
||||||
if if_boolean {
|
if if_boolean {
|
||||||
self.then_statement.run(context)
|
self.then_statement.run(context)
|
||||||
} else if let Some(statement) = &self.else_statement {
|
} else {
|
||||||
|
let expressions = &self.else_if_expressions;
|
||||||
|
|
||||||
|
for (index, expression) in expressions.into_iter().enumerate() {
|
||||||
|
let if_boolean = expression.run(context)?.as_boolean()?;
|
||||||
|
|
||||||
|
if if_boolean {
|
||||||
|
let statement = self.else_if_statements.get(index).unwrap();
|
||||||
|
|
||||||
|
return statement.run(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(statement) = &self.else_statement {
|
||||||
statement.run(context)
|
statement.run(context)
|
||||||
} else {
|
} else {
|
||||||
Ok(Value::Empty)
|
Ok(Value::Empty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,8 @@ impl<'context, 'code> Evaluator<'context, 'code> {
|
|||||||
let root_node = cursor.node();
|
let root_node = cursor.node();
|
||||||
let mut prev_result = Ok(Value::Empty);
|
let mut prev_result = Ok(Value::Empty);
|
||||||
|
|
||||||
|
println!("{}", root_node.to_sexp());
|
||||||
|
|
||||||
for item_node in root_node.children(&mut cursor) {
|
for item_node in root_node.children(&mut cursor) {
|
||||||
let item = Item::from_syntax_node(item_node, self.source)?;
|
let item = Item::from_syntax_node(item_node, self.source)?;
|
||||||
prev_result = item.run(self.context);
|
prev_result = item.run(self.context);
|
||||||
@ -188,18 +190,18 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn evaluate_if_then() {
|
fn evaluate_if() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
evaluate("if true then 'true'"),
|
evaluate("if true { 'true' }"),
|
||||||
Ok(Value::String("true".to_string()))
|
Ok(Value::String("true".to_string()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn evaluate_if_then_else() {
|
fn evaluate_if_else() {
|
||||||
assert_eq!(evaluate("if false then 1 else 2"), Ok(Value::Integer(2)));
|
assert_eq!(evaluate("if false { 1 } else { 2 }"), Ok(Value::Integer(2)));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
evaluate("if true then 1.0 else 42.0"),
|
evaluate("if true { 1.0 } else { 42.0 }"),
|
||||||
Ok(Value::Float(1.0))
|
Ok(Value::Float(1.0))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -209,12 +211,13 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
evaluate(
|
evaluate(
|
||||||
"
|
"
|
||||||
if false
|
if false {
|
||||||
then 'no'
|
'no'
|
||||||
else if 1 + 1 == 3
|
} else if 1 + 1 == 3 {
|
||||||
then 'nope'
|
'nope'
|
||||||
else
|
} else {
|
||||||
'ok'
|
'ok'
|
||||||
|
}
|
||||||
"
|
"
|
||||||
),
|
),
|
||||||
Ok(Value::String("ok".to_string()))
|
Ok(Value::String("ok".to_string()))
|
||||||
@ -226,15 +229,17 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
evaluate(
|
evaluate(
|
||||||
"
|
"
|
||||||
if false
|
if false {
|
||||||
then 'no'
|
'no'
|
||||||
else if 1 + 1 == 1
|
} else if 1 + 1 == 1 {
|
||||||
then 'nope'
|
'nope'
|
||||||
else if 9 / 2 == 4
|
} else if 9 / 2 == 4 {
|
||||||
then 'nope'
|
'nope'
|
||||||
else if 'foo' == 'bar'
|
} else if 'foo' == 'bar' {
|
||||||
then 'nope'
|
'nope'
|
||||||
else 'ok'
|
} else {
|
||||||
|
'ok'
|
||||||
|
}
|
||||||
"
|
"
|
||||||
),
|
),
|
||||||
Ok(Value::String("ok".to_string()))
|
Ok(Value::String("ok".to_string()))
|
||||||
|
Loading…
Reference in New Issue
Block a user