Remove expressions from break statements
This commit is contained in:
parent
780ea0858b
commit
565fd450a9
@ -53,22 +53,15 @@ impl AbstractTree for Loop {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
|
||||||
abstract_tree::{Expression, ValueNode},
|
|
||||||
Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn basic_loop() {
|
fn basic_loop() {
|
||||||
let result = Loop {
|
let result = Loop {
|
||||||
statements: vec![Statement::Break(Some(Expression::Value(
|
statements: vec![Statement::Break],
|
||||||
ValueNode::Integer(42),
|
|
||||||
)))],
|
|
||||||
}
|
}
|
||||||
.run(&Context::new());
|
.run(&Context::new());
|
||||||
|
|
||||||
assert_eq!(result, Ok(Action::Break(Some(Value::integer(42)))))
|
assert_eq!(result, Ok(Action::Break))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ pub trait AbstractTree {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub enum Action {
|
pub enum Action {
|
||||||
Break(Option<Value>),
|
Break,
|
||||||
Return(Value),
|
Return(Value),
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
@ -50,15 +50,8 @@ pub enum Action {
|
|||||||
impl Action {
|
impl Action {
|
||||||
pub fn as_value(self) -> Result<Value, ValidationError> {
|
pub fn as_value(self) -> Result<Value, ValidationError> {
|
||||||
match self {
|
match self {
|
||||||
Action::Break(value) => {
|
|
||||||
if let Some(value) = value {
|
|
||||||
Ok(value)
|
|
||||||
} else {
|
|
||||||
Err(ValidationError::ExpectedValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Action::Return(value) => Ok(value),
|
Action::Return(value) => Ok(value),
|
||||||
Action::None => Err(ValidationError::ExpectedValue),
|
_ => Err(ValidationError::ExpectedValue),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ use super::{AbstractTree, Action, Assignment, Block, Expression, IfElse, Loop, T
|
|||||||
pub enum Statement {
|
pub enum Statement {
|
||||||
Assignment(Assignment),
|
Assignment(Assignment),
|
||||||
Block(Block),
|
Block(Block),
|
||||||
Break(Option<Expression>),
|
Break,
|
||||||
Expression(Expression),
|
Expression(Expression),
|
||||||
IfElse(IfElse),
|
IfElse(IfElse),
|
||||||
Loop(Loop),
|
Loop(Loop),
|
||||||
@ -20,13 +20,7 @@ impl AbstractTree for Statement {
|
|||||||
match self {
|
match self {
|
||||||
Statement::Assignment(assignment) => assignment.expected_type(_context),
|
Statement::Assignment(assignment) => assignment.expected_type(_context),
|
||||||
Statement::Block(block) => block.expected_type(_context),
|
Statement::Block(block) => block.expected_type(_context),
|
||||||
Statement::Break(expression_option) => {
|
Statement::Break => Ok(Type::None),
|
||||||
if let Some(expression) = expression_option {
|
|
||||||
expression.expected_type(_context)
|
|
||||||
} else {
|
|
||||||
Ok(Type::None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Statement::Expression(expression) => expression.expected_type(_context),
|
Statement::Expression(expression) => expression.expected_type(_context),
|
||||||
Statement::IfElse(if_else) => if_else.expected_type(_context),
|
Statement::IfElse(if_else) => if_else.expected_type(_context),
|
||||||
Statement::Loop(r#loop) => r#loop.expected_type(_context),
|
Statement::Loop(r#loop) => r#loop.expected_type(_context),
|
||||||
@ -37,13 +31,7 @@ impl AbstractTree for Statement {
|
|||||||
match self {
|
match self {
|
||||||
Statement::Assignment(assignment) => assignment.validate(_context),
|
Statement::Assignment(assignment) => assignment.validate(_context),
|
||||||
Statement::Block(block) => block.validate(_context),
|
Statement::Block(block) => block.validate(_context),
|
||||||
Statement::Break(expression_option) => {
|
Statement::Break => Ok(()),
|
||||||
if let Some(expression) = expression_option {
|
|
||||||
expression.validate(_context)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Statement::Expression(expression) => expression.validate(_context),
|
Statement::Expression(expression) => expression.validate(_context),
|
||||||
Statement::IfElse(if_else) => if_else.validate(_context),
|
Statement::IfElse(if_else) => if_else.validate(_context),
|
||||||
Statement::Loop(r#loop) => r#loop.validate(_context),
|
Statement::Loop(r#loop) => r#loop.validate(_context),
|
||||||
@ -54,15 +42,7 @@ impl AbstractTree for Statement {
|
|||||||
match self {
|
match self {
|
||||||
Statement::Assignment(assignment) => assignment.run(_context),
|
Statement::Assignment(assignment) => assignment.run(_context),
|
||||||
Statement::Block(block) => block.run(_context),
|
Statement::Block(block) => block.run(_context),
|
||||||
Statement::Break(expression) => {
|
Statement::Break => Ok(Action::Break),
|
||||||
if let Some(expression) = expression {
|
|
||||||
let value = expression.run(_context)?.as_return_value()?;
|
|
||||||
|
|
||||||
Ok(Action::Break(Some(value)))
|
|
||||||
} else {
|
|
||||||
Ok(Action::Break(None))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Statement::Expression(expression) => expression.run(_context),
|
Statement::Expression(expression) => expression.run(_context),
|
||||||
Statement::IfElse(if_else) => if_else.run(_context),
|
Statement::IfElse(if_else) => if_else.run(_context),
|
||||||
Statement::Loop(r#loop) => r#loop.run(_context),
|
Statement::Loop(r#loop) => r#loop.run(_context),
|
||||||
|
@ -53,13 +53,7 @@ impl Interpreter {
|
|||||||
for (statement, _span) in statements {
|
for (statement, _span) in statements {
|
||||||
value = match statement.run(&self.context) {
|
value = match statement.run(&self.context) {
|
||||||
Ok(action) => match action {
|
Ok(action) => match action {
|
||||||
Action::Break(value_option) => {
|
Action::Break => None,
|
||||||
if let Some(value) = value_option {
|
|
||||||
Some(value)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Action::Return(value) => Some(value),
|
Action::Return(value) => Some(value),
|
||||||
Action::None => continue,
|
Action::None => continue,
|
||||||
},
|
},
|
||||||
|
@ -304,9 +304,7 @@ pub fn parser<'src>() -> DustParser<'src> {
|
|||||||
.map(|expression| Statement::Expression(expression))
|
.map(|expression| Statement::Expression(expression))
|
||||||
.boxed();
|
.boxed();
|
||||||
|
|
||||||
let r#break = just(Token::Keyword("break"))
|
let r#break = just(Token::Keyword("break")).to(Statement::Break);
|
||||||
.ignore_then(expression.clone().or_not())
|
|
||||||
.map(|expression| Statement::Break(expression));
|
|
||||||
|
|
||||||
let assignment = identifier
|
let assignment = identifier
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -17,7 +17,22 @@ fn loops_and_breaks() {
|
|||||||
"
|
"
|
||||||
),
|
),
|
||||||
Ok(Some(Value::integer(3)))
|
Ok(Some(Value::integer(3)))
|
||||||
)
|
);
|
||||||
|
assert_eq!(
|
||||||
|
interpret(
|
||||||
|
"
|
||||||
|
foobar = {
|
||||||
|
while true {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
'foobar'
|
||||||
|
}
|
||||||
|
|
||||||
|
foobar
|
||||||
|
"
|
||||||
|
),
|
||||||
|
Ok(Some(Value::string("foobar".to_string())))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user