diff --git a/src/front/wgsl/mod.rs b/src/front/wgsl/mod.rs index 3f2348b98b..977797a258 100644 --- a/src/front/wgsl/mod.rs +++ b/src/front/wgsl/mod.rs @@ -3743,6 +3743,40 @@ impl Parser { Some(crate::Statement::Loop { body, continuing }) } + "while" => { + let _ = lexer.next(); + let mut body = crate::Block::new(); + + let (condition, span) = lexer.capture_span(|lexer| { + emitter.start(context.expressions); + let condition = self.parse_general_expression( + lexer, + context.as_expression(&mut body, &mut emitter), + )?; + lexer.expect(Token::Paren('{'))?; + body.extend(emitter.finish(context.expressions)); + Ok(condition) + })?; + let mut reject = crate::Block::new(); + reject.push(crate::Statement::Break, NagaSpan::default()); + body.push( + crate::Statement::If { + condition, + accept: crate::Block::new(), + reject, + }, + NagaSpan::from(span), + ); + + while !lexer.skip(Token::Paren('}')) { + self.parse_statement(lexer, context.reborrow(), &mut body, false)?; + } + + Some(crate::Statement::Loop { + body, + continuing: crate::Block::new(), + }) + } "for" => { let _ = lexer.next(); lexer.expect(Token::Paren('('))?; diff --git a/src/front/wgsl/tests.rs b/src/front/wgsl/tests.rs index 906311248f..1ccff93e89 100644 --- a/src/front/wgsl/tests.rs +++ b/src/front/wgsl/tests.rs @@ -262,6 +262,32 @@ fn parse_loop() { ", ) .unwrap(); + parse_str( + " + fn main() { + var found: bool = false; + var i: i32 = 0; + while !found { + if i == 10 { + found = true; + } + + i = i + 1; + } + } + ", + ) + .unwrap(); + parse_str( + " + fn main() { + while true { + break; + } + } + ", + ) + .unwrap(); parse_str( " fn main() { @@ -418,7 +444,7 @@ fn parse_struct_instantiation() { a: f32, b: vec3, }; - + @stage(fragment) fn fs_main() { var foo: Foo = Foo(0.0, vec3(0.0, 1.0, 42.0)); diff --git a/tests/in/collatz.wgsl b/tests/in/collatz.wgsl index 15a9d46056..377c0f8449 100644 --- a/tests/in/collatz.wgsl +++ b/tests/in/collatz.wgsl @@ -14,10 +14,7 @@ var v_indices: PrimeIndices; fn collatz_iterations(n_base: u32) -> u32 { var n = n_base; var i: u32 = 0u; - loop { - if n <= 1u { - break; - } + while n > 1u { if n % 2u == 0u { n = n / 2u; } diff --git a/tests/out/hlsl/collatz.hlsl b/tests/out/hlsl/collatz.hlsl index babae9c90a..d74efad893 100644 --- a/tests/out/hlsl/collatz.hlsl +++ b/tests/out/hlsl/collatz.hlsl @@ -9,7 +9,8 @@ uint collatz_iterations(uint n_base) n = n_base; while(true) { uint _expr5 = n; - if ((_expr5 <= 1u)) { + if ((_expr5 > 1u)) { + } else { break; } uint _expr8 = n; diff --git a/tests/out/ir/collatz.ron b/tests/out/ir/collatz.ron index 5cf3c6b086..50860b2cb7 100644 --- a/tests/out/ir/collatz.ron +++ b/tests/out/ir/collatz.ron @@ -125,7 +125,7 @@ ), Constant(2), Binary( - op: LessEqual, + op: Greater, left: 6, right: 7, ), @@ -199,10 +199,10 @@ )), If( condition: 8, - accept: [ + accept: [], + reject: [ Break, ], - reject: [], ), Emit(( start: 8, diff --git a/tests/out/msl/collatz.msl b/tests/out/msl/collatz.msl index a1a0788ada..e0f8ece621 100644 --- a/tests/out/msl/collatz.msl +++ b/tests/out/msl/collatz.msl @@ -21,7 +21,8 @@ uint collatz_iterations( n = n_base; while(true) { uint _e5 = n; - if (_e5 <= 1u) { + if (_e5 > 1u) { + } else { break; } uint _e8 = n; diff --git a/tests/out/spv/collatz.spvasm b/tests/out/spv/collatz.spvasm index bd2dd1f5fb..2980ef8305 100644 --- a/tests/out/spv/collatz.spvasm +++ b/tests/out/spv/collatz.spvasm @@ -57,9 +57,9 @@ OpLoopMerge %22 %24 None OpBranch %23 %23 = OpLabel %25 = OpLoad %4 %13 -%27 = OpULessThanEqual %26 %25 %5 +%27 = OpUGreaterThan %26 %25 %5 OpSelectionMerge %28 None -OpBranchConditional %27 %29 %28 +OpBranchConditional %27 %28 %29 %29 = OpLabel OpBranch %22 %28 = OpLabel diff --git a/tests/out/wgsl/collatz.wgsl b/tests/out/wgsl/collatz.wgsl index 37e530c0ce..7b0a134fd5 100644 --- a/tests/out/wgsl/collatz.wgsl +++ b/tests/out/wgsl/collatz.wgsl @@ -12,7 +12,8 @@ fn collatz_iterations(n_base: u32) -> u32 { n = n_base; loop { let _e5 = n; - if (_e5 <= 1u) { + if (_e5 > 1u) { + } else { break; } let _e8 = n;