← DL-Pascal collectioncov03.pas
DOWNLOAD ORIGINAL FILE
{ DL-Pascal Coverage Section 3: Procedures and Functions }
{ Exercises value/var params, nested procedures, }
{ recursion, forward declarations, function variables, }
{ procedure variables, and parameter edge cases. }
{ Expected: runs without error, displays results. }
{$D-C-R-}
PROGRAM Section3;
VAR
i, j : Integer;
li : LongInt;
r : Real;
b : Boolean;
PROCEDURE Check(msg : STRING; passed : Boolean);
BEGIN
IF passed THEN
WriteLn('OK ', msg)
ELSE
WriteLn('FAIL ', msg);
END;
{ ---- Value vs VAR parameters ---- }
PROCEDURE AddOne(n : Integer);
BEGIN
n := n + 1; { value param - caller unchanged }
END;
PROCEDURE AddOneVar(VAR n : Integer);
BEGIN
n := n + 1; { var param - caller changed }
END;
PROCEDURE TestValueVar;
VAR n : Integer;
BEGIN
n := 5;
AddOne(n);
Check('Value param unchanged', n = 5);
n := 5;
AddOneVar(n);
Check('VAR param changed', n = 6);
{ Multiple var params }
i := 3; j := 7;
AddOneVar(i); AddOneVar(j);
Check('Multi VAR params', (i = 4) AND (j = 8));
END;
{ ---- Swap via VAR params ---- }
PROCEDURE Swap(VAR a, b : Integer);
VAR tmp : Integer;
BEGIN
tmp := a; a := b; b := tmp;
END;
PROCEDURE TestSwap;
BEGIN
i := 10; j := 20;
Swap(i, j);
Check('Swap integers', (i = 20) AND (j = 10));
{ Swap back }
Swap(i, j);
Check('Swap back', (i = 10) AND (j = 20));
END;
{ ---- Functions ---- }
FUNCTION Square(n : Integer) : Integer;
BEGIN
Square := n * n;
END;
FUNCTION Max(a, b : Integer) : Integer;
BEGIN
IF a > b THEN Max := a ELSE Max := b;
END;
FUNCTION Min(a, b : Integer) : Integer;
BEGIN
IF a < b THEN Min := a ELSE Min := b;
END;
FUNCTION AbsVal(n : Integer) : Integer;
BEGIN
IF n < 0 THEN AbsVal := -n ELSE AbsVal := n;
END;
FUNCTION RealSquare(x : Real) : Real;
BEGIN
RealSquare := x * x;
END;
PROCEDURE TestFunctions;
BEGIN
Check('Square 5', Square(5) = 25);
Check('Square 0', Square(0) = 0);
Check('Square -3', Square(-3) = 9);
Check('Max 3 7', Max(3, 7) = 7);
Check('Max 7 3', Max(7, 3) = 7);
Check('Max equal', Max(5, 5) = 5);
Check('Min 3 7', Min(3, 7) = 3);
Check('AbsVal neg', AbsVal(-9) = 9);
Check('AbsVal pos', AbsVal(9) = 9);
r := RealSquare(2.5);
Check('RealSquare', r = 6.25);
{ Function in expression }
i := Square(3) + Square(4);
Check('Func in expr', i = 25);
{ Nested function calls }
i := Max(Square(2), Square(3));
Check('Nested func', i = 9);
{ Function result as param }
i := AbsVal(Min(-5, -3));
Check('Func as param', i = 5);
END;
{ ---- Recursion ---- }
FUNCTION Factorial(n : Integer) : LongInt;
BEGIN
IF n <= 1 THEN Factorial := 1
ELSE Factorial := n * Factorial(n - 1);
END;
FUNCTION Fibonacci(n : Integer) : Integer;
BEGIN
IF n <= 1 THEN Fibonacci := n
ELSE Fibonacci := Fibonacci(n-1) + Fibonacci(n-2);
END;
FUNCTION Power(base : Real; exp : Integer) : Real;
BEGIN
IF exp = 0 THEN Power := 1.0
ELSE IF exp > 0 THEN Power := base * Power(base, exp-1)
ELSE Power := 1.0 / Power(base, -exp);
END;
FUNCTION GCD(a, b : Integer) : Integer;
BEGIN
IF b = 0 THEN GCD := a
ELSE GCD := GCD(b, a MOD b);
END;
PROCEDURE TestRecursion;
BEGIN
Check('Factorial 0', Factorial(0) = 1);
Check('Factorial 1', Factorial(1) = 1);
Check('Factorial 5', Factorial(5) = 120);
Check('Factorial 10', Factorial(10) = 3628800);
Check('Fibonacci 0', Fibonacci(0) = 0);
Check('Fibonacci 1', Fibonacci(1) = 1);
Check('Fibonacci 7', Fibonacci(7) = 13);
Check('Fibonacci 10', Fibonacci(10) = 55);
r := Power(2.0, 10);
Check('Power 2^10', r = 1024.0);
r := Power(2.0, 0);
Check('Power 2^0', r = 1.0);
r := Power(2.0, -1);
Check('Power 2^-1', r = 0.5);
Check('GCD 12 8', GCD(12, 8) = 4);
Check('GCD 100 75', GCD(100, 75) = 25);
Check('GCD prime', GCD(17, 13) = 1);
END;
{ ---- Forward declarations ---- }
PROCEDURE IsEven(n : Integer); FORWARD;
PROCEDURE IsOdd(n : Integer);
BEGIN
IF n = 0 THEN
Check('Mutual recur odd', False) { should not reach 0 via odd path }
ELSE IF n = 1 THEN
Check('Mutual recur odd=1', True)
ELSE
IsEven(n - 1);
END;
PROCEDURE IsEven(n : Integer);
BEGIN
IF n = 0 THEN
Check('Mutual recur even=0', True)
ELSE
IsOdd(n - 1);
END;
PROCEDURE TestForward;
BEGIN
IsEven(4); { 4->odd(3)->even(2)->odd(1)->check }
IsOdd(5); { 5->even(4)->odd(3)->even(2)->odd(1)->check }
END;
{ ---- Nested procedures ---- }
PROCEDURE TestNested;
VAR outerN : Integer;
PROCEDURE Inner1;
BEGIN
outerN := outerN + 1; { accesses outer variable }
END;
PROCEDURE Inner2(VAR n : Integer);
VAR localN : Integer;
PROCEDURE DeepInner;
BEGIN
localN := localN * 2;
END;
BEGIN
localN := n;
DeepInner;
n := localN;
END;
BEGIN
outerN := 10;
Inner1;
Check('Nested access outer', outerN = 11);
Inner1;
Check('Nested access outer 2', outerN = 12);
i := 5;
Inner2(i);
Check('Nested deep inner', i = 10);
END;
{ ---- Multiple return paths ---- }
FUNCTION Sign(n : Integer) : Integer;
BEGIN
IF n > 0 THEN BEGIN Sign := 1; Exit; END;
IF n < 0 THEN BEGIN Sign := -1; Exit; END;
Sign := 0;
END;
FUNCTION FirstPosDiv(n : Integer) : Integer;
{ Return smallest divisor > 1, or n if prime }
VAR d : Integer;
BEGIN
d := 2;
WHILE d * d <= n DO BEGIN
IF n MOD d = 0 THEN BEGIN
FirstPosDiv := d;
Exit;
END;
Inc(d);
END;
FirstPosDiv := n;
END;
PROCEDURE TestExit;
BEGIN
Check('Sign pos', Sign(5) = 1);
Check('Sign neg', Sign(-3) = -1);
Check('Sign zero', Sign(0) = 0);
Check('PrimDiv 12', FirstPosDiv(12) = 2);
Check('PrimDiv 15', FirstPosDiv(15) = 3);
Check('PrimDiv 7', FirstPosDiv(7) = 7);
Check('PrimDiv 49', FirstPosDiv(49) = 7);
END;
{ ---- Procedure/Function variables ---- }
TYPE
TIntFunc = FUNCTION(n : Integer) : Integer;
TIntProc = PROCEDURE(VAR n : Integer);
FUNCTION Double(n : Integer) : Integer;
BEGIN Double := n * 2; END;
FUNCTION Triple(n : Integer) : Integer;
BEGIN Triple := n * 3; END;
PROCEDURE TestProcVars;
VAR
fn : TIntFunc;
pr : TIntProc;
BEGIN
fn := Double;
Check('Func var double', fn(5) = 10);
fn := Triple;
Check('Func var triple', fn(5) = 15);
{ Function var in expression }
fn := Square;
i := fn(4) + fn(3);
Check('Func var expr', i = 25);
pr := AddOneVar;
i := 7;
pr(i);
Check('Proc var', i = 8);
END;
{ ---- String parameter ---- }
FUNCTION StrLen(s : STRING) : Integer;
BEGIN
StrLen := Length(s);
END;
{$V-}
PROCEDURE AppendBang(VAR s : STRING);
BEGIN
s := s + '!';
END;
PROCEDURE TestStringParams;
VAR s : STRING[20];
BEGIN
Check('StrLen hello', StrLen('Hello') = 5);
Check('StrLen empty', StrLen('') = 0);
s := 'Hi';
AppendBang(s);
Check('VAR string', s = 'Hi!');
AppendBang(s);
Check('VAR string x2', s = 'Hi!!');
{$V+}
END;
{ ---- Accumulator pattern ---- }
PROCEDURE Accumulate(VAR sum : LongInt; val : Integer);
BEGIN
sum := sum + val;
END;
PROCEDURE TestAccumulate;
VAR sum : LongInt;
n : Integer;
BEGIN
sum := 0;
FOR n := 1 TO 100 DO Accumulate(sum, n);
Check('Accumulate 1..100', sum = 5050);
sum := 0;
FOR n := 1 TO 10 DO Accumulate(sum, Square(n));
Check('Accumulate squares', sum = 385); { sum of 1^2..10^2 }
END;
{ ---- Main ---- }
BEGIN
WriteLn('=== Section 3: Procedures and Functions ===');
WriteLn;
WriteLn('-- Value vs VAR --');
TestValueVar;
WriteLn;
WriteLn('-- Swap --');
TestSwap;
WriteLn;
WriteLn('-- Functions --');
TestFunctions;
WriteLn;
WriteLn('-- Recursion --');
TestRecursion;
WriteLn;
WriteLn('-- Forward --');
TestForward;
WriteLn;
WriteLn('-- Nested --');
TestNested;
WriteLn;
WriteLn('-- Exit --');
TestExit;
WriteLn;
WriteLn('-- Proc/Func Vars --');
TestProcVars;
WriteLn;
WriteLn('-- String Params --');
TestStringParams;
WriteLn;
WriteLn('-- Accumulate --');
TestAccumulate;
WriteLn;
WriteLn('=== Section 3 complete ===');
END.