Implement new control flow syntax

This commit is contained in:
Jeff 2023-10-09 17:01:30 -04:00
parent 39692b3bd7
commit 574cff5cc6
2 changed files with 73 additions and 31 deletions

View File

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

View File

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