Add support for infinite for() loops (#259)

This commit is contained in:
William Wallace 2021-04-22 01:59:41 +01:00 committed by GitHub
parent 15291e493e
commit ba09a43447
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 23 additions and 4 deletions

View file

@ -1366,6 +1366,12 @@ impl<'o, 's> AnalyzeProc<'o, 's> {
allterm.finalize();
return allterm
},
Statement::ForInfinite { block } => {
let mut scoped_locals = local_vars.clone();
let mut state = self.visit_block(block, &mut scoped_locals);
state.end_loop();
return state
}
Statement::ForLoop { init, test, inc, block } => {
let mut scoped_locals = local_vars.clone();
if let Some(init) = init {

View file

@ -74,15 +74,17 @@ fn do_while() {
}
pub const FOR_LOOP_CONDITION_ERRORS: &[(u32, u16, &str)] = &[
(2, 5, "loop condition is always true"),
(2, 5, "control flow condition is a static term"),
(4, 5, "control flow condition is a constant evalutation"),
(4, 5, "loop condition is always true"),
(4, 5, "control flow condition is a static term"),
(6, 5, "control flow condition is a constant evalutation"),
];
#[test]
fn for_loop_condition() {
let code = r##"
/proc/test()
for()
break
for(var/x = 0; 1; x++)
break
for(var/y = 0; 5 <= 7; y++)

View file

@ -1028,6 +1028,9 @@ pub enum Statement {
arms: Vec<(Spanned<Expression>, Block)>,
else_arm: Option<Block>
},
ForInfinite {
block: Block,
},
ForLoop {
init: Option<Box<Statement>>,
test: Option<Box<Expression>>,

View file

@ -268,6 +268,7 @@ impl TTKind {
#[derive(Debug)]
enum LoopContext {
None,
ForInfinite,
ForLoop,
ForList,
ForRange,
@ -1241,6 +1242,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> {
require!(self.statement_terminator());
spanned(Statement::DoWhile { block, condition })
} else if let Some(()) = self.exact_ident("for")? {
// for ()
// for (Var [as Type] [in List]) Statement
// for (Init, Test, Inc) Statement
// for (Var in Low to High)
@ -1353,7 +1355,10 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> {
block: require!(self.block(&LoopContext::ForList)),
})
} else {
Err(self.error("for-in-list must start with variable"))
require!(self.exact(Token::Punct(Punctuation::RParen)));
spanned(Statement::ForInfinite {
block: require!(self.block(&LoopContext::ForInfinite)),
})
}
} else if let Some(()) = self.exact_ident("spawn")? {
let expr;

View file

@ -237,6 +237,9 @@ impl<'o> WalkProc<'o> {
self.visit_block(else_arm);
}
},
Statement::ForInfinite { block } => {
self.visit_block(block);
}
Statement::ForLoop { init, test, inc, block } => {
if let Some(init) = init {
self.visit_statement(location, init);