mirror of
https://github.com/SpaceManiac/SpacemanDMM.git
synced 2025-12-23 05:36:47 +00:00
Add support for infinite for() loops (#259)
This commit is contained in:
parent
15291e493e
commit
ba09a43447
5 changed files with 23 additions and 4 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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++)
|
||||
|
|
|
|||
|
|
@ -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>>,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue