export const description = `
Flow control tests for loops.
`;

import { makeTestGroup } from '../../../../common/framework/test_group.js';
import { AllFeaturesMaxLimitsGPUTest } from '../../../gpu_test.js';

import { runFlowControlTest } from './harness.js';

export const g = makeTestGroup(AllFeaturesMaxLimitsGPUTest);

g.test('loop_break')
  .desc('Test that flow control exits a loop when reaching a break statement')
  .params(u => u.combine('preventValueOptimizations', [true, false]))
  .fn(t => {
    runFlowControlTest(
      t,
      f =>
        `
  ${f.expect_order(0)}
  var i = ${f.value(0)};
  loop {
    ${f.expect_order(1, 3, 5, 7)}
    if i == 3 {
      break;
    }
    ${f.expect_order(2, 4, 6)}
    i++;
  }
  ${f.expect_order(8)}
`
    );
  });

g.test('loop_continue')
  .desc('Test flow control for a loop continue statement')
  .params(u => u.combine('preventValueOptimizations', [true, false]))
  .fn(t => {
    runFlowControlTest(
      t,
      f =>
        `
  ${f.expect_order(0)}
  var i = ${f.value(0)};
  loop {
    ${f.expect_order(1, 3, 5, 7, 8)}
    if i == 3 {
      i++;
      continue;
      ${f.expect_not_reached()}
    }
    ${f.expect_order(2, 4, 6, 9)}
    if i == 4 {
      break;
    }
    i++;
  }
  ${f.expect_order(10)}
`
    );
  });

g.test('loop_continuing_basic')
  .desc('Test basic flow control for a loop continuing block')
  .params(u => u.combine('preventValueOptimizations', [true, false]))
  .fn(t => {
    runFlowControlTest(
      t,
      f =>
        `
  ${f.expect_order(0)}
  var i = ${f.value(0)};
  loop {
    ${f.expect_order(1, 3, 5)}
    i++;

    continuing {
      ${f.expect_order(2, 4, 6)}
      break if i == 3;
    }
  }
  ${f.expect_order(7)}
`
    );
  });

g.test('nested_loops')
  .desc('Test flow control for a loop nested in another loop')
  .params(u => u.combine('preventValueOptimizations', [true, false]))
  .fn(t => {
    runFlowControlTest(
      t,
      f =>
        `
  ${f.expect_order(0)}
  var i = ${f.value(0)};
  loop {
    ${f.expect_order(1, 11, 21)}
    if i == ${f.value(6)} {
      ${f.expect_order(22)}
      break;
      ${f.expect_not_reached()}
    }
    ${f.expect_order(2, 12)}
    loop {
      i++;
      ${f.expect_order(3, 6, 9, 13, 16, 19)}
      if (i % ${f.value(3)}) == 0 {
        ${f.expect_order(10, 20)}
        break;
        ${f.expect_not_reached()}
      }
      ${f.expect_order(4, 7, 14, 17)}
      if (i & ${f.value(1)}) == 0 {
        ${f.expect_order(8, 15)}
        continue;
        ${f.expect_not_reached()}
      }
      ${f.expect_order(5, 18)}
    }
  }
  ${f.expect_order(23)}
`
    );
  });

g.test('loop_break_if_logical_and_condition')
  .desc('Test flow control for a loop with a logical and break if')
  .params(u => u.combine('preventValueOptimizations', [true, false]))
  .fn(t => {
    runFlowControlTest(t, f => ({
      entrypoint: `
  ${f.expect_order(0)}
  var i = ${f.value(0)};
  loop {
    ${f.expect_order(1, 4, 7)}
    continuing {
      i++;
      break if !(a(i) && b(i));
    }
  }
  ${f.expect_order(9)}
      `,
      extra: `
fn a(i : i32) -> bool {
  ${f.expect_order(2, 5, 8)}
  return i < ${f.value(3)};
}
fn b(i : i32) -> bool {
  ${f.expect_order(3, 6)}
  return i < ${f.value(5)};
}
      `,
    }));
  });

g.test('loop_break_if_logical_or_condition')
  .desc('Test flow control for a loop with a logical or break if')
  .params(u => u.combine('preventValueOptimizations', [true, false]))
  .fn(t => {
    runFlowControlTest(t, f => ({
      entrypoint: `
  ${f.expect_order(0)}
  var i = ${f.value(0)};
  loop {
    ${f.expect_order(1, 3, 6, 9)}
    continuing {
      i++;
      break if !(a(i) || b(i));
    }
  }
  ${f.expect_order(12)}
      `,
      extra: `
fn a(i : i32) -> bool {
  ${f.expect_order(2, 4, 7, 10)}
  return i < ${f.value(2)};
}
fn b(i : i32) -> bool {
  ${f.expect_order(5, 8, 11)}
  return i < ${f.value(4)};
}
      `,
    }));
  });
