← DL-Pascal collection

cov02.pas

DOWNLOAD ORIGINAL FILE

{ DL-Pascal Coverage Section 2: Control Flow     }
{ Exercises IF/THEN/ELSE, WHILE, REPEAT/UNTIL,   }
{ FOR TO/DOWNTO, CASE/OF, nested combinations,   }
{ GOTO, and edge cases.                          }
{ Expected: runs without error, displays results }
{$D-C-R-}

PROGRAM Section2;

VAR
  i, j, k  : Integer;
  b         : Boolean;
  c         : Char;

PROCEDURE Check(msg : STRING; passed : Boolean);
BEGIN
  IF passed THEN
    WriteLn('OK   ', msg)
  ELSE
    WriteLn('FAIL ', msg);
END;

{ ---- IF / THEN / ELSE ---- }
PROCEDURE TestIf;
VAR n : Integer;
BEGIN
  { Simple true branch }
  n := 0;
  IF 5 > 3 THEN n := 1;
  Check('IF true branch',    n = 1);

  { Simple false branch - no else }
  n := 0;
  IF 3 > 5 THEN n := 1;
  Check('IF false no-else',  n = 0);

  { IF THEN ELSE true }
  n := 0;
  IF 5 > 3 THEN n := 1 ELSE n := 2;
  Check('IF-ELSE true',      n = 1);

  { IF THEN ELSE false }
  n := 0;
  IF 3 > 5 THEN n := 1 ELSE n := 2;
  Check('IF-ELSE false',     n = 2);

  { Nested IF - dangling else binds to nearest IF }
  n := 0;
  b := True;
  IF b THEN
    b := False;
    IF b THEN n := 1
    ELSE n := 2;
  Check('Nested IF else',    n = 2);

  { Chained IF ELSE IF }
  n := 5;
  IF n < 0 THEN i := -1
  ELSE IF n = 0 THEN i := 0
  ELSE IF n < 10 THEN i := 1
  ELSE i := 2;
  Check('Chained IF',        i = 1);

  { IF with compound statement }
  n := 0;
  b := True;
  IF b THEN BEGIN
    n := n + 1;
    n := n + 1;
  END;
  Check('IF compound',       n = 2);

  { IF ELSE with compound }
  n := 0;
  b := False;
  IF b THEN BEGIN
    n := 99;
  END ELSE BEGIN
    n := n + 3;
    n := n + 3;
  END;
  Check('IF-ELSE compound',  n = 6);

  { Boolean variable in IF }
  b := (7 MOD 2) = 1;
  IF b THEN n := 7 ELSE n := 0;
  Check('IF bool var',       n = 7);
END;

{ ---- WHILE / DO ---- }
PROCEDURE TestWhile;
VAR n, sum : Integer;
BEGIN
  { Basic count }
  n := 0; sum := 0;
  WHILE n < 5 DO BEGIN
    sum := sum + n;
    Inc(n);
  END;
  Check('WHILE sum 0..4',    sum = 10);

  { Zero iterations }
  n := 0;
  b := False;
  WHILE b DO Inc(n);
  Check('WHILE zero iters',  n = 0);

  { Single iteration }
  n := 0;
  WHILE n = 0 DO Inc(n);
  Check('WHILE one iter',    n = 1);

  { Nested WHILE }
  n := 0;
  i := 0;
  WHILE i < 3 DO BEGIN
    j := 0;
    WHILE j < 3 DO BEGIN
      Inc(n);
      Inc(j);
    END;
    Inc(i);
  END;
  Check('WHILE nested 3x3',  n = 9);

  { WHILE with compound condition }
  n := 0; i := 10;
  WHILE (n < 5) AND (i > 0) DO BEGIN
    Inc(n); Dec(i, 2);
  END;
  Check('WHILE compound cond', (n = 5) AND (i = 0));

  { Countdown }
  n := 10;
  WHILE n > 0 DO Dec(n);
  Check('WHILE countdown',   n = 0);
END;

{ ---- REPEAT / UNTIL ---- }
PROCEDURE TestRepeat;
VAR n, sum : Integer;
BEGIN
  { Basic - always executes at least once }
  n := 0;
  REPEAT
    Inc(n);
  UNTIL n = 5;
  Check('REPEAT to 5',       n = 5);

  { Always executes once even if condition true }
  n := 99;
  REPEAT
    n := 1;
  b := True;
  UNTIL b;
  Check('REPEAT once',       n = 1);

  { Sum via repeat }
  n := 1; sum := 0;
  REPEAT
    sum := sum + n;
    Inc(n);
  UNTIL n > 5;
  Check('REPEAT sum 1..5',   sum = 15);

  { Nested REPEAT }
  n := 0;
  i := 0;
  REPEAT
    j := 0;
    REPEAT
      Inc(n);
      Inc(j);
    UNTIL j = 4;
    Inc(i);
  UNTIL i = 4;
  Check('REPEAT nested 4x4', n = 16);

  { Compound condition }
  n := 0; i := 0;
  REPEAT
    Inc(n); Inc(i);
  UNTIL (n >= 3) OR (i >= 10);
  Check('REPEAT compound',   n = 3);
END;

{ ---- FOR TO / DOWNTO ---- }
PROCEDURE TestFor;
VAR n, sum : Integer;
    li     : LongInt;
BEGIN
  { Basic TO }
  sum := 0;
  FOR i := 1 TO 5 DO sum := sum + i;
  Check('FOR TO sum 1..5',   sum = 15);

  { Zero iterations when start > end }
  n := 0;
  FOR i := 5 TO 1 DO Inc(n);
  Check('FOR TO zero iters', n = 0);

  { DOWNTO }
  sum := 0;
  FOR i := 5 DOWNTO 1 DO sum := sum + i;
  Check('FOR DOWNTO sum',    sum = 15);

  { Zero iters DOWNTO }
  n := 0;
  FOR i := 1 DOWNTO 5 DO Inc(n);
  Check('FOR DOWNTO zero',   n = 0);

  { Single iteration }
  n := 0;
  FOR i := 3 TO 3 DO n := i;
  Check('FOR single iter',   n = 3);

  { Nested FOR }
  n := 0;
  FOR i := 1 TO 4 DO
    FOR j := 1 TO 4 DO
      Inc(n);
  Check('FOR nested 4x4',    n = 16);

  { FOR with step via LongInt range }
  li := 0;
  FOR i := 1 TO 100 DO Inc(li, i);
  Check('FOR sum 1..100',    li = 5050);

  { FOR over char range }
  n := 0;
  FOR c := 'A' TO 'Z' DO Inc(n);
  Check('FOR char A..Z',     n = 26);

  { Ensure loop var has final value after loop }
  FOR i := 1 TO 5 DO ;
  Check('FOR final var',     i = 5);
END;

{ ---- CASE / OF ---- }
PROCEDURE TestCase;
VAR n : Integer;
BEGIN
  { Integer CASE }
  i := 2;
  CASE i OF
    1 : n := 10;
    2 : n := 20;
    3 : n := 30;
  END;
  Check('CASE int match',    n = 20);

  { CASE with ELSE }
  i := 99;
  CASE i OF
    1 : n := 1;
    2 : n := 2;
  ELSE
    n := 0;
  END;
  Check('CASE else',         n = 0);

  { CASE no match no else - value unchanged }
  n := 42;
  i := 99;
  CASE i OF
    1 : n := 1;
    2 : n := 2;
  END;
  Check('CASE no match',     n = 42);

  { CASE with range }
  i := 5;
  CASE i OF
    1..3 : n := 1;
    4..6 : n := 2;
    7..9 : n := 3;
  END;
  Check('CASE range',        n = 2);

  { CASE with list }
  i := 3;
  CASE i OF
    1, 3, 5, 7, 9 : n := 1;  { odd }
    2, 4, 6, 8    : n := 2;  { even }
  END;
  Check('CASE list odd',     n = 1);

  i := 4;
  CASE i OF
    1, 3, 5, 7, 9 : n := 1;
    2, 4, 6, 8    : n := 2;
  END;
  Check('CASE list even',    n = 2);

  { CASE on Char }
  c := 'B';
  CASE c OF
    'A'      : n := 1;
    'B', 'C' : n := 2;
    'D'..'Z' : n := 3;
  ELSE
    n := 0;
  END;
  Check('CASE char',         n = 2);

  { CASE with compound statement }
  i := 1;
  n := 0;
  CASE i OF
    1 : BEGIN n := n + 1; n := n + 1; END;
    2 : n := 99;
  END;
  Check('CASE compound',     n = 2);
END;

{ ---- Mixed / nested control structures ---- }
PROCEDURE TestMixed;
VAR n, sum : Integer;
BEGIN
  { FOR containing IF }
  sum := 0;
  FOR i := 1 TO 10 DO
    IF Odd(i) THEN sum := sum + i;
  Check('FOR+IF odd sum',    sum = 25);  { 1+3+5+7+9 }

  { WHILE containing CASE }
  n := 1; sum := 0;
  WHILE n <= 5 DO BEGIN
    CASE n OF
      1, 2 : Inc(sum, 1);
      3    : Inc(sum, 10);
      4, 5 : Inc(sum, 100);
    END;
    Inc(n);
  END;
  Check('WHILE+CASE',        sum = 212);  { 1+1+10+100+100 }

  { REPEAT containing FOR }
  n := 0; sum := 0;
  REPEAT
    FOR j := 1 TO 3 DO Inc(sum);
    Inc(n);
  UNTIL n = 4;
  Check('REPEAT+FOR',        sum = 12);

  { Fibonacci via WHILE }
  i := 0; j := 1; n := 0;
  WHILE j < 100 DO BEGIN
    k := i + j;
    i := j;
    j := k;
    Inc(n);
  END;
  Check('Fibonacci count',   n = 10);  { 1,1,2,3,5,8,13,21,34,55,89 }
  Check('Fibonacci last',    i = 55);

  { Triangular numbers via nested FOR }
  sum := 0;
  FOR i := 1 TO 5 DO
    FOR j := 1 TO i DO
      Inc(sum);
  Check('Triangular 5',      sum = 15);  { 1+2+3+4+5 }
END;

{ ---- GOTO ---- }
PROCEDURE TestGoto;
LABEL skip, done;
VAR n : Integer;
BEGIN
  n := 0;
  GOTO skip;
  n := 99;  { should be skipped }
skip:
  n := n + 1;
  Check('GOTO forward',      n = 1);

  { GOTO to exit a loop early (legitimate use) }
  n := 0;
  FOR i := 1 TO 10 DO BEGIN
    Inc(n);
    IF n = 5 THEN GOTO done;
  END;
done:
  Check('GOTO exit loop',    n = 5);
END;

{ ---- Edge cases ---- }
PROCEDURE TestEdge;
VAR n : Integer;
BEGIN
  { Empty WHILE body }
  i := 0;
  WHILE i < 5 DO Inc(i);
  Check('WHILE no BEGIN',    i = 5);

  { FOR with max range check }
  n := 0;
  FOR i := -5 TO 5 DO Inc(n);
  Check('FOR negative start', n = 11);

  { Deeply nested IF }
  i := 3;
  IF i > 0 THEN
    IF i > 1 THEN
      IF i > 2 THEN
        IF i > 3 THEN n := 0
        ELSE n := 3
      ELSE n := 2
    ELSE n := 1
  ELSE n := 0;
  Check('Deep nested IF',    n = 3);

  { CASE boundary values }
  i := 0;
  CASE i OF
    0    : n := 99;
    1..9 : n := 1;
  END;
  Check('CASE zero',         n = 99);
END;

{ ---- Main ---- }
BEGIN
  WriteLn('=== Section 2: Control Flow ===');
  WriteLn;

  WriteLn('-- IF/THEN/ELSE --');
  TestIf;
  WriteLn;

  WriteLn('-- WHILE/DO --');
  TestWhile;
  WriteLn;

  WriteLn('-- REPEAT/UNTIL --');
  TestRepeat;
  WriteLn;

  WriteLn('-- FOR TO/DOWNTO --');
  TestFor;
  WriteLn;

  WriteLn('-- CASE/OF --');
  TestCase;
  WriteLn;

  WriteLn('-- Mixed/Nested --');
  TestMixed;
  WriteLn;

  WriteLn('-- GOTO --');
  TestGoto;
  WriteLn;

  WriteLn('-- Edge Cases --');
  TestEdge;
  WriteLn;

  WriteLn('=== Section 2 complete ===');
END.