impl loop and add tests for both unary operators and loops
This commit is contained in:
parent
679f0de6b6
commit
caf8a411aa
@ -1153,6 +1153,19 @@ impl Engine {
|
||||
}
|
||||
}
|
||||
}
|
||||
Stmt::Loop(ref body) => {
|
||||
loop {
|
||||
match self.eval_stmt(scope, body) {
|
||||
Err(EvalAltResult::LoopBreak) => {
|
||||
return Ok(Box::new(()));
|
||||
}
|
||||
Err(x) => {
|
||||
return Err(x);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
Stmt::Break => Err(EvalAltResult::LoopBreak),
|
||||
Stmt::Return => Err(EvalAltResult::Return(Box::new(()))),
|
||||
Stmt::ReturnWithVal(ref a) => {
|
||||
|
@ -90,6 +90,7 @@ pub enum Stmt {
|
||||
If(Box<Expr>, Box<Stmt>),
|
||||
IfElse(Box<Expr>, Box<Stmt>, Box<Stmt>),
|
||||
While(Box<Expr>, Box<Stmt>),
|
||||
Loop(Box<Stmt>),
|
||||
Var(String, Option<Box<Expr>>),
|
||||
Block(Vec<Stmt>),
|
||||
Expr(Box<Expr>),
|
||||
@ -142,6 +143,7 @@ pub enum Token {
|
||||
If,
|
||||
Else,
|
||||
While,
|
||||
Loop,
|
||||
LessThan,
|
||||
GreaterThan,
|
||||
Bang,
|
||||
@ -398,6 +400,7 @@ impl<'a> TokenIterator<'a> {
|
||||
"if" => return Some(Token::If),
|
||||
"else" => return Some(Token::Else),
|
||||
"while" => return Some(Token::While),
|
||||
"loop" => return Some(Token::Loop),
|
||||
"break" => return Some(Token::Break),
|
||||
"return" => return Some(Token::Return),
|
||||
"fn" => return Some(Token::Fn),
|
||||
@ -805,6 +808,14 @@ fn parse_while<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Stmt, Pars
|
||||
Ok(Stmt::While(Box::new(guard), Box::new(body)))
|
||||
}
|
||||
|
||||
fn parse_loop<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Stmt, ParseError> {
|
||||
input.next();
|
||||
|
||||
let body = try!(parse_block(input));
|
||||
|
||||
Ok(Stmt::Loop(Box::new(body)))
|
||||
}
|
||||
|
||||
fn parse_var<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Stmt, ParseError> {
|
||||
input.next();
|
||||
|
||||
@ -868,6 +879,7 @@ fn parse_stmt<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Stmt, Parse
|
||||
match input.peek() {
|
||||
Some(&Token::If) => parse_if(input),
|
||||
Some(&Token::While) => parse_while(input),
|
||||
Some(&Token::Loop) => parse_loop(input),
|
||||
Some(&Token::Break) => {
|
||||
input.next();
|
||||
Ok(Stmt::Break)
|
||||
|
47
src/tests.rs
47
src/tests.rs
@ -410,3 +410,50 @@ fn test_comments() {
|
||||
|
||||
assert!(engine.eval::<i64>("let /* I am a multiline comment, yay! */ x = 5; x").is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unary_minus() {
|
||||
let mut engine = Engine::new();
|
||||
|
||||
assert_eq!(engine.eval::<i64>("let x = -5; x").unwrap(), -5);
|
||||
|
||||
assert_eq!(engine.eval::<i64>("fn n(x) { -x } n(5)").unwrap(), -5);
|
||||
|
||||
assert_eq!(engine.eval::<i64>("5 - -(-5)").unwrap(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not() {
|
||||
let mut engine = Engine::new();
|
||||
|
||||
assert_eq!(engine.eval::<bool>("let not_true = !true; not_true").unwrap(), false);
|
||||
|
||||
assert_eq!(engine.eval::<bool>("fn not(x) { !x } not(false)").unwrap(), true);
|
||||
|
||||
// TODO - do we allow stacking unary operators directly? e.g '!!!!!!!true'
|
||||
assert_eq!(engine.eval::<bool>("!(!(!(!(true))))").unwrap(), true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_loop() {
|
||||
let mut engine = Engine::new();
|
||||
|
||||
assert!(
|
||||
engine.eval::<bool>("
|
||||
let x = 0;
|
||||
let i = 0;
|
||||
|
||||
loop {
|
||||
if i < 10 {
|
||||
x = x + i;
|
||||
i = i + 1;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
x == 45
|
||||
").unwrap()
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user