# Oberon language test and validation suite

# test halt and assert statements and simple procedure call (basics for the test suite)

positive: empty module

	MODULE Test;
	END Test.

negative: simple halt

	MODULE Test;
	BEGIN HALT (1234);
	END Test.

positive: satisified assertion

	MODULE Test;
	VAR b: BOOLEAN;
	BEGIN b := TRUE; ASSERT (b);
	END Test.

negative: unsatisified assertion

	MODULE Test;
	VAR b: BOOLEAN;
	BEGIN b := FALSE; ASSERT (b);
	END Test.

negative: simple halt in global procedure

	MODULE Test;
	PROCEDURE Procedure;
	BEGIN HALT (1234);
	END Procedure;
	BEGIN Procedure;
	END Test.

positive: satisified assertion in global procedure

	MODULE Test;
	PROCEDURE Procedure;
	VAR b: BOOLEAN;
	BEGIN b := TRUE; ASSERT (b);
	END Procedure;
	BEGIN Procedure;
	END Test.

negative: unsatisified assertion in global procedure

	MODULE Test;
	PROCEDURE Procedure;
	VAR b: BOOLEAN;
	BEGIN b := FALSE; ASSERT (b);
	END Procedure;
	BEGIN Procedure;
	END Test.

positive: parameterless procedure call

	MODULE Test;
	VAR called: BOOLEAN;

		PROCEDURE P;
		BEGIN
			called := TRUE;
		END P;
	BEGIN
		called := FALSE;
		P;
		ASSERT(called);
	END Test.


# basic types storage test

positive: Char stored in PAF

	MODULE Test;

	PROCEDURE Char;
	VAR a,b: CHAR;
	BEGIN
		a := 'a';
		b := a;
		ASSERT(b = 'a');
	END Char;

	BEGIN
		Char;
	END Test.

positive: Shortint stored in PAF

	MODULE Test;

	PROCEDURE Shortint;
	VAR a,b: SHORTINT;
	BEGIN
		a := 13;
		b := a;
		ASSERT(b = 13);
	END Shortint;

	BEGIN
		Shortint;
	END Test.

positive: Integer stored in PAF

	MODULE Test;

	PROCEDURE Integer;
	VAR a,b: INTEGER;
	BEGIN
		a := 2233;
		b := a;
		ASSERT(b = 2233);
	END Integer;

	BEGIN
		Integer;
	END Test.

positive: Longint stored in PAF

	MODULE Test;

	PROCEDURE Longint;
	VAR a,b: LONGINT;
	BEGIN
		a := 70800;
		b := a;
		ASSERT(b = 70800);
	END Longint;

	BEGIN
		Longint;
	END Test.

positive: Hugeint stored in PAF

	MODULE Test;

	PROCEDURE Hugeint;
	VAR a,b: HUGEINT;
	BEGIN
		a := 70800;
		b := a;
		ASSERT(b = 70800);
	END Hugeint;

	BEGIN
		Hugeint;
	END Test.

positive: Real stored in PAF

	MODULE Test;

	PROCEDURE Real;
	VAR a,b: REAL;
	BEGIN
		a := 888;
		b := a;
		ASSERT(b = 888);
	END Real;

	BEGIN
		Real;
	END Test.

positive: Longreal stored in PAF

	MODULE Test;

	PROCEDURE Longreal;
	VAR a,b: LONGREAL;
	BEGIN
		a := 888;
		b := a;
		ASSERT(b = 888);
	END Longreal;

	BEGIN
		Longreal;
	END Test.

positive: Set stored in PAF

	MODULE Test;

	PROCEDURE Set;
	VAR a,b: SET;
	BEGIN
		a := {1,2,8,9,31};
		b := a;
		ASSERT(b = {1,2,8,9,31});
	END Set;

	BEGIN
		Set;
	END Test.

positive: Boolean stored in PAF

	MODULE Test;

	PROCEDURE Boolean;
	VAR a,b,c: BOOLEAN;
	BEGIN
		a := FALSE;
		b := TRUE;
		c := FALSE;
		ASSERT(b = TRUE);
	END Boolean;

	BEGIN
		Boolean;
	END Test.


# constant declarations

positive: expression containing a constant

	MODULE Test;
	CONST N = 10000;
	VAR i: INTEGER;
	BEGIN i := N - 1; ASSERT (i = 9999);
	END Test.

positive: lengths of string constants

	MODULE Test;
	CONST String = "This string is not empty";
	CONST Copy = String;

	PROCEDURE Assert (CONST str: ARRAY OF CHAR);
	BEGIN ASSERT (LEN (str) # 0);
	END Assert;

	BEGIN Assert (String); Assert (Copy);
	END Test.


# basic type declarations

positive: constant boolean assignment

	MODULE Test;
	VAR b: BOOLEAN;
	BEGIN b := TRUE; ASSERT (b = TRUE);
	END Test.

positive: variable boolean assignment

	MODULE Test;
	VAR b1, b2: BOOLEAN;
	BEGIN b1 := TRUE; b2 := FALSE; b2 := b1; ASSERT (b2 = TRUE);
	END Test.

positive: boolean equality

	MODULE Test;
	VAR b1, b2: BOOLEAN;
	BEGIN b1 := TRUE; b2 := b1; ASSERT (b1 = b2); b1 := FALSE; b2 := b1; ASSERT (b1 = b2);
	END Test.

positive: array of boolean values

	MODULE Test;
	VAR b: ARRAY 2 OF BOOLEAN;
	BEGIN b[1] := TRUE; ASSERT (b[1]);
	END Test.

positive: constant character assignment

	MODULE Test;
	VAR c: CHAR;
	BEGIN c := 'c'; ASSERT (c = 'c');
	END Test.

positive: variable character assignment

	MODULE Test;
	VAR c1, c2: CHAR;
	BEGIN c1 := 'A'; c2 := 'B'; c2 := c1; ASSERT (c2 = 'A');
	END Test.

positive: char array variable assignment

	MODULE Test;
	VAR v: ARRAY 2 OF CHAR;
	BEGIN v[0] := CHR(92); ASSERT (ORD(v[0]) = 92);
	END Test.

positive: heximal character value assignment

	MODULE Test;
	VAR c: CHAR;
	BEGIN c := 020X; ASSERT (c = ' ');
	END Test.

positive: constant integer assignment

	MODULE Test;
	VAR i: INTEGER;
	BEGIN i := 2; ASSERT (i = 2);
	END Test.

positive: variable integer assignment

	MODULE Test;
	VAR i1, i2: INTEGER;
	BEGIN i1 := 45; i2 := 64; i2 := i1; ASSERT (i1 = 45);
	END Test.

positive: constant real assignment

	MODULE Test;
	VAR r: REAL;
	BEGIN r := 2; ASSERT (r = 2);
	END Test.

positive: variable real assignment

	MODULE Test;
	VAR r1, r2: REAL;
	BEGIN r1 := 2.25; r2 := 3.75; r2 := r1; ASSERT (r1 = 2.25);
	END Test.

positive: real value assignment to real variable

	MODULE Test;
	VAR r: REAL;
	BEGIN r := 1.25; ASSERT (r = 1.25);
	END Test.

positive: constant set assignment

	MODULE Test;
	VAR s: SET;
	BEGIN s := {1}; ASSERT (1 IN s);
	END Test.

positive: variable set assignment

	MODULE Test;
	VAR s1, s2: SET; i: INTEGER;
	BEGIN i := 5; s1 := {i}; s2 := {}; s2 := s1; ASSERT (i IN s2);
	END Test.

positive: set inclusions

	MODULE Test;
	VAR s: SET; i, j, k: INTEGER;
	BEGIN i := 1; j := 3; k := 7; s := {1, 3, 5..8}; ASSERT ((i IN s) & (j IN s) & (k IN s));
	END Test.

negative: set value out of bounds at maximum

	MODULE Test;
	VAR n: INTEGER; s: SET;
	BEGIN n := MAX(SET) + 1; s := {n};
	END Test.

negative: set value out of bounds at minimum

	MODULE Test;
	VAR n: INTEGER; s: SET;
	BEGIN n := MIN(SET) - 1; s := {n};
	END Test.


# array type declarations

negative: array out of bounds while reading

	MODULE Test;
	VAR a: ARRAY 1 OF INTEGER; r, i: INTEGER;
	BEGIN a[0] := 0; i := 1; r := a[i];
	END Test.

negative: array out of bounds while writing

	MODULE Test;
	VAR a: ARRAY 1 OF INTEGER; i: INTEGER;
	BEGIN i := 1; a[i] := 0;
	END Test.

positive: index of array element is record variable

	MODULE Test;
	TYPE R = RECORD i: INTEGER END;
	VAR ai: ARRAY 2 OF INTEGER; ar: ARRAY 2 OF R;
	BEGIN ai[0] := 0; ai[1] := 5; ar[0].i := 1; ASSERT (ai[ar[ai[0]].i] = 5);
	END Test.

positive: one-dimensional array element assignment

	MODULE Test;
	VAR a: ARRAY 2 OF CHAR;
	BEGIN a[1] := 'c'; ASSERT (a[1] = 'c');
	END Test.

positive: two-dimensional array element assignment

	MODULE Test;
	VAR a: ARRAY 2, 2 OF BOOLEAN;
	BEGIN a[1, 1] := TRUE; ASSERT (a[1, 1] = TRUE);
	END Test.


# record type declarations

positive: record initialization

	MODULE Test;
	VAR r: RECORD i: INTEGER END;
	BEGIN r.i := 5; ASSERT (r.i = 5);
	END Test.

positive: record copies

	MODULE Test;
	VAR a, b: RECORD i, j: INTEGER END;
	BEGIN a.i := 1; a.j := 2; b := a; ASSERT (b.i = 1); ASSERT (b.j = 2);
	END Test.


# pointer type declarations

positive: dynamic record allocation with new

	MODULE Test;
	VAR p: POINTER TO RECORD x: INTEGER END;
	BEGIN NEW (p); ASSERT (p # NIL); p.x := 3; ASSERT (p.x = 3);
	END Test.

positive: valid type guard test

	MODULE Test;
	TYPE R1 = RECORD END; R2 = RECORD (R1) END; P1 = POINTER TO R1; P2 = POINTER TO R2;
	VAR p1: P1; p2: P2;
	BEGIN NEW (p2); p1 := p2; p2 := p1(P2);
	END Test.


# procedure type declarations

positive: procedure type with value parameter INTEGER

	MODULE Test;
	VAR a: ARRAY 5 OF INTEGER; i: INTEGER; r: INTEGER;

	PROCEDURE Iterate (VAR a: ARRAY OF INTEGER; p : PROCEDURE (r: INTEGER));
	VAR i: LONGINT;
	BEGIN FOR i := 0 TO LEN (a) - 1 DO p (a[i]) END;
	END Iterate;

	PROCEDURE Accummulate (v: INTEGER);
	BEGIN r := r + v;
	END Accummulate;

	BEGIN FOR i := 0 TO 4 DO a[i] := i END; r := 0; Iterate (a, Accummulate); ASSERT (r = 10);
	END Test.
	
positive: procedure type with value parameter REAL

	MODULE Test;
	VAR a: ARRAY 5 OF REAL; i: INTEGER; r: REAL;

	PROCEDURE Iterate (VAR a: ARRAY OF REAL; p : PROCEDURE (r: REAL));
	VAR i: LONGINT;
	BEGIN FOR i := 0 TO LEN (a) - 1 DO p (a[i]) END;
	END Iterate;

	PROCEDURE Accummulate (v: REAL);
	BEGIN r := r + v;
	END Accummulate;

	BEGIN FOR i := 0 TO 4 DO a[i] := i END; r := 0; Iterate (a, Accummulate); ASSERT (r = 10);
	END Test.

positive: procedure type with var parameter INTEGER

	MODULE Test;
	VAR i: INTEGER; k: INTEGER; p: PROCEDURE (VAR r: INTEGER; b: INTEGER);

	PROCEDURE Accummulate (VAR r: INTEGER; v: INTEGER);
	BEGIN r := r + v;
	END Accummulate;

	BEGIN k := 0; p := Accummulate; FOR i := 0 TO 4 DO p (k, i) END; ASSERT (k = 10);
	END Test.
	
positive: procedure type with var parameter REAL

	MODULE Test;
	VAR i: INTEGER; k: REAL; p: PROCEDURE (VAR r: REAL; b: REAL);

	PROCEDURE Accummulate (VAR r: REAL; v: REAL);
	BEGIN r := r + v;
	END Accummulate;

	BEGIN k := 0; p := Accummulate; FOR i := 0 TO 4 DO p (k, i) END; ASSERT (k = 10);
	END Test.

positive: procedure type with result type INTEGER

	MODULE Test;
	VAR r: INTEGER; p: PROCEDURE (a, b: INTEGER): INTEGER;

	PROCEDURE Add (a, b: INTEGER): INTEGER;
	BEGIN RETURN a + b;
	END Add;

	BEGIN p := Add; r := p (3, 4); ASSERT (r = 7);
	END Test.

positive: procedure type with result type REAL

	MODULE Test;
	VAR r: REAL; p: PROCEDURE (a, b: REAL): REAL;

	PROCEDURE Add (a, b: REAL): REAL;
	BEGIN RETURN a + b;
	END Add;

	BEGIN p := Add; r := p (3, 4); ASSERT (r = 7);
	END Test.

positive: procedure type with result type in record INTEGER

	MODULE Test;
	VAR r: INTEGER; p: RECORD p: PROCEDURE (a, b: INTEGER): INTEGER END;

	PROCEDURE Add (a, b: INTEGER): INTEGER;
	BEGIN RETURN a + b;
	END Add;

	BEGIN p.p := Add; r := p.p (3, 4); ASSERT (r = 7);
	END Test.
	
positive: procedure type with result type in record REAL

	MODULE Test;
	VAR r: REAL; p: RECORD p: PROCEDURE (a, b: REAL): REAL END;

	PROCEDURE Add (a, b: REAL): REAL;
	BEGIN RETURN a + b;
	END Add;

	BEGIN p.p := Add; r := p.p (3, 4); ASSERT (r = 7);
	END Test.

positive: procedure array

	MODULE Test;
	VAR i: INTEGER; a: ARRAY 10 OF PROCEDURE (VAR a: INTEGER);

	PROCEDURE Add3 (VAR v: INTEGER);
	BEGIN INC (v, 3);
	END Add3;

	BEGIN i := 3; a[6] := Add3; a[6] (i); ASSERT (i = 6); a[i](i); ASSERT (i = 9);
	END Test.

positive: procedure array with return type

	MODULE Test;
	VAR i: INTEGER; a: ARRAY 10 OF PROCEDURE (i: INTEGER): INTEGER;

	PROCEDURE Add2 (v: INTEGER): INTEGER;
	BEGIN RETURN v + 2;
	END Add2;

	BEGIN a[3] := Add2; i := a[3](1); ASSERT (i = 3); INC (i, a[i](i)); ASSERT (i = 8);
	END Test.


# conversions

positive: constant positive real to integer conversion

	MODULE Test;
	VAR i: LONGINT;
	BEGIN i := ENTIER (3.5); ASSERT (i = 3);
	END Test.

positive: constant negative real to integer conversion

	MODULE Test;
	VAR i: LONGINT;
	BEGIN i := ENTIER (-3.5); ASSERT (i = -4);
	END Test.

positive: positive real to integer conversion

	MODULE Test;
	VAR r: REAL; i: LONGINT;
	BEGIN r := 3.5; i := ENTIER (r); ASSERT (i = 3);
	END Test.


positive: negative real to integer conversion

	MODULE Test;
	VAR r: REAL; i: LONGINT;
	BEGIN r := -3.5; i := ENTIER (r); ASSERT (i = -4);
	END Test.


# variable declarations

positive: two-dimensional array assignment

	MODULE Test;
	VAR a: ARRAY 8, 12 OF INTEGER;
	BEGIN a[1, 2] := 3; ASSERT (a[1][2] = 3);
	END Test.

positive: two-dimensional open array assignment

	MODULE Test;
	VAR a: ARRAY 8, 12 OF INTEGER;

	PROCEDURE P (VAR b: ARRAY OF ARRAY OF INTEGER);
	BEGIN b[1][2] := 3;
	END P;

	BEGIN P (a); ASSERT (a[1][2] = 3);
	END Test.


# operations

positive: logical operations

	MODULE Test;
	VAR a, b: BOOLEAN;
	BEGIN
		a := FALSE; ASSERT (~a);
		b := FALSE; ASSERT (~a & ~b); ASSERT (~a OR ~b);
		b := TRUE; ASSERT (~a & b); ASSERT (~a OR b);
		a := TRUE; ASSERT (a);
		b := FALSE; ASSERT (a & ~b); ASSERT (a OR ~b);
		b := TRUE; ASSERT (a & b); ASSERT (a OR b);
	END Test.

positive: arithmetic operations

	MODULE Test;
	VAR a, b: INTEGER;
	BEGIN
		a := 9; b := 7;
		ASSERT (+a = 9); ASSERT (+b = 7);
		ASSERT (-a = -9); ASSERT (-b = -7);
		ASSERT (a + b = 16); ASSERT (b + a = 16);
		ASSERT (a - b = 2); ASSERT (b - a = -2);
		ASSERT (a * b = 63); ASSERT (b * a = 63);
		ASSERT (a DIV b = 1); ASSERT (b DIV a = 0);
		ASSERT (a MOD b = 2); ASSERT (b MOD a = 7);
	END Test.

positive: set operations

	MODULE Test;
	VAR a, b, c: SET;
	BEGIN
		a := {0, 1, 2}; ASSERT (a = {0..2}); ASSERT ((0 IN a) & (1 IN a) & (2 IN a) & ~(3 IN a) & ~(4 IN a));
		b := {2, 3, 4}; ASSERT (b = {2..4}); ASSERT (~(0 IN b) & ~(1 IN b) & (2 IN b) & (3 IN b) & (4 IN b));
		c := a + b; ASSERT (c = {0..4}); ASSERT ((0 IN c) & (1 IN c) & (2 IN c) & (3 IN c) & (4 IN c));
		c := a - b; ASSERT (c = {0..1}); ASSERT ((0 IN c) & (1 IN c) & ~(2 IN c) & ~(3 IN c) & ~(4 IN c));
		c := a * b; ASSERT (c = {2..2}); ASSERT (~(0 IN c) & ~(1 IN c) & (2 IN c) & ~(3 IN c) & ~(4 IN c));
		c := a / b; ASSERT (c = {0..1, 3..4}); ASSERT ((0 IN c) & (1 IN c) & ~(2 IN c) & (3 IN c) & (4 IN c));
	END Test.

positive: relations

	MODULE Test;
	VAR ai, bi: INTEGER; as, bs: SET; ar, br: REAL;
	BEGIN
		ai := 0; bi := 1; ASSERT (~(ai = bi)); ASSERT (ai # bi); ASSERT (ai < bi); ASSERT (ai <= bi); ASSERT (~(ai > bi)); ASSERT (~(ai >= bi));
		as := {1}; bs := {1, 2}; ASSERT (~(as = bs)); ASSERT (as # bs); ASSERT (as < bs); ASSERT (as <= bs); ASSERT (~(as > bs)); ASSERT (~(as >= bs));
		ar := 0; br := 1; ASSERT (~(ar = br)); ASSERT (ar # br); ASSERT (ar < br); ASSERT (ar <= br); ASSERT (~(ar > br)); ASSERT (~(ar >= br));
	END Test.


# complement

positive: complement on booleans

	MODULE Test;
	VAR value: BOOLEAN;
	BEGIN
		value := TRUE; ASSERT (value); ASSERT (~~value);
		value := FALSE; ASSERT (~value); ASSERT (~~~value);
	END Test.


# relational operations

positive: relational operations on booleans

	MODULE Test;
	VAR value: BOOLEAN;
	BEGIN
		value := TRUE;
		ASSERT (value = TRUE); ASSERT (~(value = FALSE)); ASSERT (value = value);
		ASSERT (value # FALSE); ASSERT (~(value # TRUE)); ASSERT (~(value # value));
		value := FALSE;
		ASSERT (value = FALSE); ASSERT (~(value = TRUE)); ASSERT (value = value);
		ASSERT (value # TRUE); ASSERT (~(value # FALSE)); ASSERT (~(value # value));
	END Test.

positive: relational operations on characters

	MODULE Test;
	VAR value: CHAR;
	BEGIN
		value := 'a';
		ASSERT (value = 'a'); ASSERT (~(value = 'b')); ASSERT (value = value);
		ASSERT (value # 'b'); ASSERT (~(value # 'a')); ASSERT (~(value # value));
		ASSERT (value < 'z'); ASSERT (~(value < 0X)); ASSERT (~(value < value));
		ASSERT (value <= 'z'); ASSERT (~(value <= 0X)); ASSERT (value <= value);
		ASSERT (value > 0X); ASSERT (~(value > 'z')); ASSERT (~(value > value));
		ASSERT (value >= 0X); ASSERT (~(value >= 'z')); ASSERT (value >= value);
	END Test.

positive: relational operations on short integers

	MODULE Test;
	VAR value: SHORTINT;
	BEGIN
		value := 5;
		ASSERT (value = 5); ASSERT (~(value = 6)); ASSERT (value = value);
		ASSERT (value # 6); ASSERT (~(value # 5)); ASSERT (~(value # value));
		ASSERT (value < 6); ASSERT (~(value < 4)); ASSERT (~(value < value));
		ASSERT (value <= 6); ASSERT (~(value <= 4)); ASSERT (value <= value);
		ASSERT (value > 4); ASSERT (~(value > 6)); ASSERT (~(value > value));
		ASSERT (value >= 4); ASSERT (~(value >= 6)); ASSERT (value >= value);
	END Test.

positive: relational operations on integers

	MODULE Test;
	VAR value: INTEGER;
	BEGIN
		value := 5;
		ASSERT (value = 5); ASSERT (~(value = 6)); ASSERT (value = value);
		ASSERT (value # 6); ASSERT (~(value # 5)); ASSERT (~(value # value));
		ASSERT (value < 6); ASSERT (~(value < 4)); ASSERT (~(value < value));
		ASSERT (value <= 6); ASSERT (~(value <= 4)); ASSERT (value <= value);
		ASSERT (value > 4); ASSERT (~(value > 6)); ASSERT (~(value > value));
		ASSERT (value >= 4); ASSERT (~(value >= 6)); ASSERT (value >= value);
	END Test.

positive: relational operations on long integers

	MODULE Test;
	VAR value: LONGINT;
	BEGIN
		value := 5;
		ASSERT (value = 5); ASSERT (~(value = 6)); ASSERT (value = value);
		ASSERT (value # 6); ASSERT (~(value # 5)); ASSERT (~(value # value));
		ASSERT (value < 6); ASSERT (~(value < 4)); ASSERT (~(value < value));
		ASSERT (value <= 6); ASSERT (~(value <= 4)); ASSERT (value <= value);
		ASSERT (value > 4); ASSERT (~(value > 6)); ASSERT (~(value > value));
		ASSERT (value >= 4); ASSERT (~(value >= 6)); ASSERT (value >= value);
	END Test.

positive: relational operations on huge integers

	MODULE Test;
	VAR value: HUGEINT;
	BEGIN
		value := 5;
		ASSERT (value = 5); ASSERT (~(value = 6)); ASSERT (value = value);
		ASSERT (value # 6); ASSERT (~(value # 5)); ASSERT (~(value # value));
		ASSERT (value < 6); ASSERT (~(value < 4)); ASSERT (~(value < value));
		ASSERT (value <= 6); ASSERT (~(value <= 4)); ASSERT (value <= value);
		ASSERT (value > 4); ASSERT (~(value > 6)); ASSERT (~(value > value));
		ASSERT (value >= 4); ASSERT (~(value >= 6)); ASSERT (value >= value);
	END Test.

positive: relational operations on reals

	MODULE Test;
	VAR value: REAL;
	BEGIN
		value := 5;
		ASSERT (value = 5); ASSERT (~(value = 6)); ASSERT (value = value);
		ASSERT (value # 6); ASSERT (~(value # 5)); ASSERT (~(value # value));
		ASSERT (value < 6); ASSERT (~(value < 4)); ASSERT (~(value < value));
		ASSERT (value <= 6); ASSERT (~(value <= 4)); ASSERT (value <= value);
		ASSERT (value > 4); ASSERT (~(value > 6)); ASSERT (~(value > value));
		ASSERT (value >= 4); ASSERT (~(value >= 6)); ASSERT (value >= value);
	END Test.

positive: relational operations on long reals

	MODULE Test;
	VAR value: LONGREAL;
	BEGIN
		value := 5;
		ASSERT (value = 5); ASSERT (~(value = 6)); ASSERT (value = value);
		ASSERT (value # 6); ASSERT (~(value # 5)); ASSERT (~(value # value));
		ASSERT (value < 6); ASSERT (~(value < 4)); ASSERT (~(value < value));
		ASSERT (value <= 6); ASSERT (~(value <= 4)); ASSERT (value <= value);
		ASSERT (value > 4); ASSERT (~(value > 6)); ASSERT (~(value > value));
		ASSERT (value >= 4); ASSERT (~(value >= 6)); ASSERT (value >= value);
	END Test.

positive: relational operations on sets

	MODULE Test;
	VAR value: SET;
	BEGIN
		value := {1, 2};
		ASSERT (value = {1, 2}); ASSERT (~(value = {2})); ASSERT (value = value);
		ASSERT (value # {2}); ASSERT (~(value # {1, 2})); ASSERT (~(value # value));
		ASSERT (value < {1, 2, 3}); ASSERT (~(value < {2})); ASSERT (~(value < value));
		ASSERT (value <= {1, 2, 3}); ASSERT (~(value <= {2})); ASSERT (value <= value);
		ASSERT (value > {2}); ASSERT (~(value > {1, 2, 3})); ASSERT (~(value > value));
		ASSERT (value >= {2}); ASSERT (~(value >= {1, 2, 3})); ASSERT (value >= value);
	END Test.

positive: relational operations on character arrays

	MODULE Test;
	VAR value: ARRAY 10 OF CHAR;
	BEGIN
		value := "text";
		ASSERT (value = "text"); ASSERT (~(value = "abc")); ASSERT (value = value);
		ASSERT (value # "abc"); ASSERT (~(value # "text")); ASSERT (~(value # value));
		ASSERT (value < "xyz"); ASSERT (~(value < "abc")); ASSERT (~(value < value));
		ASSERT (value <= "xyz"); ASSERT (~(value <= "abc")); ASSERT (value <= value);
		ASSERT (value > "abc"); ASSERT (~(value > "xyz")); ASSERT (~(value > value));
		ASSERT (value >= "abc"); ASSERT (~(value >= "xyz")); ASSERT (value >= value);
		ASSERT (value[0] = 't'); ASSERT (value[1] = 'e'); ASSERT (value[2] = 'x'); ASSERT (value[3] = 't'); ASSERT (value[4] = 0X);
	END Test.


# negation

positive: negation on short integers

	MODULE Test;
	VAR value: SHORTINT;
	BEGIN value := 5; ASSERT (-value = -5); ASSERT (-(-value) = 5); ASSERT (-(-value) = value)
	END Test.

positive: negation on integers

	MODULE Test;
	VAR value: INTEGER;
	BEGIN value := 5; ASSERT (-value = -5); ASSERT (-(-value) = 5); ASSERT (-(-value) = value)
	END Test.

positive: negation on long integers

	MODULE Test;
	VAR value: LONGINT;
	BEGIN value := 5; ASSERT (-value = -5); ASSERT (-(-value) = 5); ASSERT (-(-value) = value)
	END Test.

positive: negation on huge integers

	MODULE Test;
	VAR value: HUGEINT;
	BEGIN value := 5; ASSERT (-value = -5); ASSERT (-(-value) = 5); ASSERT (-(-value) = value)
	END Test.

positive: negation on reals

	MODULE Test;
	VAR value: REAL;
	BEGIN value := 5; ASSERT (-value = -5); ASSERT (-(-value) = 5); ASSERT (-(-value) = value)
	END Test.

positive: negation on long reals

	MODULE Test;
	VAR value: LONGREAL;
	BEGIN value := 5; ASSERT (-value = -5); ASSERT (-(-value) = 5); ASSERT (-(-value) = value)
	END Test.

positive: negation on sets

	MODULE Test;
	VAR value: SET;
	BEGIN value := {1, 2}; ASSERT (-value = {0, 3 .. MAX (SET)}); ASSERT (-(-value) = {1, 2}); ASSERT (-(-value) = value)
	END Test.


# absolute value

positive: absolute value of short integer

	MODULE Test;
	VAR value: SHORTINT;
	BEGIN
		value := 5; ASSERT (ABS (value) = 5); ASSERT (ABS (-value) = 5); ASSERT (ABS (value) = value); ASSERT (ABS (-value) = value);
		value := -5; ASSERT (ABS (value) = 5); ASSERT (ABS (-value) = 5); ASSERT (ABS (value) = -value); ASSERT (ABS (-value) = -value);
	END Test.

positive: absolute value of integer

	MODULE Test;
	VAR value: INTEGER;
	BEGIN
		value := 5; ASSERT (ABS (value) = 5); ASSERT (ABS (-value) = 5); ASSERT (ABS (value) = value); ASSERT (ABS (-value) = value);
		value := -5; ASSERT (ABS (value) = 5); ASSERT (ABS (-value) = 5); ASSERT (ABS (value) = -value); ASSERT (ABS (-value) = -value);
	END Test.

positive: absolute value of long integer

	MODULE Test;
	VAR value: LONGINT;
	BEGIN
		value := 5; ASSERT (ABS (value) = 5); ASSERT (ABS (-value) = 5); ASSERT (ABS (value) = value); ASSERT (ABS (-value) = value);
		value := -5; ASSERT (ABS (value) = 5); ASSERT (ABS (-value) = 5); ASSERT (ABS (value) = -value); ASSERT (ABS (-value) = -value);
	END Test.

positive: absolute value of huge integer

	MODULE Test;
	VAR value: HUGEINT;
	BEGIN
		value := 5; ASSERT (ABS (value) = 5); ASSERT (ABS (-value) = 5); ASSERT (ABS (value) = value); ASSERT (ABS (-value) = value);
		value := -5; ASSERT (ABS (value) = 5); ASSERT (ABS (-value) = 5); ASSERT (ABS (value) = -value); ASSERT (ABS (-value) = -value);
	END Test.

positive: absolute value of real

	MODULE Test;
	VAR value: REAL;
	BEGIN
		value := 5; ASSERT (ABS (value) = 5); ASSERT (ABS (-value) = 5); ASSERT (ABS (value) = value); ASSERT (ABS (-value) = value);
		value := -5; ASSERT (ABS (value) = 5); ASSERT (ABS (-value) = 5); ASSERT (ABS (value) = -value); ASSERT (ABS (-value) = -value);
	END Test.

positive: absolute value of long real

	MODULE Test;
	VAR value: LONGREAL;
	BEGIN
		value := 5; ASSERT (ABS (value) = 5); ASSERT (ABS (-value) = 5); ASSERT (ABS (value) = value); ASSERT (ABS (-value) = value);
		value := -5; ASSERT (ABS (value) = 5); ASSERT (ABS (-value) = 5); ASSERT (ABS (value) = -value); ASSERT (ABS (-value) = -value);
	END Test.


# logical operations

positive: logical and on booleans

	MODULE Test;
	VAR a, b: BOOLEAN;
	BEGIN
		a := FALSE; b := FALSE; ASSERT (a & b = FALSE);
		a := FALSE; b := TRUE; ASSERT (a & b = FALSE);
		a := TRUE; b := FALSE; ASSERT (a & b = FALSE);
		a := TRUE; b := TRUE; ASSERT (a & b = TRUE);
	END Test.

positive: logical and on boolean return values

	MODULE Test;
	PROCEDURE True (): BOOLEAN; BEGIN RETURN TRUE; END True;
	PROCEDURE False (): BOOLEAN; BEGIN RETURN FALSE; END False;
	BEGIN
		ASSERT (False () & False () = FALSE);
		ASSERT (False () & True () = FALSE);
		ASSERT (True () & False () = FALSE);
		ASSERT (True () & True () = TRUE);
	END Test.

positive: logical or on booleans

	MODULE Test;
	VAR a, b: BOOLEAN;
	BEGIN
		a := FALSE; b := FALSE; ASSERT (a OR b = FALSE);
		a := FALSE; b := TRUE; ASSERT (a OR b = TRUE);
		a := TRUE; b := FALSE; ASSERT (a OR b = TRUE);
		a := TRUE; b := TRUE; ASSERT (a OR b = TRUE);
	END Test.

positive: logical or on boolean return values

	MODULE Test;
	PROCEDURE True (): BOOLEAN; BEGIN RETURN TRUE; END True;
	PROCEDURE False (): BOOLEAN; BEGIN RETURN FALSE; END False;
	BEGIN
		ASSERT (False () OR False () = FALSE);
		ASSERT (False () OR True () = TRUE);
		ASSERT (True () OR False () = TRUE);
		ASSERT (True () OR True () = TRUE);
	END Test.

positive: short-circuit evaluation

	MODULE Test;
	PROCEDURE True (): BOOLEAN; BEGIN RETURN TRUE; END True;
	PROCEDURE False (): BOOLEAN; BEGIN RETURN FALSE; END False;
	PROCEDURE Halt (): BOOLEAN; BEGIN HALT (1234); END Halt;
	BEGIN
		ASSERT (False () & Halt () = FALSE);
		ASSERT (True () OR Halt () = TRUE);
	END Test.


# capital letter operation

positive: capital letter of character

	MODULE Test;
	VAR value: CHAR;
	BEGIN
		value := '0'; ASSERT (CAP (value) = '0'); ASSERT (CAP (value) = CAP ('0'));
		value := '9'; ASSERT (CAP (value) = '9'); ASSERT (CAP (value) = CAP ('9'));
		value := 'a'; ASSERT (CAP (value) = 'A'); ASSERT (CAP (value) = CAP ('a'));
		value := 'z'; ASSERT (CAP (value) = 'Z'); ASSERT (CAP (value) = CAP ('z'));
		value := 'A'; ASSERT (CAP (value) = 'A'); ASSERT (CAP (value) = CAP ('A'));
		value := 'Z'; ASSERT (CAP (value) = 'Z'); ASSERT (CAP (value) = CAP ('Z'));
	END Test.

# character annd ordinal value operations

positive: ordinal value of character

	MODULE Test;
	VAR value: CHAR; i: INTEGER;
	BEGIN
		value := '0'; ASSERT (ORD (value) = ORD ('0'));
		value := '9'; ASSERT (ORD (value) = ORD ('9'));
		value := 'a'; ASSERT (ORD (value) = ORD ('a'));
		value := 'z'; ASSERT (ORD (value) = ORD ('z'));
		value := 'A'; ASSERT (ORD (value) = ORD ('A'));
		value := 'Z'; ASSERT (ORD (value) = ORD ('Z'));
		FOR i := ORD (0X) TO ORD (0FFX) DO value := CHR (i); ASSERT (ORD (value) = i); END;
	END Test.

positive: character value of short integer

	MODULE Test;
	VAR value: SHORTINT;
	BEGIN
		value := ORD ('0'); ASSERT (CHR (value) = '0');
		value := ORD ('9'); ASSERT (CHR (value) = '9');
		value := ORD ('a'); ASSERT (CHR (value) = 'a');
		value := ORD ('z'); ASSERT (CHR (value) = 'z');
		value := ORD ('A'); ASSERT (CHR (value) = 'A');
		value := ORD ('Z'); ASSERT (CHR (value) = 'Z');
	END Test.

positive: character value of integer

	MODULE Test;
	VAR value: INTEGER;
	BEGIN
		value := ORD ('0'); ASSERT (CHR (value) = '0');
		value := ORD ('9'); ASSERT (CHR (value) = '9');
		value := ORD ('a'); ASSERT (CHR (value) = 'a');
		value := ORD ('z'); ASSERT (CHR (value) = 'z');
		value := ORD ('A'); ASSERT (CHR (value) = 'A');
		value := ORD ('Z'); ASSERT (CHR (value) = 'Z');
	END Test.

positive: character value of long integer

	MODULE Test;
	VAR value: LONGINT;
	BEGIN
		value := ORD ('0'); ASSERT (CHR (value) = '0');
		value := ORD ('9'); ASSERT (CHR (value) = '9');
		value := ORD ('a'); ASSERT (CHR (value) = 'a');
		value := ORD ('z'); ASSERT (CHR (value) = 'z');
		value := ORD ('A'); ASSERT (CHR (value) = 'A');
		value := ORD ('Z'); ASSERT (CHR (value) = 'Z');
	END Test.

positive: character value of huge integer

	MODULE Test;
	VAR value: HUGEINT;
	BEGIN
		value := ORD ('0'); ASSERT (CHR (value) = '0');
		value := ORD ('9'); ASSERT (CHR (value) = '9');
		value := ORD ('a'); ASSERT (CHR (value) = 'a');
		value := ORD ('z'); ASSERT (CHR (value) = 'z');
		value := ORD ('A'); ASSERT (CHR (value) = 'A');
		value := ORD ('Z'); ASSERT (CHR (value) = 'Z');
	END Test.


# set element operations

positive: short integer as set element

	MODULE Test;
	VAR element: SHORTINT; set: SET;
	BEGIN
		element := MIN (SET); set := {element}; ASSERT (element IN set); ASSERT (set - {element} = {});
		element := MIN (SET) + 2; set := {element}; ASSERT (element IN set); ASSERT (set - {element} = {});
		element := MAX (SET); set := {element}; ASSERT (element IN set); ASSERT (set - {element} = {});
		element := MAX (SET) - 2; set := {element}; ASSERT (element IN set); ASSERT (set - {element} = {});
	END Test.

negative: short integer as too small set element

	MODULE Test;
	VAR element: SHORTINT; set: SET;
	BEGIN element := MIN (SET) - 1; set := {element};
	END Test.

negative: short integer as too large set element

	MODULE Test;
	VAR element: SHORTINT; set: SET;
	BEGIN element := MAX (SET) + 1; set := {element};
	END Test.

positive: short integer as first set element

	MODULE Test;
	VAR element: SHORTINT; set: SET;
	BEGIN
		element := MIN (SET); set := {element .. MAX (SET)}; ASSERT (element IN set); ASSERT (set = {MIN (SET) .. MAX (SET)}); ASSERT (-set = {});
		element := MIN (SET); set := {element .. MIN (SET)}; ASSERT (element IN set); ASSERT (set = {MIN (SET) .. MIN (SET)}); ASSERT (set = {element}); ASSERT (set = {MIN (SET)});
		element := MIN (SET) + 2; set := {element .. MAX (SET)}; ASSERT (element IN set); ASSERT (set = {MIN (SET) + 2 .. MAX (SET)}); ASSERT (-set = {MIN (SET), MIN (SET) + 1});
		element := MIN (SET) + 2; set := {element .. MIN (SET)}; ASSERT (~(element IN set)); ASSERT (set = {element .. MIN (SET)}); ASSERT (set = {});
	END Test.

negative: short integer as too small first set element

	MODULE Test;
	VAR element: SHORTINT; set: SET;
	BEGIN element := MIN (SET) - 1;set := {element .. MAX (SET)};
	END Test.

negative: short integer as too large first set element

	MODULE Test;
	VAR element: SHORTINT; set: SET;
	BEGIN element := MAX (SET) + 1;set := {element .. MAX (SET)};
	END Test.

positive: short integer as last set element

	MODULE Test;
	VAR element: SHORTINT; set: SET;
	BEGIN
		element := MAX (SET); set := {MIN (SET) .. element}; ASSERT (element IN set); ASSERT (set = {MIN (SET) .. MAX (SET)}); ASSERT (-set = {});
		element := MAX (SET); set := {MAX (SET) .. element}; ASSERT (element IN set); ASSERT (set = {MAX (SET) .. MAX (SET)}); ASSERT (set = {MAX (SET)});
		element := MAX (SET) - 2; set := {MIN (SET) .. element}; ASSERT (element IN set); ASSERT (set = {MIN (SET) .. MAX (SET) - 2}); ASSERT (-set = {MAX (SET) - 1, MAX (SET)});
		element := MAX (SET) - 2; set := {MAX (SET).. element}; ASSERT (~(element IN set)); ASSERT (set = {MAX (SET) .. element}); ASSERT (set = {});
	END Test.

negative: short integer as too small last set element

	MODULE Test;
	VAR element: SHORTINT; set: SET;
	BEGIN element := MIN (SET) - 1;set := {MIN (SET) .. element};
	END Test.

negative: short integer as too large last set element

	MODULE Test;
	VAR element: SHORTINT; set: SET;
	BEGIN element := MAX (SET) + 1;set := {MIN (SET) .. element};
	END Test.

positive: short integers as set elements

	MODULE Test;
	VAR first, last: SHORTINT; set: SET;
	BEGIN
		first := MIN (SET); last := MAX (SET); set := {first .. last}; ASSERT (set = {MIN (SET) .. MAX (SET)});
		ASSERT (first IN set); ASSERT (last IN set); ASSERT (-set = {});
		first := MIN (SET) + 2; last := MAX (SET) - 2; set := {first .. last}; ASSERT (set = {MIN (SET) + 2 .. MAX (SET) - 2});
		ASSERT (first IN set); ASSERT (last IN set); ASSERT (-set = {MIN (SET), MIN (SET) + 1, MAX (SET) - 1, MAX (SET)});
		first := MIN (SET) + 2; last := first; set := {first .. last}; ASSERT (set = {first});
		first := MIN (SET) + 2; last := first + 1; set := {first .. last}; ASSERT (set = {first, last});
		first := MIN (SET) + 2; last := first - 1; set := {first .. last}; ASSERT (set = {});
	END Test.

positive: integer as set element

	MODULE Test;
	VAR element: INTEGER; set: SET;
	BEGIN
		element := MIN (SET); set := {element}; ASSERT (element IN set); ASSERT (set - {element} = {});
		element := MAX (SET); set := {element}; ASSERT (element IN set); ASSERT (set - {element} = {});
	END Test.

negative: integer as too small set element

	MODULE Test;
	VAR element: INTEGER; set: SET;
	BEGIN element := MIN (SET) - 1; set := {element};
	END Test.

negative: integer as too large set element

	MODULE Test;
	VAR element: INTEGER; set: SET;
	BEGIN element := MAX (SET) + 1; set := {element};
	END Test.

positive: integer as first set element

	MODULE Test;
	VAR element: INTEGER; set: SET;
	BEGIN
		element := MIN (SET); set := {element .. MAX (SET)}; ASSERT (element IN set); ASSERT (set = {MIN (SET) .. MAX (SET)}); ASSERT (-set = {});
		element := MIN (SET); set := {element .. MIN (SET)}; ASSERT (element IN set); ASSERT (set = {MIN (SET) .. MIN (SET)}); ASSERT (set = {element}); ASSERT (set = {MIN (SET)});
		element := MIN (SET) + 2; set := {element .. MAX (SET)}; ASSERT (element IN set); ASSERT (set = {MIN (SET) + 2 .. MAX (SET)}); ASSERT (-set = {MIN (SET), MIN (SET) + 1});
		element := MIN (SET) + 2; set := {element .. MIN (SET)}; ASSERT (~(element IN set)); ASSERT (set = {element .. MIN (SET)}); ASSERT (set = {});
	END Test.

negative: integer as too small first set element

	MODULE Test;
	VAR element: INTEGER; set: SET;
	BEGIN element := MIN (SET) - 1;set := {element .. MAX (SET)};
	END Test.

negative: integer as too large first set element

	MODULE Test;
	VAR element: INTEGER; set: SET;
	BEGIN element := MAX (SET) + 1;set := {element .. MAX (SET)};
	END Test.

positive: integer as last set element

	MODULE Test;
	VAR element: INTEGER; set: SET;
	BEGIN
		element := MAX (SET); set := {MIN (SET) .. element}; ASSERT (element IN set); ASSERT (set = {MIN (SET) .. MAX (SET)}); ASSERT (-set = {});
		element := MAX (SET); set := {MAX (SET) .. element}; ASSERT (element IN set); ASSERT (set = {MAX (SET) .. MAX (SET)}); ASSERT (set = {MAX (SET)});
		element := MAX (SET) - 2; set := {MIN (SET) .. element}; ASSERT (element IN set); ASSERT (set = {MIN (SET) .. MAX (SET) - 2}); ASSERT (-set = {MAX (SET) - 1, MAX (SET)});
		element := MAX (SET) - 2; set := {MAX (SET).. element}; ASSERT (~(element IN set)); ASSERT (set = {MAX (SET) .. element}); ASSERT (set = {});
	END Test.

negative: integer as too small last set element

	MODULE Test;
	VAR element: INTEGER; set: SET;
	BEGIN element := MIN (SET) - 1;set := {MIN (SET) .. element};
	END Test.

negative: integer as too large last set element

	MODULE Test;
	VAR element: INTEGER; set: SET;
	BEGIN element := MAX (SET) + 1;set := {MIN (SET) .. element};
	END Test.

positive: integers as set elements

	MODULE Test;
	VAR first, last: INTEGER; set: SET;
	BEGIN
		first := MIN (SET); last := MAX (SET); set := {first .. last}; ASSERT (set = {MIN (SET) .. MAX (SET)});
		ASSERT (first IN set); ASSERT (last IN set); ASSERT (-set = {});
		first := MIN (SET) + 2; last := MAX (SET) - 2; set := {first .. last}; ASSERT (set = {MIN (SET) + 2 .. MAX (SET) - 2});
		ASSERT (first IN set); ASSERT (last IN set); ASSERT (-set = {MIN (SET), MIN (SET) + 1, MAX (SET) - 1, MAX (SET)});
		first := MIN (SET) + 2; last := first; set := {first .. last}; ASSERT (set = {first});
		first := MIN (SET) + 2; last := first + 1; set := {first .. last}; ASSERT (set = {first, last});
		first := MIN (SET) + 2; last := first - 1; set := {first .. last}; ASSERT (set = {});
	END Test.

positive: long integer as set element

	MODULE Test;
	VAR element: LONGINT; set: SET;
	BEGIN
		element := MIN (SET); set := {element}; ASSERT (element IN set); ASSERT (set - {element} = {});
		element := MAX (SET); set := {element}; ASSERT (element IN set); ASSERT (set - {element} = {});
	END Test.

negative: long integer as too small set element

	MODULE Test;
	VAR element: LONGINT; set: SET;
	BEGIN element := MIN (SET) - 1; set := {element};
	END Test.

negative: long integer as too large set element

	MODULE Test;
	VAR element: LONGINT; set: SET;
	BEGIN element := MAX (SET) + 1; set := {element};
	END Test.

positive: long integer as first set element

	MODULE Test;
	VAR element: LONGINT; set: SET;
	BEGIN
		element := MIN (SET); set := {element .. MAX (SET)}; ASSERT (element IN set); ASSERT (set = {MIN (SET) .. MAX (SET)}); ASSERT (-set = {});
		element := MIN (SET); set := {element .. MIN (SET)}; ASSERT (element IN set); ASSERT (set = {MIN (SET) .. MIN (SET)}); ASSERT (set = {element}); ASSERT (set = {MIN (SET)});
		element := MIN (SET) + 2; set := {element .. MAX (SET)}; ASSERT (element IN set); ASSERT (set = {MIN (SET) + 2 .. MAX (SET)}); ASSERT (-set = {MIN (SET), MIN (SET) + 1});
		element := MIN (SET) + 2; set := {element .. MIN (SET)}; ASSERT (~(element IN set)); ASSERT (set = {element .. MIN (SET)}); ASSERT (set = {});
	END Test.

negative: long integer as too small first set element

	MODULE Test;
	VAR element: LONGINT; set: SET;
	BEGIN element := MIN (SET) - 1;set := {element .. MAX (SET)};
	END Test.

negative: long integer as too large first set element

	MODULE Test;
	VAR element: LONGINT; set: SET;
	BEGIN element := MAX (SET) + 1;set := {element .. MAX (SET)};
	END Test.

positive: long integer as last set element

	MODULE Test;
	VAR element: LONGINT; set: SET;
	BEGIN
		element := MAX (SET); set := {MIN (SET) .. element}; ASSERT (element IN set); ASSERT (set = {MIN (SET) .. MAX (SET)}); ASSERT (-set = {});
		element := MAX (SET); set := {MAX (SET) .. element}; ASSERT (element IN set); ASSERT (set = {MAX (SET) .. MAX (SET)}); ASSERT (set = {MAX (SET)});
		element := MAX (SET) - 2; set := {MIN (SET) .. element}; ASSERT (element IN set); ASSERT (set = {MIN (SET) .. MAX (SET) - 2}); ASSERT (-set = {MAX (SET) - 1, MAX (SET)});
		element := MAX (SET) - 2; set := {MAX (SET).. element}; ASSERT (~(element IN set)); ASSERT (set = {MAX (SET) .. element}); ASSERT (set = {});
	END Test.

negative: long integer as too small last set element

	MODULE Test;
	VAR element: LONGINT; set: SET;
	BEGIN element := MIN (SET) - 1;set := {MIN (SET) .. element};
	END Test.

negative: long integer as too large last set element

	MODULE Test;
	VAR element: LONGINT; set: SET;
	BEGIN element := MAX (SET) + 1;set := {MIN (SET) .. element};
	END Test.

positive: long integers as set elements

	MODULE Test;
	VAR first, last: LONGINT; set: SET;
	BEGIN
		first := MIN (SET); last := MAX (SET); set := {first .. last}; ASSERT (set = {MIN (SET) .. MAX (SET)});
		ASSERT (first IN set); ASSERT (last IN set); ASSERT (-set = {});
		first := MIN (SET) + 2; last := MAX (SET) - 2; set := {first .. last}; ASSERT (set = {MIN (SET) + 2 .. MAX (SET) - 2});
		ASSERT (first IN set); ASSERT (last IN set); ASSERT (-set = {MIN (SET), MIN (SET) + 1, MAX (SET) - 1, MAX (SET)});
		first := MIN (SET) + 2; last := first; set := {first .. last}; ASSERT (set = {first});
		first := MIN (SET) + 2; last := first + 1; set := {first .. last}; ASSERT (set = {first, last});
		first := MIN (SET) + 2; last := first - 1; set := {first .. last}; ASSERT (set = {});
	END Test.

positive: huge integer as set element

	MODULE Test;
	VAR element: HUGEINT; set: SET;
	BEGIN
		element := MIN (SET); set := {element}; ASSERT (element IN set); ASSERT (set - {element} = {});
		element := MAX (SET); set := {element}; ASSERT (element IN set); ASSERT (set - {element} = {});
	END Test.

negative: huge integer as too small set element

	MODULE Test;
	VAR element: HUGEINT; set: SET;
	BEGIN element := MIN (SET) - 1; set := {element};
	END Test.

negative: huge integer as too large set element

	MODULE Test;
	VAR element: HUGEINT; set: SET;
	BEGIN element := MAX (SET) + 1; set := {element};
	END Test.

positive: huge integer as first set element

	MODULE Test;
	VAR element: HUGEINT; set: SET;
	BEGIN
		element := MIN (SET); set := {element .. MAX (SET)}; ASSERT (element IN set); ASSERT (set = {MIN (SET) .. MAX (SET)}); ASSERT (-set = {});
		element := MIN (SET); set := {element .. MIN (SET)}; ASSERT (element IN set); ASSERT (set = {MIN (SET) .. MIN (SET)}); ASSERT (set = {element}); ASSERT (set = {MIN (SET)});
		element := MIN (SET) + 2; set := {element .. MAX (SET)}; ASSERT (element IN set); ASSERT (set = {MIN (SET) + 2 .. MAX (SET)}); ASSERT (-set = {MIN (SET), MIN (SET) + 1});
		element := MIN (SET) + 2; set := {element .. MIN (SET)}; ASSERT (~(element IN set)); ASSERT (set = {element .. MIN (SET)}); ASSERT (set = {});
	END Test.

negative: huge integer as too small first set element

	MODULE Test;
	VAR element: HUGEINT; set: SET;
	BEGIN element := MIN (SET) - 1;set := {element .. MAX (SET)};
	END Test.

negative: huge integer as too large first set element

	MODULE Test;
	VAR element: HUGEINT; set: SET;
	BEGIN element := MAX (SET) + 1;set := {element .. MAX (SET)};
	END Test.

positive: huge integer as last set element

	MODULE Test;
	VAR element: HUGEINT; set: SET;
	BEGIN
		element := MAX (SET); set := {MIN (SET) .. element}; ASSERT (element IN set); ASSERT (set = {MIN (SET) .. MAX (SET)}); ASSERT (-set = {});
		element := MAX (SET); set := {MAX (SET) .. element}; ASSERT (element IN set); ASSERT (set = {MAX (SET) .. MAX (SET)}); ASSERT (set = {MAX (SET)});
		element := MAX (SET) - 2; set := {MIN (SET) .. element}; ASSERT (element IN set); ASSERT (set = {MIN (SET) .. MAX (SET) - 2}); ASSERT (-set = {MAX (SET) - 1, MAX (SET)});
		element := MAX (SET) - 2; set := {MAX (SET).. element}; ASSERT (~(element IN set)); ASSERT (set = {MAX (SET) .. element}); ASSERT (set = {});
	END Test.

negative: huge integer as too small last set element

	MODULE Test;
	VAR element: HUGEINT; set: SET;
	BEGIN element := MIN (SET) - 1;set := {MIN (SET) .. element};
	END Test.

negative: huge integer as too large last set element

	MODULE Test;
	VAR element: HUGEINT; set: SET;
	BEGIN element := MAX (SET) + 1;set := {MIN (SET) .. element};
	END Test.

positive: huge integers as set elements

	MODULE Test;
	VAR first, last: HUGEINT; set: SET;
	BEGIN
		first := MIN (SET); last := MAX (SET); set := {first .. last}; ASSERT (set = {MIN (SET) .. MAX (SET)});
		ASSERT (first IN set); ASSERT (last IN set); ASSERT (-set = {});
		first := MIN (SET) + 2; last := MAX (SET) - 2; set := {first .. last}; ASSERT (set = {MIN (SET) + 2 .. MAX (SET) - 2});
		ASSERT (first IN set); ASSERT (last IN set); ASSERT (-set = {MIN (SET), MIN (SET) + 1, MAX (SET) - 1, MAX (SET)});
		first := MIN (SET) + 2; last := first; set := {first .. last}; ASSERT (set = {first});
		first := MIN (SET) + 2; last := first + 1; set := {first .. last}; ASSERT (set = {first, last});
		first := MIN (SET) + 2; last := first - 1; set := {first .. last}; ASSERT (set = {});
	END Test.


# odd test

positive: odd test on short integer

	MODULE Test;
	VAR value: SHORTINT;
	BEGIN
		value := 0; ASSERT (~ODD (value)); ASSERT (ODD (value + 1));
		value := 5; ASSERT (ODD (value)); ASSERT (~ODD (value + 1));
		value := -5; ASSERT (ODD (value)); ASSERT (~ODD (value + 1));
	END Test.

positive: odd test on integer

	MODULE Test;
	VAR value: INTEGER;
	BEGIN
		value := 0; ASSERT (~ODD (value)); ASSERT (ODD (value + 1));
		value := 5; ASSERT (ODD (value)); ASSERT (~ODD (value + 1));
		value := -5; ASSERT (ODD (value)); ASSERT (~ODD (value + 1));
	END Test.

positive: odd test on long integer

	MODULE Test;
	VAR value: LONGINT;
	BEGIN
		value := 0; ASSERT (~ODD (value)); ASSERT (ODD (value + 1));
		value := 5; ASSERT (ODD (value)); ASSERT (~ODD (value + 1));
		value := -5; ASSERT (ODD (value)); ASSERT (~ODD (value + 1));
	END Test.

positive: odd test on huge integer

	MODULE Test;
	VAR value: HUGEINT;
	BEGIN
		value := 0; ASSERT (~ODD (value)); ASSERT (ODD (value + 1));
		value := 5; ASSERT (ODD (value)); ASSERT (~ODD (value + 1));
		value := -5; ASSERT (ODD (value)); ASSERT (~ODD (value + 1));
	END Test.


# explicit basic type conversions

positive: long on short integer

	MODULE Test;
	VAR value: SHORTINT;
	BEGIN value := 11H; ASSERT (LONG (value) = 11H); ASSERT (LONG (value) = LONG (11H));
	END Test.

positive: long on integer

	MODULE Test;
	VAR value: INTEGER;
	BEGIN value := 1122H; ASSERT (LONG (value) = 1122H); ASSERT (LONG (value) = LONG (1122H));
	END Test.

positive: long on long integer

	MODULE Test;
	VAR value: LONGINT;
	BEGIN value := 11223344H; ASSERT (LONG (value) = 11223344H); ASSERT (LONG (value) = LONG (11223344H));
	END Test.

positive: short on integer

	MODULE Test;
	VAR value: INTEGER;
	BEGIN value := 1122H; ASSERT (SHORT (value) = SHORT (INTEGER(1122H)));
	END Test.

positive: short on long integer

	MODULE Test;
	VAR value: LONGINT;
	BEGIN value := 11223344H;ASSERT (SHORT (value) = SHORT (LONGINT(11223344H)));
	END Test.

positive: short on huge integer

	MODULE Test;
	VAR value: HUGEINT;
	BEGIN value := 1122334455667788H; ASSERT (SHORT (value) = SHORT (HUGEINT(1122334455667788H)));
	END Test.

positive: entier on reals

	MODULE Test;
	VAR value: REAL;
	BEGIN
		value := 0; ASSERT (ENTIER (value) = 0);
		value := 1; ASSERT (ENTIER (value) = 1);
		value := 1.75; ASSERT (ENTIER (value) = 1);
		value := -1; ASSERT (ENTIER (value) = -1);
		value := -1.75; ASSERT (ENTIER (value) = -2);
	END Test.

positive: entier on long reals

	MODULE Test;
	VAR value: LONGREAL;
	BEGIN
		value := 0; ASSERT (ENTIER (value) = 0);
		value := 1; ASSERT (ENTIER (value) = 1);
		value := 1.75; ASSERT (ENTIER (value) = 1);
		value := -1; ASSERT (ENTIER (value) = -1);
		value := -1.75; ASSERT (ENTIER (value) = -2);
	END Test.


# arithmetic operations

positive: addition on short integers

	MODULE Test;
	VAR a, b: SHORTINT;
	BEGIN
		a := 3; b := 2; ASSERT (a + b = +5); ASSERT (a + b = 3 + 2);
		a := -3; b := 2; ASSERT (a + b = -1); ASSERT (a + b = (-3) + 2);
		a := 3; b := -2; ASSERT (a + b = +1); ASSERT (a + b = 3 + (-2));
		a := -3; b := -2; ASSERT (a + b = -5); ASSERT (a + b = (-3) + (-2));
		a := MAX (SHORTINT); b := MIN (SHORTINT) + 1; ASSERT (a + b = 0); ASSERT (a + b = MAX (SHORTINT) + MIN (SHORTINT) + 1);
	END Test.

positive: addition on integers

	MODULE Test;
	VAR a, b: INTEGER;
	BEGIN
		a := 3; b := 2; ASSERT (a + b = +5); ASSERT (a + b = 3 + 2);
		a := -3; b := 2; ASSERT (a + b = -1); ASSERT (a + b = (-3) + 2);
		a := 3; b := -2; ASSERT (a + b = +1); ASSERT (a + b = 3 + (-2));
		a := -3; b := -2; ASSERT (a + b = -5); ASSERT (a + b = (-3) + (-2));
		a := MAX (INTEGER); b := MIN (INTEGER) + 1; ASSERT (a + b = 0); ASSERT (a + b = MAX (INTEGER) + MIN (INTEGER) + 1);
	END Test.

positive: addition on long integers

	MODULE Test;
	VAR a, b: LONGINT;
	BEGIN
		a := 3; b := 2; ASSERT (a + b = +5); ASSERT (a + b = 3 + 2);
		a := -3; b := 2; ASSERT (a + b = -1); ASSERT (a + b = (-3) + 2);
		a := 3; b := -2; ASSERT (a + b = +1); ASSERT (a + b = 3 + (-2));
		a := -3; b := -2; ASSERT (a + b = -5); ASSERT (a + b = (-3) + (-2));
		a := MAX (LONGINT); b := MIN (LONGINT) + 1; ASSERT (a + b = 0); ASSERT (a + b = MAX (LONGINT) + MIN (LONGINT) + 1);
	END Test.

positive: addition on huge integers

	MODULE Test;
	VAR a, b: HUGEINT;
	BEGIN
		a := 3; b := 2; ASSERT (a + b = +5); ASSERT (a + b = 3 + 2);
		a := -3; b := 2; ASSERT (a + b = -1); ASSERT (a + b = (-3) + 2);
		a := 3; b := -2; ASSERT (a + b = +1); ASSERT (a + b = 3 + (-2));
		a := -3; b := -2; ASSERT (a + b = -5); ASSERT (a + b = (-3) + (-2));
		a := MAX (HUGEINT); b := MIN (HUGEINT) + 1; ASSERT (a + b = 0); ASSERT (a + b = MAX (HUGEINT) + MIN (HUGEINT) + 1);
	END Test.

positive: addition on reals

	MODULE Test;
	VAR a, b: REAL;
	BEGIN
		a := 3.5; b := 2.5; ASSERT (a + b = +6); ASSERT (a + b = 3.5 + 2.5);
		a := -3.5; b := 2.5; ASSERT (a + b = -1); ASSERT (a + b = (-3.5) + 2.5);
		a := 3.5; b := -2.5; ASSERT (a + b = +1); ASSERT (a + b = 3.5 + (-2.5));
		a := -3.5; b := -2.5; ASSERT (a + b = -6); ASSERT (a + b = (-3.5) + (-2.5));
	END Test.

positive: addition on long reals

	MODULE Test;
	VAR a, b: LONGREAL;
	BEGIN
		a := 3; b := 2; ASSERT (a + b = +5); ASSERT (a + b = 3 + 2);
		a := -3; b := 2; ASSERT (a + b = -1); ASSERT (a + b = (-3) + 2);
		a := 3; b := -2; ASSERT (a + b = +1); ASSERT (a + b = 3 + (-2));
		a := -3; b := -2; ASSERT (a + b = -5); ASSERT (a + b = (-3) + (-2));
	END Test.

positive: subtraction on short integers

	MODULE Test;
	VAR a, b: SHORTINT;
	BEGIN
		a := 3; b := 2; ASSERT (a - b = +1); ASSERT (a - b = 3 - 2);
		a := -3; b := 2; ASSERT (a - b = -5); ASSERT (a - b = (-3) - 2);
		a := 3; b := -2; ASSERT (a - b = +5); ASSERT (a - b = 3 - (-2));
		a := -3; b := -2; ASSERT (a - b = -1); ASSERT (a - b = (-3) - (-2));
		a := MIN (SHORTINT) + 1; b := MAX (SHORTINT); ASSERT (a - b = 2); ASSERT (a - b = SHORT (INTEGER(MIN (SHORTINT) + 1 - MAX (SHORTINT))));
	END Test.

positive: subtraction on integers

	MODULE Test;
	VAR a, b: INTEGER;
	BEGIN
		a := 3; b := 2; ASSERT (a - b = +1); ASSERT (a - b = 3 - 2);
		a := -3; b := 2; ASSERT (a - b = -5); ASSERT (a - b = (-3) - 2);
		a := 3; b := -2; ASSERT (a - b = +5); ASSERT (a - b = 3 - (-2));
		a := -3; b := -2; ASSERT (a - b = -1); ASSERT (a - b = (-3) - (-2));
		a := MIN (INTEGER) + 1; b := MAX (INTEGER); ASSERT (a - b = 2); ASSERT (a - b = SHORT (LONGINT(MIN (INTEGER) + 1 - MAX (INTEGER))));
	END Test.

positive: subtraction on long integers

	MODULE Test;
	VAR a, b: LONGINT;
	BEGIN
		a := 3; b := 2; ASSERT (a - b = +1); ASSERT (a - b = 3 - 2);
		a := -3; b := 2; ASSERT (a - b = -5); ASSERT (a - b = (-3) - 2);
		a := 3; b := -2; ASSERT (a - b = +5); ASSERT (a - b = 3 - (-2));
		a := -3; b := -2; ASSERT (a - b = -1); ASSERT (a - b = (-3) - (-2));
		a := MIN (LONGINT) + 1; b := MAX (LONGINT); ASSERT (a - b = 2);
		(* ASSERT (a - b = SHORT (MIN (LONGINT) + 1 - MAX (LONGINT))); *)
	END Test.

positive: subtraction on huge integers

	MODULE Test;
	VAR a, b: HUGEINT;
	BEGIN
		a := 3; b := 2; ASSERT (a - b = +1); ASSERT (a - b = 3 - 2);
		a := -3; b := 2; ASSERT (a - b = -5); ASSERT (a - b = (-3) - 2);
		a := 3; b := -2; ASSERT (a - b = +5); ASSERT (a - b = 3 - (-2));
		a := -3; b := -2; ASSERT (a - b = -1); ASSERT (a - b = (-3) - (-2));
		a := MIN (HUGEINT) + 1; b := MAX (HUGEINT); ASSERT (a - b = 2); ASSERT (a - b = MIN (HUGEINT) + 1 - MAX (HUGEINT));
	END Test.

positive: subtraction on reals

	MODULE Test;
	VAR a, b: REAL;
	BEGIN
		a := 3.5; b := 2.5; ASSERT (a - b = +1); ASSERT (a - b = 3.5 - 2.5);
		a := -3.5; b := 2.5; ASSERT (a - b = -6); ASSERT (a - b = (-3.5) - 2.5);
		a := 3.5; b := -2.5; ASSERT (a - b = +6); ASSERT (a - b = 3.5 - (-2.5));
		a := -3.5; b := -2.5; ASSERT (a - b = -1); ASSERT (a - b = (-3.5) - (-2.5));
	END Test.

positive: subtraction on long reals

	MODULE Test;
	VAR a, b: LONGREAL;
	BEGIN
		a := 3.5; b := 2.5; ASSERT (a - b = +1); ASSERT (a - b = 3.5 - 2.5);
		a := -3.5; b := 2.5; ASSERT (a - b = -6); ASSERT (a - b = (-3.5) - 2.5);
		a := 3.5; b := -2.5; ASSERT (a - b = +6); ASSERT (a - b = 3.5 - (-2.5));
		a := -3.5; b := -2.5; ASSERT (a - b = -1); ASSERT (a - b = (-3.5) - (-2.5));
	END Test.

positive: multiplication on short integers

	MODULE Test;
	VAR a, b: SHORTINT;
	BEGIN
		a := 3; b := 2; ASSERT (a * b = +6); ASSERT (a * b = 3 * 2);
		a := -3; b := 2; ASSERT (a * b = -6); ASSERT (a * b = (-3) * 2);
		a := 3; b := -2; ASSERT (a * b = -6); ASSERT (a * b = 3 * (-2));
		a := -3; b := -2; ASSERT (a * b = +6); ASSERT (a * b = (-3) * (-2));
		a := MAX (SHORTINT); b := MAX (SHORTINT); ASSERT (a * b = 1); ASSERT (a * b = SHORT (INTEGER(MAX (SHORTINT) * MAX (SHORTINT))));
	END Test.

positive: multiplication on integers

	MODULE Test;
	VAR a, b: INTEGER;
	BEGIN
		a := 3; b := 2; ASSERT (a * b = +6); ASSERT (a * b = 3 * 2);
		a := -3; b := 2; ASSERT (a * b = -6); ASSERT (a * b = (-3) * 2);
		a := 3; b := -2; ASSERT (a * b = -6); ASSERT (a * b = 3 * (-2));
		a := -3; b := -2; ASSERT (a * b = +6); ASSERT (a * b = (-3) * (-2));
		a := MAX (INTEGER); b := MAX (INTEGER); ASSERT (a * b = 1); ASSERT (a * b = SHORT (LONGINT(MAX (INTEGER) * MAX (INTEGER))));
	END Test.

positive: multiplication on long integers

	MODULE Test;
	VAR a, b: LONGINT;
	BEGIN
		a := 3; b := 2; ASSERT (a * b = +6); ASSERT (a * b = 3 * 2);
		a := -3; b := 2; ASSERT (a * b = -6); ASSERT (a * b = (-3) * 2);
		a := 3; b := -2; ASSERT (a * b = -6); ASSERT (a * b = 3 * (-2));
		a := -3; b := -2; ASSERT (a * b = +6); ASSERT (a * b = (-3) * (-2));
		a := MAX (LONGINT); b := MAX (LONGINT); ASSERT (a * b = 1);
		(*ASSERT (a * b = SHORT (HUGEINT(MAX (LONGINT) * MAX (LONGINT))));*)
	END Test.

positive: multiplication on huge integers

	MODULE Test;
	VAR a, b: HUGEINT;
	BEGIN
		a := 3; b := 2; ASSERT (a * b = +6); ASSERT (a * b = 3 * 2);
		a := -3; b := 2; ASSERT (a * b = -6); ASSERT (a * b = (-3) * 2);
		a := 3; b := -2; ASSERT (a * b = -6); ASSERT (a * b = 3 * (-2));
		a := -3; b := -2; ASSERT (a * b = +6); ASSERT (a * b = (-3) * (-2));
		a := MAX (HUGEINT); b := MAX (HUGEINT); ASSERT (a * b = 1); ASSERT (a * b = MAX (HUGEINT) * MAX (HUGEINT));
	END Test.

positive: multiplication on reals

	MODULE Test;
	VAR a, b: REAL;
	BEGIN
		a := 3.5; b := 2.5; ASSERT (a * b = +8.75); ASSERT (a * b = 3.5 * 2.5);
		a := -3.5; b := 2.5; ASSERT (a * b = -8.75); ASSERT (a * b = (-3.5) * 2.5);
		a := 3.5; b := -2.5; ASSERT (a * b = -8.75); ASSERT (a * b = 3.5 * (-2.5));
		a := -3.5; b := -2.5; ASSERT (a * b = +8.75); ASSERT (a * b = (-3.5) * (-2.5));
	END Test.

positive: multiplication on long reals

	MODULE Test;
	VAR a, b: LONGREAL;
	BEGIN
		a := 3.5; b := 2.5; ASSERT (a * b = +8.75); ASSERT (a * b = 3.5 * 2.5);
		a := -3.5; b := 2.5; ASSERT (a * b = -8.75); ASSERT (a * b = (-3.5) * 2.5);
		a := 3.5; b := -2.5; ASSERT (a * b = -8.75); ASSERT (a * b = 3.5 * (-2.5));
		a := -3.5; b := -2.5; ASSERT (a * b = +8.75); ASSERT (a * b = (-3.5) * (-2.5));
	END Test.

positive: integer division on short integers with positive divisor

	MODULE Test;
	VAR a, b: SHORTINT;
	BEGIN
		a := 3; b := 2; ASSERT (a DIV b = +1); ASSERT (a DIV b = 3 DIV 2);
		a := -3; b := 2; ASSERT (a DIV b = -2); ASSERT (a DIV b = (-3) DIV 2);
		a := 2; b := 3; ASSERT (a DIV b = +0); ASSERT (a DIV b = 2 DIV 3);
		a := -2; b := 3; ASSERT (a DIV b = -1); ASSERT (a DIV b = (-2) DIV 3);
		a := MAX (SHORTINT); b := MAX (SHORTINT); ASSERT (a DIV b = 1); ASSERT (a DIV b = MAX (SHORTINT) DIV MAX (SHORTINT));
	END Test.

negative: integer division on short integers with negative divisor

	MODULE Test;
	VAR a, b, c: SHORTINT;
	BEGIN
		a := 3; b := -2; c := a DIV b;
	END Test.

negative: integer division by zero on short integer

	MODULE Test;
	VAR a, b, r: SHORTINT;
	BEGIN a := 3; b := 0; r := a DIV b;
	END Test.

positive: integer division on integers with positive divisor

	MODULE Test;
	VAR a, b: INTEGER;
	BEGIN
		a := 3; b := 2; ASSERT (a DIV b = +1); ASSERT (a DIV b = 3 DIV 2);
		a := -3; b := 2; ASSERT (a DIV b = -2); ASSERT (a DIV b = (-3) DIV 2);
		a := 2; b := 3; ASSERT (a DIV b = +0); ASSERT (a DIV b = 2 DIV 3);
		a := -2; b := 3; ASSERT (a DIV b = -1); ASSERT (a DIV b = (-2) DIV 3);
		a := MAX (INTEGER); b := MAX (INTEGER); ASSERT (a DIV b = 1); ASSERT (a DIV b = MAX (INTEGER) DIV MAX (INTEGER));
	END Test.

negative: integer division on integers with negative divisor

	MODULE Test;
	VAR a, b, c: INTEGER;
	BEGIN
		a := 3; b := -2; c := a DIV b;
	END Test.


negative: integer division by zero on integer

	MODULE Test;
	VAR a, b, r: INTEGER;
	BEGIN a := 3; b := 0; r := a DIV b;
	END Test.

positive: integer division on long integers with positive divisor

	MODULE Test;
	VAR a, b: LONGINT;
	BEGIN
		a := 3; b := 2; ASSERT (a DIV b = +1); ASSERT (a DIV b = 3 DIV 2);
		a := -3; b := 2; ASSERT (a DIV b = -2); ASSERT (a DIV b = (-3) DIV 2);
		a := 2; b := 3; ASSERT (a DIV b = +0); ASSERT (a DIV b = 2 DIV 3);
		a := -2; b := 3; ASSERT (a DIV b = -1); ASSERT (a DIV b = (-2) DIV 3);
		a := MAX (LONGINT); b := MAX (LONGINT); ASSERT (a DIV b = 1); ASSERT (a DIV b = MAX (LONGINT) DIV MAX (LONGINT));
	END Test.

negative: integer division on long integers with negative divisor

	MODULE Test;
	VAR a, b, c: LONGINT;
	BEGIN
		a := 3; b := -2; c := a DIV b;
	END Test.

negative: integer division by zero on long integer

	MODULE Test;
	VAR a, b, r: LONGINT;
	BEGIN a := 3; b := 0; r := a DIV b;
	END Test.

positive: integer division on huge integers with positive divisor

	MODULE Test;
	VAR a, b: HUGEINT;
	BEGIN
		a := 3; b := 2; ASSERT (a DIV b = +1); ASSERT (a DIV b = 3 DIV 2);
		a := -3; b := 2; ASSERT (a DIV b = -2); ASSERT (a DIV b = (-3) DIV 2);
		a := 2; b := 3; ASSERT (a DIV b = +0); ASSERT (a DIV b = 2 DIV 3);
		a := -2; b := 3; ASSERT (a DIV b = -1); ASSERT (a DIV b = (-2) DIV 3);
		a := MAX (HUGEINT); b := MAX (HUGEINT); ASSERT (a DIV b = 1); ASSERT (a DIV b = MAX (HUGEINT) DIV MAX (HUGEINT));
	END Test.

negative: integer division on huge integers with negative divisor

	MODULE Test;
	VAR a, b, c: HUGEINT;
	BEGIN
		a := 3; b := -2; c := a DIV b;
	END Test.

negative: integer division by zero on huge integer

	MODULE Test;
	VAR a, b, r: HUGEINT;
	BEGIN a := 3; b := 0; r := a DIV b;
	END Test.

positive: real division on short integers

	MODULE Test;
	VAR a, b: SHORTINT;
	BEGIN a := 3; b := 2; ASSERT (a / b = 1.5); ASSERT (a / b = 3 / 2);
	END Test.

positive: real division on integers

	MODULE Test;
	VAR a, b: INTEGER;
	BEGIN a := 3; b := 2; ASSERT (a / b = 1.5); ASSERT (a / b = 3 / 2);
	END Test.

positive: real division on long integers

	MODULE Test;
	VAR a, b: LONGINT;
	BEGIN a := 3; b := 2; ASSERT (a / b = 1.5); ASSERT (a / b = 3 / 2);
	END Test.

positive: real division on huge integers

	MODULE Test;
	VAR a, b: HUGEINT;
	BEGIN a := 3; b := 2; ASSERT (a / b = 1.5); ASSERT (a / b = 3 / 2);
	END Test.

positive: real division on reals

	MODULE Test;
	VAR a, b: REAL;
	BEGIN a := 3; b := 2; ASSERT (a / b = 1.5); ASSERT (a / b = 3 / 2);
	END Test.

positive: real division on long reals

	MODULE Test;
	VAR a, b: LONGREAL;
	BEGIN a := 3; b := 2; ASSERT (a / b = 1.5); ASSERT (a / b = 3 / 2);
	END Test.

positive: modulo on short integers

	MODULE Test;
	VAR a, b: SHORTINT;
	BEGIN
		a := 3; b := 2; ASSERT (a MOD b = +1); ASSERT (3 MOD b = +1); ASSERT (a MOD 2 = +1); ASSERT (a MOD b = 3 MOD 2);
		a := -3; b := 2; ASSERT (a MOD b = +1); ASSERT ((-3) MOD b = +1); ASSERT (a MOD 2 = +1); ASSERT (a MOD b = (-3) MOD 2);
		a := 2; b := 3; ASSERT (a MOD b = +2); ASSERT (2 MOD b = +2); ASSERT (a MOD 3 = +2); ASSERT (a MOD b = 2 MOD 3);
		a := -2; b := 3; ASSERT (a MOD b = 1); ASSERT ((-2) MOD b = 1); ASSERT (a MOD 3 = 1); ASSERT (a MOD b = (-2) MOD 3);
		a := MAX (SHORTINT); b := MAX (SHORTINT); ASSERT (a MOD b = 0); ASSERT (a MOD b = MAX (SHORTINT) MOD MAX (SHORTINT));
	END Test.

negative: modulo by zero on short integer

	MODULE Test;
	VAR a, b, r: SHORTINT;
	BEGIN a := 3; b := 0; r := a MOD b;
	END Test.

positive: modulo on integers

	MODULE Test;
	VAR a, b: INTEGER;
	BEGIN
		a := 3; b := 2; ASSERT (a MOD b = +1); ASSERT (3 MOD b = +1); ASSERT (a MOD 2 = +1); ASSERT (a MOD b = 3 MOD 2);
		a := -3; b := 2; ASSERT (a MOD b = +1); ASSERT ((-3) MOD b = +1); ASSERT (a MOD 2 = +1); ASSERT (a MOD b = (-3) MOD 2);
		a := 2; b := 3; ASSERT (a MOD b = +2); ASSERT (2 MOD b = +2); ASSERT (a MOD 3 = +2); ASSERT (a MOD b = 2 MOD 3);
		a := -2; b := 3; ASSERT (a MOD b = 1); ASSERT ((-2) MOD b = 1); ASSERT (a MOD 3 = 1); ASSERT (a MOD b = (-2) MOD 3);
		a := MAX (INTEGER); b := MAX (INTEGER); ASSERT (a MOD b = 0); ASSERT (a MOD b = MAX (INTEGER) MOD MAX (INTEGER));
	END Test.

negative: modulo by zero on integer

	MODULE Test;
	VAR a, b, r: INTEGER;
	BEGIN a := 3; b := 0; r := a MOD b;
	END Test.


positive: modulo on long integers

	MODULE Test;
	VAR a, b: LONGINT;
	BEGIN
		a := 3; b := 2; ASSERT (a MOD b = +1); ASSERT (3 MOD b = +1); ASSERT (a MOD 2 = +1); ASSERT (a MOD b = 3 MOD 2);
		a := -3; b := 2; ASSERT (a MOD b = +1); ASSERT ((-3) MOD b = +1); ASSERT (a MOD 2 = +1); ASSERT (a MOD b = (-3) MOD 2);
		a := 2; b := 3; ASSERT (a MOD b = +2); ASSERT (2 MOD b = +2); ASSERT (a MOD 3 = +2); ASSERT (a MOD b = 2 MOD 3);
		a := -2; b := 3; ASSERT (a MOD b = 1); ASSERT ((-2) MOD b = 1); ASSERT (a MOD 3 = 1); ASSERT (a MOD b = (-2) MOD 3);
		a := MAX (LONGINT); b := MAX (LONGINT); ASSERT (a MOD b = 0); ASSERT (a MOD b = MAX (LONGINT) MOD MAX (LONGINT));
	END Test.

negative: modulo by zero on long integer

	MODULE Test;
	VAR a, b, r: LONGINT;
	BEGIN a := 3; b := 0; r := a MOD b;
	END Test.

positive: modulo on huge integers

	MODULE Test;
	VAR a, b: HUGEINT;
	BEGIN
		a := 3; b := 2; ASSERT (a MOD b = +1); ASSERT (3 MOD b = +1); ASSERT (a MOD 2 = +1); ASSERT (a MOD b = 3 MOD 2);
		a := -3; b := 2; ASSERT (a MOD b = +1); ASSERT ((-3) MOD b = +1); ASSERT (a MOD 2 = +1); ASSERT (a MOD b = (-3) MOD 2);
		a := 2; b := 3; ASSERT (a MOD b = +2); ASSERT (2 MOD b = +2); ASSERT (a MOD 3 = +2); ASSERT (a MOD b = 2 MOD 3);
		a := -2; b := 3; ASSERT (a MOD b = 1); ASSERT ((-2) MOD b = 1); ASSERT (a MOD 3 = 1); ASSERT (a MOD b = (-2) MOD 3);
		a := MAX (HUGEINT); b := MAX (HUGEINT); ASSERT (a MOD b = 0); ASSERT (a MOD b = MAX (HUGEINT) MOD MAX (HUGEINT));
	END Test.

negative: modulo by zero on huge integer

	MODULE Test;
	VAR a, b, r: HUGEINT;
	BEGIN a := 3; b := 0; r := a MOD b;
	END Test.

positive: arithmetic shift on short integer

	MODULE Test;
	VAR a, b: SHORTINT;
	BEGIN
		a := 6; b := 2; ASSERT (ASH (a, b) = 24); ASSERT (ASH (a, b) = ASH (a, 2)); ASSERT (ASH (a, b) = ASH (6, 2));
		a := 6; b := 0; ASSERT (ASH (a, b) = 6); ASSERT (ASH (a, b) = ASH (a, 0)); ASSERT (ASH (a, b) = ASH (6, 0));
		a := 6; b := -2; ASSERT (ASH (a, b) = 1); ASSERT (ASH (a, b) = ASH (a, -2)); ASSERT (ASH (a, b) = ASH (6, -2));
	END Test.

positive: arithmetic shift on integer

	MODULE Test;
	VAR a, b: INTEGER;
	BEGIN
		a := 6; b := 2; ASSERT (ASH (a, b) = 24); ASSERT (ASH (a, b) = ASH (a, 2)); ASSERT (ASH (a, b) = ASH (6, 2));
		a := 6; b := 0; ASSERT (ASH (a, b) = 6); ASSERT (ASH (a, b) = ASH (a, 0)); ASSERT (ASH (a, b) = ASH (6, 0));
		a := 6; b := -2; ASSERT (ASH (a, b) = 1); ASSERT (ASH (a, b) = ASH (a, -2)); ASSERT (ASH (a, b) = ASH (6, -2));
	END Test.

positive: arithmetic shift on long integer

	MODULE Test;
	VAR a, b: LONGINT;
	BEGIN
		a := 6; b := 2; ASSERT (ASH (a, b) = 24); ASSERT (ASH (a, b) = ASH (a, 2)); ASSERT (ASH (a, b) = ASH (6, 2));
		a := 6; b := 0; ASSERT (ASH (a, b) = 6); ASSERT (ASH (a, b) = ASH (a, 0)); ASSERT (ASH (a, b) = ASH (6, 0));
		a := 6; b := -2; ASSERT (ASH (a, b) = 1); ASSERT (ASH (a, b) = ASH (a, -2)); ASSERT (ASH (a, b) = ASH (6, -2));
	END Test.

positive: arithmetic shift on huge integer

	MODULE Test;
	VAR a, b: HUGEINT;
	BEGIN
		a := 6; b := 2; ASSERT (ASH (a, b) = 24); ASSERT (ASH (a, b) = ASH (a, 2)); ASSERT (ASH (a, b) = ASH (6, 2));
		a := 6; b := 0; ASSERT (ASH (a, b) = 6); ASSERT (ASH (a, b) = ASH (a, 0)); ASSERT (ASH (a, b) = ASH (6, 0));
		a := 6; b := -2; ASSERT (ASH (a, b) = 1); ASSERT (ASH (a, b) = ASH (a, -2)); ASSERT (ASH (a, b) = ASH (6, -2));
	END Test.


# set operators

positive: set union

	MODULE Test;
	VAR a, b: SET;
	BEGIN
		a := {}; b := {}; ASSERT (a + b = {}); ASSERT (a + b = {} + {});
		a := {1, 2}; b := {}; ASSERT (a + b = {1, 2}); ASSERT (a + b = {1, 2} + {});
		a := {}; b := {2, 3}; ASSERT (a + b = {2, 3}); ASSERT (a + b = {} + {2, 3});
		a := {1, 2}; b := {2, 3}; ASSERT (a + b = {1..3}); ASSERT (a + b = {1, 2} + {2, 3});
		a := {}; b := {}; ASSERT (a + {} = {}); ASSERT ({} + b = {} + {});
		a := {1, 2}; b := {}; ASSERT (a + {} = {1, 2}); ASSERT ({1,2} + b = {1, 2} + {});
		a := {}; b := {2, 3}; ASSERT (a + {2,3} = {2, 3}); ASSERT ({} + b = {} + {2, 3});
		a := {1, 2}; b := {2, 3}; ASSERT (a + {2,3} = {1..3}); ASSERT ({1,2} + b = {1, 2} + {2, 3});

	END Test.

positive: set difference

	MODULE Test;
	VAR a, b: SET;
	BEGIN
		a := {}; b := {}; ASSERT (a - b = {}); ASSERT (a - b = {} - {});
		a := {1, 2}; b := {}; ASSERT (a - b = {1, 2}); ASSERT (a - b = {1, 2} - {});
		a := {}; b := {2, 3}; ASSERT (a - b = {}); ASSERT (a - b = {} - {2, 3});
		a := {1, 2}; b := {2, 3}; ASSERT (a - b = {1}); ASSERT (a - b = {1, 2} - {2, 3});
		a := {}; b := {}; ASSERT (a - {} = {}); ASSERT ({} - b = {} - {});
		a := {1, 2}; b := {}; ASSERT (a - {} = {1, 2}); ASSERT ({1,2} - b = {1, 2} - {});
		a := {}; b := {2, 3}; ASSERT (a - {2,3} = {}); ASSERT ({} - b = {} - {2, 3});
		a := {1, 2}; b := {2, 3}; ASSERT (a - {2,3} = {1}); ASSERT ({1,2} - b = {1, 2} - {2, 3});
	END Test.

positive: set intersection

	MODULE Test;
	VAR a, b: SET;
	BEGIN
		a := {}; b := {}; ASSERT (a * b = {}); ASSERT (a * b = {} * {});
		a := {1, 2}; b := {}; ASSERT (a * b = {}); ASSERT (a * b = {1, 2} * {});
		a := {}; b := {2, 3}; ASSERT (a * b = {}); ASSERT (a * b = {} * {2, 3});
		a := {1, 2}; b := {2, 3}; ASSERT (a * b = {2}); ASSERT (a * b = {1, 2} * {2, 3});
		a := {}; b := {}; ASSERT ({} * b = {}); ASSERT (a * {} = {} * {});
		a := {1, 2}; b := {}; ASSERT ({1,2} * b = {}); ASSERT (a * {} = {1, 2} * {});
		a := {}; b := {2, 3}; ASSERT (a * {2,3} = {}); ASSERT ({} * b = {} * {2, 3});
		a := {1, 2}; b := {2, 3}; ASSERT ({1,2} * b = {2}); ASSERT (a * {2,3} = {1, 2} * {2, 3});
	END Test.

positive: symmetric set difference

	MODULE Test;
	VAR a, b: SET;
	BEGIN
		a := {}; b := {}; ASSERT (a / b = {}); ASSERT (a / b = {} / {});
		a := {1, 2}; b := {}; ASSERT (a / b = {1, 2}); ASSERT (a / b = {1, 2} / {});
		a := {}; b := {2, 3}; ASSERT (a / b = {2, 3}); ASSERT (a / b = {} / {2, 3});
		a := {1, 2}; b := {2, 3}; ASSERT (a / b = {1, 3}); ASSERT (a / b = {1, 2} / {2, 3});
		a := {}; b := {}; ASSERT (a / {} = {}); ASSERT (a / {} = {} / {});
		a := {1, 2}; b := {}; ASSERT ({1,2} / b = {1, 2}); ASSERT (a / {} = {1, 2} / {});
		a := {}; b := {2, 3}; ASSERT ({} / b = {2, 3}); ASSERT (a / {2,3} = {} / {2, 3});
		a := {1, 2}; b := {2, 3}; ASSERT ({1,2} / b = {1, 3}); ASSERT (a / {2,3} = {1, 2} / {2, 3});
	END Test.


# type guards

positive: type guard on same global record

	MODULE Test;
	TYPE R = RECORD b: BOOLEAN END;
	VAR r: R;
	BEGIN r.b := TRUE; ASSERT (r(R).b);
	END Test.

positive: type guard on same local record

	MODULE Test;
	PROCEDURE Procedure;
	TYPE R = RECORD b: BOOLEAN END;
	VAR r: R;
	BEGIN r.b := TRUE; ASSERT (r(R).b);
	END Procedure;
	BEGIN Procedure;
	END Test.

positive: type guard on same parameter record

	MODULE Test;
	TYPE R = RECORD b: BOOLEAN END;
	VAR r: R;
	PROCEDURE Procedure (r: R); BEGIN ASSERT (r(R).b); END Procedure;
	BEGIN r.b := TRUE; Procedure (r);
	END Test.

positive: type guard on same variable parameter record

	MODULE Test;
	TYPE R = RECORD b: BOOLEAN END;
	VAR r: R;
	PROCEDURE Procedure (VAR r: R); BEGIN ASSERT (r(R).b); END Procedure;
	BEGIN r.b := TRUE; Procedure (r);
	END Test.

positive: type guard on same constant parameter record

	MODULE Test;
	TYPE R = RECORD b: BOOLEAN END;
	VAR r: R;
	PROCEDURE Procedure (CONST r: R); BEGIN ASSERT (r(R).b); END Procedure;
	BEGIN r.b := TRUE; Procedure (r);
	END Test.

positive: type guard on variable parameter record

	MODULE Test;
	TYPE R0 = RECORD END; R1 = RECORD (R0) b: BOOLEAN END;
	VAR r: R1;
	PROCEDURE Procedure (VAR r: R0); BEGIN ASSERT (r(R1).b); END Procedure;
	BEGIN r.b := TRUE; Procedure (r);
	END Test.

negative: unsatisfied type guard on variable parameter record

	MODULE Test;
	TYPE R0 = RECORD END; R1 = RECORD (R0) b: BOOLEAN END;
	VAR r: R0;
	PROCEDURE Procedure (VAR r: R0); BEGIN ASSERT (r(R1).b); END Procedure;
	BEGIN Procedure (r);
	END Test.

positive: type guard on constant parameter record

	MODULE Test;
	TYPE R0 = RECORD END; R1 = RECORD (R0) b: BOOLEAN END;
	VAR r: R1;
	PROCEDURE Procedure (CONST r: R0); BEGIN ASSERT (r(R1).b); END Procedure;
	BEGIN r.b := TRUE; Procedure (r);
	END Test.

negative: unsatisfied type guard on constant parameter record

	MODULE Test;
	TYPE R0 = RECORD END; R1 = RECORD (R0) b: BOOLEAN END;
	VAR r: R0;
	PROCEDURE Procedure (CONST r: R0); BEGIN ASSERT (r(R1).b); END Procedure;
	BEGIN Procedure (r);
	END Test.

positive: type guard on same pointer to record

	MODULE Test;
	TYPE R = RECORD b: BOOLEAN END; P = POINTER TO R;
	VAR p: P;
	BEGIN NEW (p); p.b := TRUE; ASSERT (p(P).b); ASSERT (p^(R).b);
	END Test.

positive: type guard on pointer to record

	MODULE Test;
	TYPE R0 = RECORD END; P0 = POINTER TO R0
	TYPE R1 = RECORD (R0) b: BOOLEAN END; P1 = POINTER TO R1;
	VAR p0: P0; p1: P1;
	BEGIN NEW (p1); p1.b := TRUE; p0 := p1; ASSERT (p0(P1).b); ASSERT (p0^(R1).b);
	END Test.

negative: unsatisfied type guard on pointer to record

	MODULE Test;
	TYPE R0 = RECORD END; P0 = POINTER TO R0;
	TYPE R1 = RECORD (R0) END; P1 = POINTER TO R1;
	VAR p0: P0; p1: P1;
	BEGIN NEW (p0); p1 := p0(P1);
	END Test.

negative: type guard on nil pointer to record

	MODULE Test;
	TYPE R0 = RECORD END; P0 = POINTER TO R0;
	TYPE R1 = RECORD (R0) END; P1 = POINTER TO R1;
	VAR p0: P0; p1: P1;
	BEGIN p0 := NIL; p1 := p0(P1);
	END Test.

positive: type guard on same object

	MODULE Test;
	TYPE O = OBJECT VAR b: BOOLEAN END O;
	VAR o: O;
	BEGIN NEW (o); o.b := TRUE; ASSERT (o(O).b);
	END Test.

positive: type guard on object

	MODULE Test;
	TYPE O0 = OBJECT END O0;
	TYPE O1 = OBJECT (O0) VAR b: BOOLEAN END O1;
	VAR o0: O0; o1: O1;
	BEGIN NEW (o1); o1.b := TRUE; o0 := o1; ASSERT (o0(O1).b);
	END Test.

negative: unsatisfied type guard on object

	MODULE Test;
	TYPE O0 = OBJECT END O0;
	TYPE O1 = OBJECT (O0) END O1;
	VAR o0: O0; o1: O1;
	BEGIN NEW (o0); o1 := o0(O1);
	END Test.

negative: type guard on nil object

	MODULE Test;
	TYPE O0 = OBJECT END O0;
	TYPE O1 = OBJECT (O0) END O1;
	VAR o0: O0; o1: O1;
	BEGIN o0 := NIL; o1 := o0(O1);
	END Test.

positive: type guard on base object

	MODULE Test;
	TYPE O0 = OBJECT;
	TYPE O1 = OBJECT (O0) VAR b: BOOLEAN END O1;
	VAR o0: O0; o1: O1;
	BEGIN NEW (o1); o1.b := TRUE; o0 := o1; ASSERT (o0(O1).b);
	END Test.

negative: type guard on nil base object

	MODULE Test;
	TYPE O0 = OBJECT;
	TYPE O1 = OBJECT (O0) END O1;
	VAR o0: O0; o1: O1;
	BEGIN o0 := NIL; o1 := o0(O1);
	END Test.


# type tests

positive: type test on same global record

	MODULE Test;
	TYPE R = RECORD END;
	VAR r: R;
	BEGIN ASSERT (r IS R);
	END Test.

positive: type test on same local record

	MODULE Test;
	PROCEDURE Procedure;
	TYPE R = RECORD END;
	VAR r: R;
	BEGIN ASSERT (r IS R);
	END Procedure;
	BEGIN Procedure;
	END Test.

positive: type test on same parameter record

	MODULE Test;
	TYPE R = RECORD END;
	VAR r: R;
	PROCEDURE Procedure (r: R); BEGIN ASSERT (r IS R); END Procedure;
	BEGIN Procedure (r);
	END Test.

positive: type test on same variable parameter record

	MODULE Test;
	TYPE R = RECORD END;
	VAR r: R;
	PROCEDURE Procedure (VAR r: R); BEGIN ASSERT (r IS R); END Procedure;
	BEGIN Procedure (r);
	END Test.

positive: type test on same constant parameter record

	MODULE Test;
	TYPE R = RECORD END;
	VAR r: R;
	PROCEDURE Procedure (CONST r: R); BEGIN ASSERT (r IS R); END Procedure;
	BEGIN Procedure (r);
	END Test.

positive: type test on variable parameter record

	MODULE Test;
	TYPE R0 = RECORD END; R1 = RECORD (R0) END;
	VAR r: R1;
	PROCEDURE Procedure (VAR r: R0); BEGIN ASSERT (r IS R1); END Procedure;
	BEGIN Procedure (r);
	END Test.

positive: unsatisfied type test on variable parameter record

	MODULE Test;
	TYPE R0 = RECORD END; R1 = RECORD (R0) END;
	VAR r: R0;
	PROCEDURE Procedure (VAR r: R0); BEGIN ASSERT (~(r IS R1)); END Procedure;
	BEGIN Procedure (r);
	END Test.

positive: type test on constant parameter record

	MODULE Test;
	TYPE R0 = RECORD END; R1 = RECORD (R0) END;
	VAR r: R1;
	PROCEDURE Procedure (CONST r: R0); BEGIN ASSERT (r IS R1); END Procedure;
	BEGIN Procedure (r);
	END Test.

positive: unsatisfied type test on constant parameter record

	MODULE Test;
	TYPE R0 = RECORD END; R1 = RECORD (R0) END;
	VAR r: R0;
	PROCEDURE Procedure (CONST r: R0); BEGIN ASSERT (~(r IS R1)); END Procedure;
	BEGIN Procedure (r);
	END Test.

positive: type test on same pointer to record

	MODULE Test;
	TYPE R = RECORD END; P = POINTER TO R;
	VAR p: P;
	BEGIN NEW (p); ASSERT (p IS P); ASSERT (p^ IS R);
	END Test.

positive: type test on pointer to record

	MODULE Test;
	TYPE R0 = RECORD END; P0 = POINTER TO R0
	TYPE R1 = RECORD (R0) END; P1 = POINTER TO R1;
	VAR p0: P0; p1: P1;
	BEGIN NEW (p1); p0 := p1; ASSERT (p0 IS P1); ASSERT (p0^ IS R1);
	END Test.

positive: unsatisfied type test on pointer to record

	MODULE Test;
	TYPE R0 = RECORD END; P0 = POINTER TO R0
	TYPE R1 = RECORD (R0) END; P1 = POINTER TO R1;
	VAR p0: P0;
	BEGIN NEW (p0); ASSERT (~(p0 IS P1)); ASSERT (~(p0^ IS R1));
	END Test.

negative: type test on nil pointer to record

	MODULE Test;
	TYPE R0 = RECORD END; P0 = POINTER TO R0;
	TYPE R1 = RECORD (R0) END; P1 = POINTER TO R1;
	VAR p0: P0;
	BEGIN p0 := NIL; ASSERT (~(p0 IS P1));
	END Test.

positive: type test on same object

	MODULE Test;
	TYPE O = OBJECT END O;
	VAR o: O;
	BEGIN NEW (o); ASSERT (o IS O);
	END Test.

positive: type test on object

	MODULE Test;
	TYPE O0 = OBJECT END O0;
	TYPE O1 = OBJECT (O0) END O1;
	VAR o0: O0; o1: O1;
	BEGIN NEW (o1); o0 := o1; ASSERT (o0 IS O1);
	END Test.

positive: unsatisfied type test on object

	MODULE Test;
	TYPE O0 = OBJECT END O0;
	TYPE O1 = OBJECT (O0) END O1;
	VAR o0: O0;
	BEGIN NEW (o0); ASSERT (~(o0 IS O1));
	END Test.

negative: type test on nil object

	MODULE Test;
	TYPE O0 = OBJECT END O0;
	TYPE O1 = OBJECT (O0) END O1;
	VAR o0: O0;
	BEGIN o0 := NIL; ASSERT (~(o0 IS O1));
	END Test.

positive: type test on base object

	MODULE Test;
	TYPE O0 = OBJECT;
	TYPE O1 = OBJECT (O0) END O1;
	VAR o0: O0; o1: O1;
	BEGIN NEW (o1); o0 := o1; ASSERT (o0 IS O1);
	END Test.

negative: type test on nil base object

	MODULE Test;
	TYPE O0 = OBJECT;
	TYPE O1 = OBJECT (O0) END O1;
	VAR o0: O0;
	BEGIN o0 := NIL; ASSERT (~(o0 IS O1));
	END Test.


# dereferencing

positive: explicit dereference on pointer to record

	MODULE Test;
	VAR p: POINTER TO RECORD a: INTEGER END;
	BEGIN NEW (p); p^.a := 45; ASSERT (p.a = 45);
	END Test.

negative: explicit dereference of nil pointer to record

	MODULE Test;
	VAR p: POINTER TO RECORD a: INTEGER END;
	BEGIN p := NIL; p^.a := 45;
	END Test.

positive: implicit dereference on pointer to record

	MODULE Test;
	VAR p: POINTER TO RECORD a: INTEGER END;
	BEGIN NEW (p); p.a := 45; ASSERT (p^.a = 45);
	END Test.

negative: implicit dereference of nil pointer to record

	MODULE Test;
	VAR p: POINTER TO RECORD a: INTEGER END;
	BEGIN p := NIL; p.a := 45;
	END Test.

positive: explicit dereference on pointer to array

	MODULE Test;
	VAR p: POINTER TO ARRAY 10 OF INTEGER;
	BEGIN NEW (p); p^[4] := 45; ASSERT (p[4] = 45);
	END Test.

positive: implicit dereference on pointer to array

	MODULE Test;
	VAR p: POINTER TO ARRAY 10 OF INTEGER;
	BEGIN NEW (p); p[4] := 45; ASSERT (p^[4] = 45);
	END Test.

negative: explicit dereference of nil pointer to array

	MODULE Test;
	VAR p: POINTER TO ARRAY 10 OF INTEGER;
	BEGIN p := NIL; p^[4] := 45;
	END Test.

negative: implicit dereference of nil pointer to array

	MODULE Test;
	VAR p: POINTER TO ARRAY 10 OF INTEGER;
	BEGIN p := NIL; p[4] := 45;
	END Test.


# array length

positive: length of one-dimensional open array

	MODULE Test;
	VAR a: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF INTEGER; len: INTEGER);
	BEGIN ASSERT (LEN (p) = len);
	END Procedure;
	BEGIN Procedure (a, 10); Procedure (a, LEN (a));
	END Test.

positive: first dimension of one-dimensional open array

	MODULE Test;
	VAR a: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF INTEGER; len: INTEGER);
	BEGIN ASSERT (LEN (p, 0) = len);
	END Procedure;
	BEGIN Procedure (a, 10); Procedure (a, LEN (a, 0));
	END Test.

positive: dynamic dimension of one-dimensional open array

	MODULE Test;
	VAR a: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF INTEGER; dim, len: INTEGER);
	BEGIN ASSERT (LEN (p, dim) = len);
	END Procedure;
	BEGIN Procedure (a, 0, 10); Procedure (a, 0, LEN (a, 0));
	END Test.

negative: negative dynamic dimension of one-dimensional open array

	MODULE Test;
	VAR a: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF INTEGER; dim: INTEGER);
	VAR len: LONGINT;
	BEGIN len := LEN (p, dim);
	END Procedure;
	BEGIN Procedure (a, -1);
	END Test.

negative: invalid dynamic dimension of one-dimensional open array

	MODULE Test;
	VAR a: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF INTEGER; dim: INTEGER);
	VAR len: LONGINT;
	BEGIN len := LEN (p, dim);
	END Procedure;
	BEGIN Procedure (a, 1);
	END Test.

positive: length of two-dimensional open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF ARRAY OF INTEGER; len: INTEGER);
	BEGIN ASSERT (LEN (p) = len);
	END Procedure;
	BEGIN Procedure (a, 10); Procedure (a, LEN (a));
	END Test.

positive: first dimension of two-dimensional open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF ARRAY OF INTEGER; len: INTEGER);
	BEGIN ASSERT (LEN (p, 0) = len);
	END Procedure;
	BEGIN Procedure (a, 10); Procedure (a, LEN (a, 0));
	END Test.

positive: second dimension of two-dimensional open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF ARRAY OF INTEGER; len: INTEGER);
	BEGIN ASSERT (LEN (p, 1) = len);
	END Procedure;
	BEGIN Procedure (a, 20); Procedure (a, LEN (a, 1));
	END Test.

positive: dynamic dimension of two-dimensional open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF ARRAY OF INTEGER; dim, len: INTEGER);
	BEGIN ASSERT (LEN (p, dim) = len);
	END Procedure;
	BEGIN Procedure (a, 0, 10); Procedure (a, 0, LEN (a, 0)); Procedure (a, 1, 20); Procedure (a, 1, LEN (a, 1));
	END Test.

negative: negative dynamic dimension of two-dimensional open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF ARRAY OF INTEGER; dim: INTEGER);
	VAR len: LONGINT;
	BEGIN len := LEN (p, dim);
	END Procedure;
	BEGIN Procedure (a, -1);
	END Test.

negative: invalid dynamic dimension of two-dimensional open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF ARRAY OF INTEGER; dim: INTEGER);
	VAR len: LONGINT;
	BEGIN len := LEN (p, dim);
	END Procedure;
	BEGIN Procedure (a, 2);
	END Test.

positive: length of one-dimensional variable open array

	MODULE Test;
	VAR a: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF INTEGER; len: INTEGER);
	BEGIN ASSERT (LEN (p) = len);
	END Procedure;
	BEGIN Procedure (a, 10); Procedure (a, LEN (a));
	END Test.

positive: first dimension of one-dimensional variable open array

	MODULE Test;
	VAR a: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF INTEGER; len: INTEGER);
	BEGIN ASSERT (LEN (p, 0) = len);
	END Procedure;
	BEGIN Procedure (a, 10); Procedure (a, LEN (a, 0));
	END Test.

positive: dynamic dimension of one-dimensional variable open array

	MODULE Test;
	VAR a: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF INTEGER; dim, len: INTEGER);
	BEGIN ASSERT (LEN (p, dim) = len);
	END Procedure;
	BEGIN Procedure (a, 0, 10); Procedure (a, 0, LEN (a, 0));
	END Test.

negative: negative dynamic dimension of one-dimensional variable open array

	MODULE Test;
	VAR a: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF INTEGER; dim: INTEGER);
	VAR len: LONGINT;
	BEGIN len := LEN (p, dim);
	END Procedure;
	BEGIN Procedure (a, -1);
	END Test.

negative: invalid dynamic dimension of one-dimensional variable open array

	MODULE Test;
	VAR a: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF INTEGER; dim: INTEGER);
	VAR len: LONGINT;
	BEGIN len := LEN (p, dim);
	END Procedure;
	BEGIN Procedure (a, 1);
	END Test.

positive: length of two-dimensional variable open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF ARRAY OF INTEGER; len: INTEGER);
	BEGIN ASSERT (LEN (p) = len);
	END Procedure;
	BEGIN Procedure (a, 10); Procedure (a, LEN (a));
	END Test.

positive: first dimension of two-dimensional variable open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF ARRAY OF INTEGER; len: INTEGER);
	BEGIN ASSERT (LEN (p, 0) = len);
	END Procedure;
	BEGIN Procedure (a, 10); Procedure (a, LEN (a, 0));
	END Test.

positive: second dimension of two-dimensional variable open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF ARRAY OF INTEGER; len: INTEGER);
	BEGIN ASSERT (LEN (p, 1) = len);
	END Procedure;
	BEGIN Procedure (a, 20); Procedure (a, LEN (a, 1));
	END Test.

positive: dynamic dimension of two-dimensional variable open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF ARRAY OF INTEGER; dim, len: INTEGER);
	BEGIN ASSERT (LEN (p, dim) = len);
	END Procedure;
	BEGIN Procedure (a, 0, 10); Procedure (a, 0, LEN (a, 0)); Procedure (a, 1, 20); Procedure (a, 1, LEN (a, 1));
	END Test.

negative: negative dynamic dimension of two-dimensional variable open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF ARRAY OF INTEGER; dim: INTEGER);
	VAR len: LONGINT;
	BEGIN len := LEN (p, dim);
	END Procedure;
	BEGIN Procedure (a, -1);
	END Test.

negative: invalid dynamic dimension of two-dimensional variable open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF ARRAY OF INTEGER; dim: INTEGER);
	VAR len: LONGINT;
	BEGIN len := LEN (p, dim);
	END Procedure;
	BEGIN Procedure (a, 2);
	END Test.

positive: length of one-dimensional constant open array

	MODULE Test;
	VAR a: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF INTEGER; len: INTEGER);
	BEGIN ASSERT (LEN (p) = len);
	END Procedure;
	BEGIN Procedure (a, 10); Procedure (a, LEN (a));
	END Test.

positive: first dimension of one-dimensional constant open array

	MODULE Test;
	VAR a: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF INTEGER; len: INTEGER);
	BEGIN ASSERT (LEN (p, 0) = len);
	END Procedure;
	BEGIN Procedure (a, 10); Procedure (a, LEN (a, 0));
	END Test.

positive: dynamic dimension of one-dimensional constant open array

	MODULE Test;
	VAR a: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF INTEGER; dim, len: INTEGER);
	BEGIN ASSERT (LEN (p, dim) = len);
	END Procedure;
	BEGIN Procedure (a, 0, 10); Procedure (a, 0, LEN (a, 0));
	END Test.

negative: negative dynamic dimension of one-dimensional constant open array

	MODULE Test;
	VAR a: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF INTEGER; dim: INTEGER);
	VAR len: LONGINT;
	BEGIN len := LEN (p, dim);
	END Procedure;
	BEGIN Procedure (a, -1);
	END Test.

negative: invalid dynamic dimension of one-dimensional constant open array

	MODULE Test;
	VAR a: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF INTEGER; dim: INTEGER);
	VAR len: LONGINT;
	BEGIN len := LEN (p, dim);
	END Procedure;
	BEGIN Procedure (a, 1);
	END Test.

positive: length of two-dimensional constant open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF ARRAY OF INTEGER; len: INTEGER);
	BEGIN ASSERT (LEN (p) = len);
	END Procedure;
	BEGIN Procedure (a, 10); Procedure (a, LEN (a));
	END Test.

positive: first dimension of two-dimensional constant open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF ARRAY OF INTEGER; len: INTEGER);
	BEGIN ASSERT (LEN (p, 0) = len);
	END Procedure;
	BEGIN Procedure (a, 10); Procedure (a, LEN (a, 0));
	END Test.

positive: second dimension of two-dimensional constant open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF ARRAY OF INTEGER; len: INTEGER);
	BEGIN ASSERT (LEN (p, 1) = len);
	END Procedure;
	BEGIN Procedure (a, 20); Procedure (a, LEN (a, 1));
	END Test.

positive: dynamic dimension of two-dimensional constant open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF ARRAY OF INTEGER; dim, len: INTEGER);
	BEGIN ASSERT (LEN (p, dim) = len);
	END Procedure;
	BEGIN Procedure (a, 0, 10); Procedure (a, 0, LEN (a, 0)); Procedure (a, 1, 20); Procedure (a, 1, LEN (a, 1));
	END Test.

negative: negative dynamic dimension of two-dimensional constant open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF ARRAY OF INTEGER; dim: INTEGER);
	VAR len: LONGINT;
	BEGIN len := LEN (p, dim);
	END Procedure;
	BEGIN Procedure (a, -1);
	END Test.

negative: invalid dynamic dimension of two-dimensional constant open array

	MODULE Test;
	VAR a: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF ARRAY OF INTEGER; dim: INTEGER);
	VAR len: LONGINT;
	BEGIN len := LEN (p, dim);
	END Procedure;
	BEGIN Procedure (a, 2);
	END Test.

positive: length of pointer to one-dimensional open array

	MODULE Test;
	VAR a: POINTER TO ARRAY OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF INTEGER; len: LONGINT);
	BEGIN ASSERT (LEN (p) = len);
	END Procedure;
	BEGIN NEW (a, 10); ASSERT (LEN (a) = 10); Procedure (a^, 10); Procedure (a^, LEN (a));
	END Test.

positive: first dimension of pointer to one-dimensional open array

	MODULE Test;
	VAR a: POINTER TO ARRAY OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF INTEGER; len: LONGINT);
	BEGIN ASSERT (LEN (p, 0) = len);
	END Procedure;
	BEGIN NEW (a, 10); ASSERT (LEN (a, 0) = 10); Procedure (a^, 10); Procedure (a^, LEN (a, 0));
	END Test.

positive: dynamic dimension of pointer to one-dimensional open array

	MODULE Test;
	VAR a: POINTER TO ARRAY OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF INTEGER; dim, len: LONGINT);
	BEGIN ASSERT (LEN (p, dim) = len);
	END Procedure;
	BEGIN NEW (a, 10); Procedure (a^, 0, 10); Procedure (a^, 0, LEN (a, 0));
	END Test.

negative: negative dynamic dimension of pointer to one-dimensional open array

	MODULE Test;
	VAR a: POINTER TO ARRAY OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF INTEGER; dim: INTEGER);
	VAR len: LONGINT;
	BEGIN len := LEN (p, dim);
	END Procedure;
	BEGIN NEW (a, 10); Procedure (a^, -1);
	END Test.

negative: invalid dynamic dimension of pointer to one-dimensional open array

	MODULE Test;
	VAR a: POINTER TO ARRAY OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF INTEGER; dim: INTEGER);
	VAR len: LONGINT;
	BEGIN len := LEN (p, dim);
	END Procedure;
	BEGIN NEW (a, 10); Procedure (a^, 1);
	END Test.

positive: length of pointer to two-dimensional open array

	MODULE Test;
	VAR a: POINTER TO ARRAY OF ARRAY OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF ARRAY OF INTEGER; len: LONGINT);
	BEGIN ASSERT (LEN (p) = len);
	END Procedure;
	BEGIN NEW (a, 10, 20); Procedure (a^, 10); Procedure (a^, LEN (a));
	END Test.

positive: first dimension of pointer to two-dimensional open array

	MODULE Test;
	VAR a: POINTER TO ARRAY OF ARRAY OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF ARRAY OF INTEGER; len: LONGINT);
	BEGIN ASSERT (LEN (p, 0) = len);
	END Procedure;
	BEGIN NEW (a, 10, 20); Procedure (a^, 10); Procedure (a^, LEN (a, 0));
	END Test.

positive: second dimension of pointer to two-dimensional open array

	MODULE Test;
	VAR a: POINTER TO ARRAY OF ARRAY OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF ARRAY OF INTEGER; len: LONGINT);
	BEGIN ASSERT (LEN (p, 1) = len);
	END Procedure;
	BEGIN NEW (a, 10, 20); Procedure (a^, 20); Procedure (a^, LEN (a, 1));
	END Test.

positive: dynamic dimension of pointer to two-dimensional open array

	MODULE Test;
	VAR a: POINTER TO ARRAY OF ARRAY OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF ARRAY OF INTEGER; dim, len: LONGINT);
	BEGIN ASSERT (LEN (p, dim) = len);
	END Procedure;
	BEGIN NEW (a, 10, 20); Procedure (a^, 0, 10); Procedure (a^, 0, LEN (a, 0)); Procedure (a^, 1, 20); Procedure (a^, 1, LEN (a, 1));
	END Test.

negative: negative dynamic dimension of pointer to two-dimensional open array

	MODULE Test;
	VAR a: POINTER TO ARRAY OF ARRAY OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF ARRAY OF INTEGER; dim: INTEGER);
	VAR len: LONGINT;
	BEGIN len := LEN (p, dim);
	END Procedure;
	BEGIN NEW (a, 10, 20); Procedure (a^, -1);
	END Test.

negative: invalid dynamic dimension of pointer to two-dimensional open array

	MODULE Test;
	VAR a: POINTER TO ARRAY OF ARRAY OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF ARRAY OF INTEGER; dim: INTEGER);
	VAR len: LONGINT;
	BEGIN len := LEN (p, dim);
	END Procedure;
	BEGIN NEW (a, 10, 20); Procedure (a^, 2);
	END Test.


# indexing

positive: indexing global array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	BEGIN g[0] := 1; g[1] := 2; g[2] := LEN (g); ASSERT (g[0] = 1); ASSERT (g[1] = 2); ASSERT (g[g[0]] = 2); ASSERT (g[g[g[0]]] = 10);
	END Test.

negative: negative index into global array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER; index: LONGINT;
	BEGIN index := -1; g[index] := 0;
	END Test.

negative: too large index into global array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER; index: LONGINT;
	BEGIN index := LEN (g); g[index] := 0;
	END Test.

positive: reading global array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Set (VAR p: ARRAY OF INTEGER; index, value: INTEGER);
	BEGIN p[index] := value;
	END Set;
	BEGIN Set (g, 5, 15); ASSERT (g[5] = 15);
	END Test.

positive: writing global array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Get (CONST p: ARRAY OF INTEGER; index: INTEGER): INTEGER;
	BEGIN RETURN p[index];
	END Get;
	BEGIN g[5] := 15; ASSERT (Get (g, 5) = 15);
	END Test.

positive: reading two-dimensional global array

	MODULE Test;
	VAR g: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Set (VAR p: ARRAY OF ARRAY OF INTEGER; index1, index2, value: INTEGER);
	BEGIN p[index1, index2] := value;
	END Set;
	BEGIN Set (g, 5, 6, 15); ASSERT (g[5, 6] = 15);
	END Test.

positive: writing two-dimensional global array

	MODULE Test;
	VAR g: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Get (CONST p: ARRAY OF ARRAY OF INTEGER; index1, index2: INTEGER): INTEGER;
	BEGIN RETURN p[index1, index2];
	END Get;
	BEGIN g[5, 6] := 15; ASSERT (Get (g, 5, 6) = 15);
	END Test.

positive: indexing local array

	MODULE Test;
	PROCEDURE Procedure;
	VAR l: ARRAY 10 OF INTEGER;
	BEGIN l[0] := 1; l[1] := 2; l[2] := LEN (l); ASSERT (l[0] = 1); ASSERT (l[1] = 2); ASSERT (l[l[0]] = 2); ASSERT (l[l[l[0]]] = 10);
	END Procedure;
	BEGIN Procedure;
	END Test.

negative: negative index into local array

	MODULE Test;
	PROCEDURE Procedure;
	VAR l: ARRAY 10 OF INTEGER; index: LONGINT;
	BEGIN index := -1; l[index] := 0;
	END Procedure;
	BEGIN Procedure;
	END Test.

negative: too large index into local array

	MODULE Test;
	PROCEDURE Procedure;
	VAR l: ARRAY 10 OF INTEGER; index: LONGINT;
	BEGIN index := LEN (l); l[index] := 0;
	END Procedure;
	BEGIN Procedure;
	END Test.

positive: reading local array

	MODULE Test;
	PROCEDURE Procedure;
	VAR l: ARRAY 10 OF INTEGER;
	BEGIN Set (l, 5, 15); ASSERT (l[5] = 15);
	END Procedure;
	PROCEDURE Set (VAR p: ARRAY OF INTEGER; index, value: INTEGER);
	BEGIN p[index] := value;
	END Set;
	BEGIN Procedure;
	END Test.

positive: writing local array

	MODULE Test;
	PROCEDURE Procedure;
	VAR l: ARRAY 10 OF INTEGER;
	BEGIN l[5] := 15; ASSERT (Get (l, 5) = 15);
	END Procedure;
	PROCEDURE Get (CONST p: ARRAY OF INTEGER; index: INTEGER): INTEGER;
	BEGIN RETURN p[index];
	END Get;
	BEGIN Procedure;
	END Test.

positive: reading two-dimensional local array

	MODULE Test;
	PROCEDURE Procedure;
	VAR l: ARRAY 10, 20 OF INTEGER;
	BEGIN Set (l, 5, 6, 15); ASSERT (l[5, 6] = 15);
	END Procedure;
	PROCEDURE Set (VAR p: ARRAY OF ARRAY OF INTEGER; index1, index2, value: INTEGER);
	BEGIN p[index1, index2] := value;
	END Set;
	BEGIN Procedure;
	END Test.

positive: writing two-dimensional local array

	MODULE Test;
	PROCEDURE Procedure;
	VAR l: ARRAY 10, 20 OF INTEGER;
	BEGIN l[5, 6] := 15; ASSERT (Get (l, 5, 6) = 15);
	END Procedure;
	PROCEDURE Get (CONST p: ARRAY OF ARRAY OF INTEGER; index1, index2: INTEGER): INTEGER;
	BEGIN RETURN p[index1, index2];
	END Get;
	BEGIN Procedure;
	END Test.

positive: indexing parameter array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY 10 OF INTEGER);
	BEGIN p[1] := 2; p[2] := LEN (p); ASSERT (p[0] = 1); ASSERT (p[1] = 2); ASSERT (p[p[0]] = 2); ASSERT (p[p[p[0]]] = 10);
	END Procedure;
	BEGIN g[0] := 1; Procedure (g);
	END Test.

negative: negative index into parameter array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER; index: LONGINT;
	PROCEDURE Procedure (p: ARRAY 10 OF INTEGER);
	BEGIN index := -1; p[index] := 0;
	END Procedure;
	BEGIN Procedure (g);
	END Test.

negative: too large index into parameter array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER; index: LONGINT;
	PROCEDURE Procedure (p: ARRAY 10 OF INTEGER);
	BEGIN index := LEN (p); p[index] := 0;
	END Procedure;
	BEGIN Procedure (g);
	END Test.

positive: reading parameter array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY 10 OF INTEGER);
	BEGIN Set (p, 5, 15); ASSERT (p[5] = 15);
	END Procedure;
	PROCEDURE Set (VAR p: ARRAY OF INTEGER; index, value: INTEGER);
	BEGIN p[index] := value;
	END Set;
	BEGIN Procedure (g);
	END Test.

positive: writing parameter array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY 10 OF INTEGER);
	BEGIN p[5] := 15; ASSERT (Get (p, 5) = 15);
	END Procedure;
	PROCEDURE Get (CONST p: ARRAY OF INTEGER; index: INTEGER): INTEGER;
	BEGIN RETURN p[index];
	END Get;
	BEGIN Procedure (g);
	END Test.

positive: reading two-dimensional parameter array

	MODULE Test;
	VAR g: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY 10, 20 OF INTEGER);
	BEGIN Set (p, 5, 6, 15); ASSERT (p[5, 6] = 15);
	END Procedure;
	PROCEDURE Set (VAR p: ARRAY OF ARRAY OF INTEGER; index1, index2, value: INTEGER);
	BEGIN p[index1, index2] := value;
	END Set;
	BEGIN Procedure (g);
	END Test.

positive: writing two-dimensional parameter array

	MODULE Test;
	VAR g: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY 10, 20 OF INTEGER);
	BEGIN p[5, 6] := 15; ASSERT (Get (p, 5, 6) = 15);
	END Procedure;
	PROCEDURE Get (CONST p: ARRAY OF ARRAY OF INTEGER; index1, index2: INTEGER): INTEGER;
	BEGIN RETURN p[index1, index2];
	END Get;
	BEGIN Procedure (g);
	END Test.

positive: indexing variable parameter array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY 10 OF INTEGER);
	BEGIN p[1] := 2; p[2] := LEN (p); ASSERT (p[0] = 1); ASSERT (p[1] = 2); ASSERT (p[p[0]] = 2); ASSERT (p[p[p[0]]] = 10);
	END Procedure;
	BEGIN g[0] := 1; Procedure (g); ASSERT (g[0] = 1); ASSERT (g[1] = 2); ASSERT (g[g[0]] = 2); ASSERT (g[g[g[0]]] = 10);
	END Test.

negative: negative index into variable parameter array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER; index: LONGINT;
	PROCEDURE Procedure (VAR p: ARRAY 10 OF INTEGER);
	BEGIN index := -1; p[index] := 0;
	END Procedure;
	BEGIN Procedure (g);
	END Test.

negative: too large index into variable parameter array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER; index: LONGINT;
	PROCEDURE Procedure (VAR p: ARRAY 10 OF INTEGER);
	BEGIN index := LEN (p); p[index] := 0;
	END Procedure;
	BEGIN Procedure (g);
	END Test.

positive: reading variable parameter array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY 10 OF INTEGER);
	BEGIN Set (p, 5, 15); ASSERT (p[5] = 15);
	END Procedure;
	PROCEDURE Set (VAR p: ARRAY OF INTEGER; index, value: INTEGER);
	BEGIN p[index] := value;
	END Set;
	BEGIN Procedure (g); ASSERT (g[5] = 15);
	END Test.

positive: writing variable parameter array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY 10 OF INTEGER);
	BEGIN p[5] := 15; ASSERT (Get (p, 5) = 15);
	END Procedure;
	PROCEDURE Get (CONST p: ARRAY OF INTEGER; index: INTEGER): INTEGER;
	BEGIN RETURN p[index];
	END Get;
	BEGIN Procedure (g); ASSERT (Get (g, 5) = 15); ASSERT (g[5] = 15);
	END Test.

positive: reading two-dimensional variable parameter array

	MODULE Test;
	VAR g: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY 10, 20 OF INTEGER);
	BEGIN Set (p, 5, 6, 15); ASSERT (p[5, 6] = 15);
	END Procedure;
	PROCEDURE Set (VAR p: ARRAY OF ARRAY OF INTEGER; index1, index2, value: INTEGER);
	BEGIN p[index1, index2] := value;
	END Set;
	BEGIN Procedure (g);  ASSERT (g[5, 6] = 15);
	END Test.

positive: writing two-dimensional variable parameter array

	MODULE Test;
	VAR g: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY 10, 20 OF INTEGER);
	BEGIN p[5, 6] := 15; ASSERT (Get (p, 5, 6) = 15);
	END Procedure;
	PROCEDURE Get (CONST p: ARRAY OF ARRAY OF INTEGER; index1, index2: INTEGER): INTEGER;
	BEGIN RETURN p[index1, index2];
	END Get;
	BEGIN Procedure (g); ASSERT (Get (g, 5, 6) = 15); ASSERT (g[5, 6] = 15);
	END Test.

positive: indexing constant parameter array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY 10 OF INTEGER);
	BEGIN ASSERT (p[0] = 1); ASSERT (p[1] = 2); ASSERT (p[p[0]] = 2); ASSERT (p[p[p[0]]] = 10);
	END Procedure;
	BEGIN g[0] := 1; g[1] := 2; g[2] := LEN (g); Procedure (g);
	END Test.

negative: negative index into constant parameter array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER; index: LONGINT;
	PROCEDURE Procedure (CONST p: ARRAY 10 OF INTEGER);
	BEGIN index := -1; index := p[index];
	END Procedure;
	BEGIN Procedure (g);
	END Test.

negative: too large index into constant parameter array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER; index: LONGINT;
	PROCEDURE Procedure (CONST p: ARRAY 10 OF INTEGER);
	BEGIN index := LEN (p); index := p[index];
	END Procedure;
	BEGIN Procedure (g);
	END Test.

positive: indexing open array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF INTEGER);
	BEGIN p[1] := 2; p[2] := SHORT (LEN (p)); ASSERT (p[0] = 1); ASSERT (p[1] = 2); ASSERT (p[p[0]] = 2); ASSERT (p[p[p[0]]] = 10);
	END Procedure;
	BEGIN g[0] := 1; Procedure (g);
	END Test.

negative: negative index into open array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER; index: LONGINT;
	PROCEDURE Procedure (p: ARRAY OF INTEGER);
	BEGIN index := -1; p[index] := 0;
	END Procedure;
	BEGIN Procedure (g);
	END Test.

negative: too large index into open array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER; index: LONGINT;
	PROCEDURE Procedure (p: ARRAY OF INTEGER);
	BEGIN index := LEN (p); p[index] := 0;
	END Procedure;
	BEGIN Procedure (g);
	END Test.

positive: reading open array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF INTEGER);
	BEGIN Set (p, 5, 15); ASSERT (p[5] = 15);
	END Procedure;
	PROCEDURE Set (VAR p: ARRAY OF INTEGER; index, value: INTEGER);
	BEGIN p[index] := value;
	END Set;
	BEGIN Procedure (g);
	END Test.

positive: writing open array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF INTEGER);
	BEGIN p[5] := 15; ASSERT (Get (p, 5) = 15);
	END Procedure;
	PROCEDURE Get (CONST p: ARRAY OF INTEGER; index: INTEGER): INTEGER;
	BEGIN RETURN p[index];
	END Get;
	BEGIN Procedure (g);
	END Test.

positive: reading two-dimensional open array

	MODULE Test;
	VAR g: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF ARRAY OF INTEGER);
	BEGIN Set (p, 5, 6, 15); ASSERT (p[5, 6] = 15);
	END Procedure;
	PROCEDURE Set (VAR p: ARRAY OF ARRAY OF INTEGER; index1, index2, value: INTEGER);
	BEGIN p[index1, index2] := value;
	END Set;
	BEGIN Procedure (g);
	END Test.

positive: writing two-dimensional open array

	MODULE Test;
	VAR g: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF ARRAY OF INTEGER);
	BEGIN p[5, 6] := 15; ASSERT (Get (p, 5, 6) = 15);
	END Procedure;
	PROCEDURE Get (CONST p: ARRAY OF ARRAY OF INTEGER; index1, index2: INTEGER): INTEGER;
	BEGIN RETURN p[index1, index2];
	END Get;
	BEGIN Procedure (g);
	END Test.

positive: indexing variable open array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF INTEGER);
	BEGIN p[1] := 2; p[2] := SHORT (LEN (p)); ASSERT (p[0] = 1); ASSERT (p[1] = 2); ASSERT (p[p[0]] = 2); ASSERT (p[p[p[0]]] = 10);
	END Procedure;
	BEGIN g[0] := 1; Procedure (g); ASSERT (g[0] = 1); ASSERT (g[1] = 2); ASSERT (g[g[0]] = 2); ASSERT (g[g[g[0]]] = 10);
	END Test.

negative: negative index into variable open array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER; index: LONGINT;
	PROCEDURE Procedure (VAR p: ARRAY OF INTEGER);
	BEGIN index := -1; p[index] := 0;
	END Procedure;
	BEGIN Procedure (g);
	END Test.

negative: too large index into variable open array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER; index: LONGINT;
	PROCEDURE Procedure (VAR p: ARRAY OF INTEGER);
	BEGIN index := LEN (p); p[index] := 0;
	END Procedure;
	BEGIN Procedure (g);
	END Test.

positive: reading variable open array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF INTEGER);
	BEGIN Set (p, 5, 15); ASSERT (p[5] = 15);
	END Procedure;
	PROCEDURE Set (VAR p: ARRAY OF INTEGER; index, value: INTEGER);
	BEGIN p[index] := value;
	END Set;
	BEGIN Procedure (g); ASSERT (g[5] = 15);
	END Test.

positive: writing variable open array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF INTEGER);
	BEGIN p[5] := 15; ASSERT (Get (p, 5) = 15);
	END Procedure;
	PROCEDURE Get (CONST p: ARRAY OF INTEGER; index: INTEGER): INTEGER;
	BEGIN RETURN p[index];
	END Get;
	BEGIN Procedure (g); ASSERT (Get (g, 5) = 15); ASSERT (g[5] = 15);
	END Test.

positive: reading two-dimensional variable open array

	MODULE Test;
	VAR g: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF ARRAY OF INTEGER);
	BEGIN Set (p, 5, 6, 15); ASSERT (p[5, 6] = 15);
	END Procedure;
	PROCEDURE Set (VAR p: ARRAY OF ARRAY OF INTEGER; index1, index2, value: INTEGER);
	BEGIN p[index1, index2] := value;
	END Set;
	BEGIN Procedure (g); ASSERT (g[5, 6] = 15);
	END Test.

positive: writing two-dimensional variable open array

	MODULE Test;
	VAR g: ARRAY 10, 20 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF ARRAY OF INTEGER);
	BEGIN p[5, 6] := 15; ASSERT (Get (p, 5, 6) = 15);
	END Procedure;
	PROCEDURE Get (CONST p: ARRAY OF ARRAY OF INTEGER; index1, index2: INTEGER): INTEGER;
	BEGIN RETURN p[index1, index2];
	END Get;
	BEGIN Procedure (g); ASSERT (Get (g, 5, 6) = 15); ASSERT (g[5, 6] = 15);
	END Test.

positive: indexing constant open array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (CONST p: ARRAY OF INTEGER);
	BEGIN ASSERT (p[0] = 1); ASSERT (p[1] = 2); ASSERT (p[p[0]] = 2); ASSERT (p[p[p[0]]] = 10);
	END Procedure;
	BEGIN g[0] := 1; g[1] := 2; g[2] := LEN (g); Procedure (g);
	END Test.

negative: negative index into constant open array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER; index: LONGINT;
	PROCEDURE Procedure (p: ARRAY OF INTEGER);
	BEGIN index := -1; p[index] := 0;
	END Procedure;
	BEGIN Procedure (g);
	END Test.

negative: too large index into constant open array

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER; index: LONGINT;
	PROCEDURE Procedure (p: ARRAY OF INTEGER);
	BEGIN index := LEN (p); p[index] := 0;
	END Procedure;
	BEGIN Procedure (g);
	END Test.

positive: indexing pointer to array

	MODULE Test;
	VAR g: POINTER TO ARRAY 10 OF INTEGER;
	BEGIN NEW (g); g[0] := 1; g[1] := 2; g[2] := LEN (g^); ASSERT (g[0] = 1); ASSERT (g[1] = 2); ASSERT (g[g[0]] = 2); ASSERT (g[g[g[0]]] = 10);
	END Test.

negative: negative index into pointer to array

	MODULE Test;
	VAR g: POINTER TO ARRAY 10 OF INTEGER; index: LONGINT;
	BEGIN NEW (g); index := -1; g[index] := 0;
	END Test.

negative: too large index into pointer to array

	MODULE Test;
	VAR g: POINTER TO ARRAY 10 OF INTEGER; index: LONGINT;
	BEGIN NEW (g); index := LEN (g^); g[index] := 0;
	END Test.

positive: reading pointer to array

	MODULE Test;
	VAR g: POINTER TO ARRAY 10 OF INTEGER;
	PROCEDURE Set (VAR p: ARRAY OF INTEGER; index, value: INTEGER);
	BEGIN p[index] := value;
	END Set;
	BEGIN NEW (g); Set (g^, 5, 15); ASSERT (g[5] = 15);
	END Test.

positive: writing pointer to array

	MODULE Test;
	VAR g: POINTER TO ARRAY 10 OF INTEGER;
	PROCEDURE Get (CONST p: ARRAY OF INTEGER; index: INTEGER): INTEGER;
	BEGIN RETURN p[index];
	END Get;
	BEGIN NEW (g); g[5] := 15; ASSERT (Get (g^, 5) = 15);
	END Test.

positive: reading two-dimensional pointer to array

	MODULE Test;
	VAR g: POINTER TO ARRAY 10, 20 OF INTEGER;
	PROCEDURE Set (VAR p: ARRAY OF ARRAY OF INTEGER; index1, index2, value: INTEGER);
	BEGIN p[index1, index2] := value;
	END Set;
	BEGIN NEW (g); Set (g^, 5, 6, 15); ASSERT (g[5, 6] = 15);
	END Test.

positive: writing two-dimensional pointer to array

	MODULE Test;
	VAR g: POINTER TO ARRAY 10, 20 OF INTEGER;
	PROCEDURE Get (CONST p: ARRAY OF ARRAY OF INTEGER; index1, index2: INTEGER): INTEGER;
	BEGIN RETURN p[index1, index2];
	END Get;
	BEGIN NEW (g); g[5, 6] := 15; ASSERT (Get (g^, 5, 6) = 15);
	END Test.

positive: indexing pointer to open array

	MODULE Test;
	VAR g: POINTER TO ARRAY OF INTEGER;
	BEGIN NEW (g, 10); g[0] := 1; g[1] := 2; g[2] := SHORT (LEN (g^)); ASSERT (g[0] = 1); ASSERT (g[1] = 2); ASSERT (g[g[0]] = 2); ASSERT (g[g[g[0]]] = 10);
	END Test.

negative: negative index into pointer to open array

	MODULE Test;
	VAR g: POINTER TO ARRAY OF INTEGER; index: LONGINT;
	BEGIN NEW (g, 10); index := -1; g[index] := 0;
	END Test.

negative: too large index into pointer to open array

	MODULE Test;
	VAR g: POINTER TO ARRAY OF INTEGER; index: LONGINT;
	BEGIN NEW (g, 10); index := LEN (g^); g[index] := 0;
	END Test.

positive: reading pointer to open array

	MODULE Test;
	VAR g: POINTER TO ARRAY OF INTEGER;
	PROCEDURE Set (VAR p: ARRAY OF INTEGER; index, value: INTEGER);
	BEGIN p[index] := value;
	END Set;
	BEGIN NEW (g, 10); Set (g^, 5, 15); ASSERT (g[5] = 15);
	END Test.

positive: writing pointer to open array

	MODULE Test;
	VAR g: POINTER TO ARRAY OF INTEGER;
	PROCEDURE Get (CONST p: ARRAY OF INTEGER; index: INTEGER): INTEGER;
	BEGIN RETURN p[index];
	END Get;
	BEGIN NEW (g, 10); g[5] := 15; ASSERT (Get (g^, 5) = 15);
	END Test.

positive: reading two-dimensional pointer to open array

	MODULE Test;
	VAR g: POINTER TO ARRAY OF ARRAY OF INTEGER;
	PROCEDURE Set (VAR p: ARRAY OF ARRAY OF INTEGER; index1, index2, value: INTEGER);
	BEGIN p[index1, index2] := value;
	END Set;
	BEGIN NEW (g, 10, 20); Set (g^, 5, 6, 15); ASSERT (g[5, 6] = 15);
	END Test.

positive: writing two-dimensional pointer to open array

	MODULE Test;
	VAR g: POINTER TO ARRAY OF ARRAY OF INTEGER;
	PROCEDURE Get (CONST p: ARRAY OF ARRAY OF INTEGER; index1, index2: INTEGER): INTEGER;
	BEGIN RETURN p[index1, index2];
	END Get;
	BEGIN NEW (g, 10, 20); g[5, 6] := 15; ASSERT (Get (g^, 5, 6) = 15);
	END Test.


# modifying parameters

positive: modifying boolean parameter

	MODULE Test;
	VAR g: BOOLEAN;
	PROCEDURE Procedure (p: BOOLEAN);
	BEGIN ASSERT (p); p := FALSE; ASSERT (~p); ASSERT (g);
	END Procedure;
	BEGIN g := TRUE; Procedure (g); ASSERT (g);
	END Test.

positive: modifying character parameter

	MODULE Test;
	VAR g: CHAR;
	PROCEDURE Procedure (p: CHAR);
	BEGIN ASSERT (p = 'c'); p := 'Z'; ASSERT (p = 'Z'); ASSERT (g = 'c');
	END Procedure;
	BEGIN g := 'c'; Procedure (g); ASSERT (g = 'c');
	END Test.

positive: modifying integer parameter

	MODULE Test;
	VAR g: INTEGER;
	PROCEDURE Procedure (p: INTEGER);
	BEGIN ASSERT (p = 2); INC (p); ASSERT (p = 3); ASSERT (g = 2);
	END Procedure;
	BEGIN g := 2; Procedure (g); ASSERT (g = 2);
	END Test.

positive: modifying real parameter

	MODULE Test;
	VAR g: REAL;
	PROCEDURE Procedure (p: REAL);
	BEGIN ASSERT (p = 2.5); p := p * 2; ASSERT (p = 5); ASSERT (g = 2.5);
	END Procedure;
	BEGIN g := 2.5; Procedure (g); ASSERT (g = 2.5);
	END Test.

positive: modifying set parameter

	MODULE Test;
	VAR g: SET;
	PROCEDURE Procedure (p: SET);
	BEGIN ASSERT (p = {3}); INCL (p, 2); INCL (p, 4); ASSERT (p = {2 .. 4}); ASSERT (g = {3});
	END Procedure;
	BEGIN g := {3}; Procedure (g); ASSERT (g = {3});
	END Test.

positive: modifying array parameter

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY 10 OF INTEGER);
	BEGIN ASSERT (p[1] = 23); ASSERT (p[8] = 91); p[8] := 19; p[1] := 32; ASSERT (p[1] = 32); ASSERT (p[8] = 19); ASSERT (g[1] = 23); ASSERT (g[8] = 91);
	END Procedure;
	BEGIN g[1] := 23; g[8] := 91; Procedure (g); ASSERT (g[1] = 23); ASSERT (g[8] = 91);
	END Test.

positive: modifying open array parameter

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (p: ARRAY OF INTEGER);
	BEGIN ASSERT (p[1] = 23); ASSERT (p[8] = 91); p[8] := 19; p[1] := 32; ASSERT (p[1] = 32); ASSERT (p[8] = 19); ASSERT (g[1] = 23); ASSERT (g[8] = 91);
	END Procedure;
	BEGIN g[1] := 23; g[8] := 91; Procedure (g); ASSERT (g[1] = 23); ASSERT (g[8] = 91);
	END Test.

positive: modifying character array parameter

	MODULE Test;
	VAR g: ARRAY 10 OF CHAR;
	PROCEDURE Procedure (p: ARRAY 10 OF CHAR);
	BEGIN ASSERT (p = "value"); p := "modified"; ASSERT (p = "modified"); ASSERT (g = "value");
	END Procedure;
	BEGIN g := "value"; Procedure (g); ASSERT (g = "value");
	END Test.

positive: modifying open character array parameter

	MODULE Test;
	VAR g: ARRAY 10 OF CHAR;
	PROCEDURE Procedure (p: ARRAY OF CHAR);
	BEGIN ASSERT (p = "value"); p := "modified"; ASSERT (p = "modified"); ASSERT (g = "value");
	END Procedure;
	BEGIN g := "value"; Procedure (g); ASSERT (g = "value");
	END Test.

positive: modifying record parameter

	MODULE Test;
	TYPE Record = RECORD x: INTEGER END;
	VAR g: Record;
	PROCEDURE Procedure (p: Record);
	BEGIN ASSERT (p.x = 15); p.x := p.x * 3; ASSERT (p.x = 45); ASSERT (g.x = 15);
	END Procedure;
	BEGIN g.x := 15; Procedure (g); ASSERT (g.x = 15);
	END Test.

positive: modifying object parameter

	MODULE Test;
	TYPE Object = OBJECT VAR x: INTEGER END Object;
	VAR g: Object;
	PROCEDURE Procedure (p: Object);
	BEGIN ASSERT (p.x = 20); p.x := 10; ASSERT (p.x = 10); ASSERT (g.x = 10);
	END Procedure;
	BEGIN NEW (g); g.x := 20; Procedure (g); ASSERT (g.x = 10);
	END Test.

positive: modifying object reference parameter

	MODULE Test;
	TYPE Object = OBJECT END Object;
	VAR g: Object;
	PROCEDURE Procedure (p: Object);
	BEGIN ASSERT (p # NIL); p := NIL; ASSERT (p = NIL); ASSERT (g # NIL);
	END Procedure;
	BEGIN NEW (g); Procedure (g); ASSERT (g # NIL);
	END Test.

positive: modifying pointer to array parameter

	MODULE Test;
	VAR g: POINTER TO ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (p: POINTER TO ARRAY 10 OF INTEGER);
	BEGIN ASSERT (p[1] = 23); ASSERT (p[8] = 91); p[8] := 19; p[1] := 32; ASSERT (p[1] = 32); ASSERT (p[8] = 19); ASSERT (g[1] = 32); ASSERT (g[8] = 19);
	END Procedure;
	BEGIN NEW (g); g[1] := 23; g[8] := 91; Procedure (g); ASSERT (g[1] = 32); ASSERT (g[8] = 19);
	END Test.

positive: modifying pointer to open array parameter

	MODULE Test;
	VAR g: POINTER TO ARRAY OF INTEGER;
	PROCEDURE Procedure (p: POINTER TO ARRAY OF INTEGER);
	BEGIN ASSERT (p[1] = 23); ASSERT (p[8] = 91); p[8] := 19; p[1] := 32; ASSERT (p[1] = 32); ASSERT (p[8] = 19); ASSERT (g[1] = 32); ASSERT (g[8] = 19);
	END Procedure;
	BEGIN NEW (g, 10); g[1] := 23; g[8] := 91; Procedure (g); ASSERT (g[1] = 32); ASSERT (g[8] = 19);
	END Test.

positive: modifying pointer to character array parameter

	MODULE Test;
	VAR g: POINTER TO ARRAY 10 OF CHAR;
	PROCEDURE Procedure (p: POINTER TO ARRAY 10 OF CHAR);
	BEGIN ASSERT (p^ = "value"); p^ := "modified"; ASSERT (p^ = "modified"); ASSERT (g^ = "modified");
	END Procedure;
	BEGIN NEW (g); g^ := "value"; Procedure (g); ASSERT (g^ = "modified");
	END Test.

positive: modifying pointer to open character array parameter

	MODULE Test;
	VAR g: POINTER TO ARRAY OF CHAR;
	PROCEDURE Procedure (p: POINTER TO ARRAY OF CHAR);
	BEGIN ASSERT (p^ = "value"); p^ := "modified"; ASSERT (p^ = "modified"); ASSERT (g^ = "modified");
	END Procedure;
	BEGIN NEW (g, 10); g^ := "value"; Procedure (g); ASSERT (g^ = "modified");
	END Test.

positive: modifying pointer to array reference parameter

	MODULE Test;
	VAR g: POINTER TO ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (p: POINTER TO ARRAY 10 OF INTEGER);
	BEGIN ASSERT (p # NIL); p := NIL; ASSERT (p = NIL); ASSERT (g # NIL);
	END Procedure;
	BEGIN NEW (g); Procedure (g); ASSERT (g # NIL);
	END Test.

positive: modifying pointer to record parameter

	MODULE Test;
	TYPE Record = RECORD x: INTEGER END;
	VAR g: POINTER TO Record;
	PROCEDURE Procedure (p: POINTER TO Record);
	BEGIN ASSERT (p.x = 15); p.x := p.x * 3; ASSERT (p.x = 45); ASSERT (g.x = 45);
	END Procedure;
	BEGIN NEW (g); g.x := 15; Procedure (g); ASSERT (g.x = 45);
	END Test.

positive: modifying pointer to record reference parameter

	MODULE Test;
	TYPE Record = RECORD END;
	VAR g: POINTER TO Record;
	PROCEDURE Procedure (p: POINTER TO Record);
	BEGIN ASSERT (p # NIL); p := NIL; ASSERT (p = NIL); ASSERT (g # NIL);
	END Procedure;
	BEGIN NEW (g); Procedure (g); ASSERT (g # NIL);
	END Test.

positive: modifying procedure parameter

	MODULE Test;
	TYPE P = PROCEDURE (p: P);
	VAR g: P;
	PROCEDURE Procedure (p: P);
	BEGIN ASSERT (p # NIL); p := NIL; ASSERT (p = NIL); ASSERT (g # NIL);
	END Procedure;
	BEGIN g := Procedure; Procedure (g); ASSERT (g # NIL);
	END Test.

positive: modifying variable boolean parameter

	MODULE Test;
	VAR g: BOOLEAN;
	PROCEDURE Procedure (VAR p: BOOLEAN);
	BEGIN ASSERT (p); p := FALSE; ASSERT (~p); ASSERT (~g);
	END Procedure;
	BEGIN g := TRUE; Procedure (g); ASSERT (~g);
	END Test.

positive: modifying variable character parameter

	MODULE Test;
	VAR g: CHAR;
	PROCEDURE Procedure (VAR p: CHAR);
	BEGIN ASSERT (p = 'c'); p := 'Z'; ASSERT (p = 'Z'); ASSERT (g = 'Z');
	END Procedure;
	BEGIN g := 'c'; Procedure (g); ASSERT (g = 'Z');
	END Test.

positive: modifying variable integer parameter

	MODULE Test;
	VAR g: INTEGER;
	PROCEDURE Procedure (VAR p: INTEGER);
	BEGIN ASSERT (p = 2); INC (p); ASSERT (p = 3); ASSERT (g = 3);
	END Procedure;
	BEGIN g := 2; Procedure (g); ASSERT (g = 3);
	END Test.

positive: modifying variable real parameter

	MODULE Test;
	VAR g: REAL;
	PROCEDURE Procedure (VAR p: REAL);
	BEGIN ASSERT (p = 2.5); p := p * 2; ASSERT (p = 5); ASSERT (g = 5);
	END Procedure;
	BEGIN g := 2.5; Procedure (g); ASSERT (g = 5);
	END Test.

positive: modifying variable set parameter

	MODULE Test;
	VAR g: SET;
	PROCEDURE Procedure (VAR p: SET);
	BEGIN ASSERT (p = {3}); INCL (p, 2); INCL (p, 4); ASSERT (p = {2 .. 4}); ASSERT (g = {2 .. 4});
	END Procedure;
	BEGIN g := {3}; Procedure (g); ASSERT (g = {2 .. 4});
	END Test.

positive: modifying variable array parameter

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY 10 OF INTEGER);
	BEGIN ASSERT (p[1] = 23); ASSERT (p[8] = 91); p[8] := 19; p[1] := 32; ASSERT (p[1] = 32); ASSERT (p[8] = 19); ASSERT (g[1] = 32); ASSERT (g[8] = 19);
	END Procedure;
	BEGIN g[1] := 23; g[8] := 91; Procedure (g); ASSERT (g[1] = 32); ASSERT (g[8] = 19);
	END Test.

positive: modifying variable open array parameter

	MODULE Test;
	VAR g: ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (VAR p: ARRAY OF INTEGER);
	BEGIN ASSERT (p[1] = 23); ASSERT (p[8] = 91); p[8] := 19; p[1] := 32; ASSERT (p[1] = 32); ASSERT (p[8] = 19); ASSERT (g[1] = 32); ASSERT (g[8] = 19);
	END Procedure;
	BEGIN g[1] := 23; g[8] := 91; Procedure (g); ASSERT (g[1] = 32); ASSERT (g[8] = 19);
	END Test.

positive: modifying variable character array parameter

	MODULE Test;
	VAR g: ARRAY 10 OF CHAR;
	PROCEDURE Procedure (VAR p: ARRAY 10 OF CHAR);
	BEGIN ASSERT (p = "value"); p := "modified"; ASSERT (p = "modified"); ASSERT (g = "modified");
	END Procedure;
	BEGIN g := "value"; Procedure (g); ASSERT (g = "modified");
	END Test.

positive: modifying variable open character array parameter

	MODULE Test;
	VAR g: ARRAY 10 OF CHAR;
	PROCEDURE Procedure (VAR p: ARRAY OF CHAR);
	BEGIN ASSERT (p = "value"); p := "modified"; ASSERT (p = "modified"); ASSERT (g = "modified");
	END Procedure;
	BEGIN g := "value"; Procedure (g); ASSERT (g = "modified");
	END Test.

positive: modifying variable record parameter

	MODULE Test;
	TYPE Record = RECORD x: INTEGER END;
	VAR g: Record;
	PROCEDURE Procedure (VAR p: Record);
	BEGIN ASSERT (p.x = 15); p.x := p.x * 3; ASSERT (p.x = 45); ASSERT (g.x = 45);
	END Procedure;
	BEGIN g.x := 15; Procedure (g); ASSERT (g.x = 45);
	END Test.

positive: modifying variable object parameter

	MODULE Test;
	TYPE Object = OBJECT VAR x: INTEGER END Object;
	VAR g: Object;
	PROCEDURE Procedure (VAR p: Object);
	BEGIN ASSERT (p.x = 20); p.x := 10; ASSERT (p.x = 10); ASSERT (g.x = 10);
	END Procedure;
	BEGIN NEW (g); g.x := 20; Procedure (g); ASSERT (g.x = 10);
	END Test.

positive: modifying variable object reference parameter

	MODULE Test;
	TYPE Object = OBJECT END Object;
	VAR g: Object;
	PROCEDURE Procedure (VAR p: Object);
	BEGIN ASSERT (p # NIL); p := NIL; ASSERT (p = NIL); ASSERT (g = NIL);
	END Procedure;
	BEGIN NEW (g); Procedure (g); ASSERT (g = NIL);
	END Test.

positive: modifying variable pointer to array parameter

	MODULE Test;
	VAR g: POINTER TO ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (VAR p: POINTER TO ARRAY 10 OF INTEGER);
	BEGIN ASSERT (p[1] = 23); ASSERT (p[8] = 91); p[8] := 19; p[1] := 32; ASSERT (p[1] = 32); ASSERT (p[8] = 19); ASSERT (g[1] = 32); ASSERT (g[8] = 19);
	END Procedure;
	BEGIN NEW (g); g[1] := 23; g[8] := 91; Procedure (g); ASSERT (g[1] = 32); ASSERT (g[8] = 19);
	END Test.

positive: modifying variable pointer to open array parameter

	MODULE Test;
	VAR g: POINTER TO ARRAY OF INTEGER;
	PROCEDURE Procedure (VAR p: POINTER TO ARRAY OF INTEGER);
	BEGIN ASSERT (p[1] = 23); ASSERT (p[8] = 91); p[8] := 19; p[1] := 32; ASSERT (p[1] = 32); ASSERT (p[8] = 19); ASSERT (g[1] = 32); ASSERT (g[8] = 19);
	END Procedure;
	BEGIN NEW (g, 10); g[1] := 23; g[8] := 91; Procedure (g); ASSERT (g[1] = 32); ASSERT (g[8] = 19);
	END Test.

positive: modifying variable pointer to character array parameter

	MODULE Test;
	VAR g: POINTER TO ARRAY 10 OF CHAR;
	PROCEDURE Procedure (VAR p: POINTER TO ARRAY 10 OF CHAR);
	BEGIN ASSERT (p^ = "value"); p^ := "modified"; ASSERT (p^ = "modified"); ASSERT (g^ = "modified");
	END Procedure;
	BEGIN NEW (g); g^ := "value"; Procedure (g); ASSERT (g^ = "modified");
	END Test.

positive: modifying variable pointer to open character array parameter

	MODULE Test;
	VAR g: POINTER TO ARRAY OF CHAR;
	PROCEDURE Procedure (VAR p: POINTER TO ARRAY OF CHAR);
	BEGIN ASSERT (p^ = "value"); p^ := "modified"; ASSERT (p^ = "modified"); ASSERT (g^ = "modified");
	END Procedure;
	BEGIN NEW (g, 10); g^ := "value"; Procedure (g); ASSERT (g^ = "modified");
	END Test.

positive: modifying variable pointer to array reference parameter

	MODULE Test;
	VAR g: POINTER TO ARRAY 10 OF INTEGER;
	PROCEDURE Procedure (VAR p: POINTER TO ARRAY 10 OF INTEGER);
	BEGIN ASSERT (p # NIL); p := NIL; ASSERT (p = NIL); ASSERT (g = NIL);
	END Procedure;
	BEGIN NEW (g); Procedure (g); ASSERT (g = NIL);
	END Test.

positive: modifying variable pointer to record parameter

	MODULE Test;
	TYPE Record = RECORD x: INTEGER END;
	VAR g: POINTER TO Record;
	PROCEDURE Procedure (VAR p: POINTER TO Record);
	BEGIN ASSERT (p.x = 15); p.x := p.x * 3; ASSERT (p.x = 45); ASSERT (g.x = 45);
	END Procedure;
	BEGIN NEW (g); g.x := 15; Procedure (g); ASSERT (g.x = 45);
	END Test.

positive: modifying variable pointer to record reference parameter

	MODULE Test;
	TYPE Record = RECORD END;
	VAR g: POINTER TO Record;
	PROCEDURE Procedure (VAR p: POINTER TO Record);
	BEGIN ASSERT (p # NIL); p := NIL; ASSERT (p = NIL); ASSERT (g = NIL);
	END Procedure;
	BEGIN NEW (g); Procedure (g); ASSERT (g = NIL);
	END Test.

positive: modifying variable procedure parameter

	MODULE Test;
	TYPE P = PROCEDURE (VAR p: P);
	VAR g: P;
	PROCEDURE Procedure (VAR p: P);
	BEGIN ASSERT (p # NIL); p := NIL; ASSERT (p = NIL); ASSERT (g = NIL);
	END Procedure;
	BEGIN g := Procedure; Procedure (g); ASSERT (g = NIL);
	END Test.


# if statement

positive: if statement with satisfied condition

	MODULE Test;
	VAR i: INTEGER;
	BEGIN i := 0; IF i = 0 THEN ELSIF i = 1 THEN HALT (1234) ELSIF i = 2 THEN HALT (1234) ELSE HALT (1234) END;
		IF i = 0 THEN RETURN ELSIF i = 1 THEN ELSIF i = 2 THEN ELSE END; HALT (1234);
	END Test.

positive: if statement with unsatisfied condition

	MODULE Test;
	VAR i: INTEGER;
	BEGIN i := 2; IF i = 0 THEN HALT (1234) ELSIF i = 1 THEN HALT (1234) ELSIF i = 2 THEN ELSE HALT (1234) END;
		IF i = 0 THEN ELSIF i = 1 THEN ELSIF i = 2 THEN RETURN ELSE END; HALT (1234);
	END Test.

positive: else if statement with unsatisfied condition

	MODULE Test;
	VAR i: INTEGER;
	BEGIN i := 4; IF i = 0 THEN HALT (1234) ELSIF i = 1 THEN HALT (1234) ELSIF i = 2 THEN HALT (1234) ELSE END;
		IF i = 0 THEN ELSIF i = 1 THEN ELSIF i = 2 THEN ELSE RETURN END; HALT (1234);
	END Test.


# exit statement

positive: unconditional exit statement

	MODULE Test;
	BEGIN LOOP EXIT; HALT (1234) END;
	END Test.

positive: nested unconditional exit statement

	MODULE Test;
	BEGIN LOOP LOOP EXIT; HALT (1234) END; EXIT; HALT (1234) END;
	END Test.

positive: conditional exit statement

	MODULE Test;
	VAR i: INTEGER;
	BEGIN i := 0; LOOP IF i = 0 THEN EXIT END; HALT (1234) END;
	END Test.

positive: nested conditional exit statement

	MODULE Test;
	VAR i: INTEGER;
	BEGIN i := 0; LOOP LOOP IF i = 0 THEN EXIT END; HALT (1234) END; EXIT; HALT (1234) END;
	END Test.


# case statement

positive: case statement with character value

	MODULE Test;
	PROCEDURE Case (c: CHAR): INTEGER;
	BEGIN CASE c OF | 'a', 't', 'j': RETURN 0 | 'l'..'o': RETURN 1 | 'r', 'b', 10X: RETURN 2 ELSE RETURN 3; END; HALT (1234);
	END Case;
	BEGIN ASSERT (Case ('a') = 0); ASSERT (Case ('b') = 2); ASSERT (Case ('c') = 3); ASSERT (Case ('j') = 0); ASSERT (Case ('n') = 1);
		ASSERT (Case ('o') = 1); ASSERT (Case ('r') = 2); ASSERT (Case ('t') = 0); ASSERT (Case ('z') = 3); ASSERT (Case (10X) = 2);
	END Test.

negative: case statement with unmatched character value

	MODULE Test;
	VAR c: CHAR;
	BEGIN c := 't'; CASE c OF | 'a'..'g': | 's', 'r': | 'u', 'v': END;
	END Test.

positive: case statement with integer value

	MODULE Test;
	PROCEDURE Case (i: INTEGER): INTEGER;
	BEGIN CASE i OF | 1, 3, 9: RETURN 0 | 4..6: RETURN 1 | 8, 2: RETURN 2 ELSE RETURN 3; END; HALT (1234);
	END Case;
	BEGIN ASSERT (Case (0) = 3); ASSERT (Case (1) = 0); ASSERT (Case (2) = 2); ASSERT (Case (3) = 0); ASSERT (Case (4) = 1);
		ASSERT (Case (5) = 1); ASSERT (Case (6) = 1); ASSERT (Case (7) = 3); ASSERT (Case (8) = 2); ASSERT (Case (9) = 0);
	END Test.

negative: case statement with unmatched integer value

	MODULE Test;
	VAR i: INTEGER;
	BEGIN i := 7; CASE i OF | 1, 3, 9: | 4..6: | 8, 2: END;
	END Test.


# for statement

positive: for statement with positive step sizes

	MODULE Test;
	VAR i, steps: INTEGER;
	BEGIN
		steps := 0; FOR i := 0 TO 10 DO INC (steps) END; ASSERT (steps = 11);
		steps := 0; FOR i := 0 TO 10 BY 1 DO INC (steps) END; ASSERT (steps = 11);
		steps := 0; FOR i := 0 TO 10 BY 2 DO INC (steps) END; ASSERT (steps = 6);
		steps := 0; FOR i := 0 TO 10 BY 3 DO INC (steps) END; ASSERT (steps = 4);
		steps := 0; FOR i := 0 TO 10 BY 4 DO INC (steps) END; ASSERT (steps = 3);
	END Test.

positive: for statement with negative step sizes

	MODULE Test;
	VAR i, steps: INTEGER;
	BEGIN
		steps := 0; FOR i := 10 TO 0 DO INC (steps) END; ASSERT (steps = 0);
		steps := 0; FOR i := 10 TO 0 BY -1 DO INC (steps) END; ASSERT (steps = 11);
		steps := 0; FOR i := 10 TO 0 BY -2 DO INC (steps) END; ASSERT (steps = 6);
		steps := 0; FOR i := 10 TO 0 BY -3 DO INC (steps) END; ASSERT (steps = 4);
		steps := 0; FOR i := 10 TO 0 BY -4 DO INC (steps) END; ASSERT (steps = 3);
	END Test.

positive: modifying start counter in for statement

	MODULE Test;
	VAR i, steps, start: INTEGER;
	BEGIN steps := 0; start := 0; FOR i := start TO 10 DO start := i; INC (steps) END; ASSERT (steps = 11);
	END Test.

positive: modifying end counter in for statement

	MODULE Test;
	VAR i, steps, end: INTEGER;
	BEGIN steps := 0; end := 10; FOR i := 0 TO end DO end := i; INC (steps) END; ASSERT (steps = 11);
	END Test.


# new statement

positive: new statement on pointer to record

	MODULE Test;
	VAR p: POINTER TO RECORD a, b: INTEGER END;
	BEGIN NEW (p); p.a := 3; p.b := p.a; ASSERT (p.b = 3);
	END Test.

positive: new statement on pointer to too large record

	MODULE Test;
	VAR p: POINTER TO RECORD data*: ARRAY MAX (LONGINT) DIV 16 - 1000 OF INTEGER END;
	BEGIN (*! NEW (p); ASSERT (p = NIL); *)
	END Test.

positive: new statement on pointer to array

	MODULE Test;
	VAR p: POINTER TO ARRAY 10 OF INTEGER;
	BEGIN NEW (p); p[2] := 3; p[1] := p[2]; ASSERT (p[2] = 3);
	END Test.

positive: new statement on pointer to too large array

	MODULE Test;
	VAR r: POINTER TO ARRAY MAX (LONGINT) DIV 16 - 1000 OF INTEGER;
	BEGIN (*! NEW (r); ASSERT (r = NIL); *)
	END Test.

positive: new statement on pointer to open array

	MODULE Test;
	VAR p: POINTER TO ARRAY OF INTEGER;
	BEGIN NEW (p, 10); p[2] := 3; p[1] := p[2]; ASSERT (p[2] = 3);
	END Test.

negative: new statement on pointer to open array with negative size

	MODULE Test;
	VAR p: POINTER TO ARRAY OF INTEGER; size: INTEGER;
	BEGIN size := -10; NEW (p, size);
	END Test.

positive: new statement on pointer to too large open array

	MODULE Test;
	VAR r: POINTER TO ARRAY OF INTEGER;
	BEGIN (*! NEW (r, MAX (LONGINT) DIV 2 - 1000); ASSERT (r = NIL); *)
	END Test.

positive: new statement on object

	MODULE Test;
	VAR o: OBJECT VAR a, b: INTEGER END;
	BEGIN NEW (o); o.a := 3; o.b := o.a; ASSERT (o.b = 3);
	END Test.

positive: new statement on too large object

	MODULE Test;
	VAR o: OBJECT VAR data*: ARRAY MAX (LONGINT) DIV 16 - 1000 OF INTEGER END;
	BEGIN (*! NEW (o); ASSERT (o = NIL); *)
	END Test.

positive: new statement modifying designator after object body

	MODULE Test;
	VAR o: OBJECT PROCEDURE &Init; BEGIN ASSERT (o = NIL); END Init; BEGIN ASSERT (o # NIL); END;
	BEGIN o := NIL; NEW (o); ASSERT (o # NIL);
	END Test.


# with statement

positive: with statement with same global record

	MODULE Test;
	TYPE R = RECORD b: BOOLEAN END;
	VAR r: R;
	BEGIN r.b := TRUE; WITH r : R DO ASSERT (r.b) END;
	END Test.

positive: with statement with same local record

	MODULE Test;
	PROCEDURE Procedure;
	TYPE R = RECORD b: BOOLEAN END;
	VAR r: R;
	BEGIN r.b := TRUE; WITH r : R DO ASSERT (r.b) END;
	END Procedure;
	BEGIN Procedure;
	END Test.

positive: with statement with same parameter record

	MODULE Test;
	TYPE R = RECORD b: BOOLEAN END;
	VAR r: R;
	PROCEDURE Procedure (r: R); BEGIN WITH r : R DO ASSERT (r.b); END; END Procedure;
	BEGIN r.b := TRUE; Procedure (r);
	END Test.

positive: with statement with same variable parameter record

	MODULE Test;
	TYPE R = RECORD b: BOOLEAN END;
	VAR r: R;
	PROCEDURE Procedure (VAR r: R); BEGIN WITH r : R DO ASSERT (r.b); END; END Procedure;
	BEGIN r.b := TRUE; Procedure (r);
	END Test.

positive: with statement with same constant parameter record

	MODULE Test;
	TYPE R = RECORD b: BOOLEAN END;
	VAR r: R;
	PROCEDURE Procedure (CONST r: R); BEGIN WITH r : R DO ASSERT (r.b); END; END Procedure;
	BEGIN r.b := TRUE; Procedure (r);
	END Test.

positive: with statement with variable parameter record

	MODULE Test;
	TYPE R0 = RECORD END; R1 = RECORD (R0) b: BOOLEAN END;
	VAR r: R1;
	PROCEDURE Procedure (VAR r: R0); BEGIN WITH r : R1 DO ASSERT (r.b); END; END Procedure;
	BEGIN r.b := TRUE; Procedure (r);
	END Test.

negative: unsatisfied with statement with variable parameter record

	MODULE Test;
	TYPE R0 = RECORD END; R1 = RECORD (R0) END;
	VAR r: R0;
	PROCEDURE Procedure (VAR r: R0); BEGIN WITH r : R1 DO END; END Procedure;
	BEGIN Procedure (r);
	END Test.

positive: with statement with constant parameter record

	MODULE Test;
	TYPE R0 = RECORD END; R1 = RECORD (R0) b: BOOLEAN END;
	VAR r: R1;
	PROCEDURE Procedure (CONST r: R0); BEGIN WITH r : R1 DO ASSERT (r.b); END; END Procedure;
	BEGIN r.b := TRUE; Procedure (r);
	END Test.

negative: unsatisfied with statement with constant parameter record

	MODULE Test;
	TYPE R0 = RECORD END; R1 = RECORD (R0) END;
	VAR r: R0;
	PROCEDURE Procedure (CONST r: R0); BEGIN WITH r : R1 DO END; END Procedure;
	BEGIN Procedure (r);
	END Test.

positive: with statement with same pointer to record

	MODULE Test;
	TYPE R = RECORD b: BOOLEAN END; P = POINTER TO R;
	VAR p: P;
	BEGIN NEW (p); p.b := TRUE; WITH p : P DO ASSERT (p.b); END;
	END Test.

positive: with statement with pointer to record

	MODULE Test;
	TYPE R0 = RECORD END; P0 = POINTER TO R0
	TYPE R1 = RECORD (R0) b: BOOLEAN END; P1 = POINTER TO R1;
	VAR p0: P0; p1: P1;
	BEGIN NEW (p1); p1.b := TRUE; p0 := p1; WITH p0 : P1 DO ASSERT (p0.b); END;
	END Test.

negative: unsatisfied with statement with pointer to record

	MODULE Test;
	TYPE R0 = RECORD END; P0 = POINTER TO R0;
	TYPE R1 = RECORD (R0) END; P1 = POINTER TO R1;
	VAR p0: P0;
	BEGIN NEW (p0); WITH p0 : P1 DO END;
	END Test.

negative: with statement with nil pointer to record

	MODULE Test;
	TYPE R0 = RECORD END; P0 = POINTER TO R0;
	TYPE R1 = RECORD (R0) END; P1 = POINTER TO R1;
	VAR p0: P0;
	BEGIN p0 := NIL; WITH p0 : P1 DO END;
	END Test.

positive: with statement with same object

	MODULE Test;
	TYPE O = OBJECT VAR b: BOOLEAN END O;
	VAR o: O;
	BEGIN NEW (o); o.b := TRUE; WITH o : O DO ASSERT (o.b); END;
	END Test.

positive: with statement with object

	MODULE Test;
	TYPE O0 = OBJECT END O0;
	TYPE O1 = OBJECT (O0) VAR b: BOOLEAN END O1;
	VAR o0: O0; o1: O1;
	BEGIN NEW (o1); o1.b := TRUE; o0 := o1; WITH o0 : O1 DO ASSERT (o0.b); END;
	END Test.

negative: unsatisfied with statement with object

	MODULE Test;
	TYPE O0 = OBJECT END O0;
	TYPE O1 = OBJECT (O0) END O1;
	VAR o0: O0;
	BEGIN NEW (o0); WITH o0 : O1 DO END;
	END Test.

negative: with statement with nil object

	MODULE Test;
	TYPE O0 = OBJECT END O0;
	TYPE O1 = OBJECT (O0) END O1;
	VAR o0: O0;
	BEGIN o0 := NIL; WITH o0 : O1 DO END;
	END Test.

positive: with statement with base object

	MODULE Test;
	TYPE O0 = OBJECT;
	TYPE O1 = OBJECT (O0) VAR b: BOOLEAN END O1;
	VAR o0: O0; o1: O1;
	BEGIN NEW (o1); o1.b := TRUE; o0 := o1; WITH o0 : O1 DO ASSERT (o0.b); END;
	END Test.

negative: with statement with nil base object

	MODULE Test;
	TYPE O0 = OBJECT;
	TYPE O1 = OBJECT (O0) END O1;
	VAR o0: O0;
	BEGIN o0 := NIL; WITH o0 : O1 DO END;
	END Test.


# nested procedures

positive: access to global variable within nested procedure

	MODULE Test;
	VAR g: INTEGER;
	PROCEDURE Procedure;
		PROCEDURE Nested; BEGIN g := 45; END Nested;
	BEGIN Nested;
	END Procedure;
	BEGIN g := 0; Procedure; ASSERT (g = 45);
	END Test.

positive: access to global variable within nested procedure called from nested procedure

	MODULE Test;
	VAR g: INTEGER;
	PROCEDURE Procedure;
		PROCEDURE Nested0; BEGIN Nested1; END Nested0;
		PROCEDURE Nested1; BEGIN g := 45; END Nested1;
	BEGIN Nested0;
	END Procedure;
	BEGIN g := 0; Procedure; ASSERT (g = 45);
	END Test.

positive: access to object variable within nested procedure

	MODULE Test;
	VAR o: OBJECT
	VAR f: INTEGER;
	PROCEDURE Procedure;
		PROCEDURE Nested; BEGIN f := 45; END Nested;
	BEGIN Nested;
	END Procedure;
	BEGIN f := 0; Procedure; ASSERT (f = 45); END;
	BEGIN NEW (o);
	END Test.

positive: access to object variable within nested procedure called from nested procedure

	MODULE Test;
	VAR o: OBJECT
	VAR f: INTEGER;
	PROCEDURE Procedure;
		PROCEDURE Nested0; BEGIN Nested1; END Nested0;
		PROCEDURE Nested1; BEGIN f := 45; END Nested1;
	BEGIN Nested0;
	END Procedure;
	BEGIN f := 0; Procedure; ASSERT (f = 45); END;
	BEGIN NEW (o);
	END Test.

positive: access to local variable within nested procedure

	MODULE Test;
	PROCEDURE Procedure;
	VAR l: INTEGER;
		PROCEDURE Nested; BEGIN l := 45; END Nested;
	BEGIN l := 0; Nested; ASSERT (l = 45);
	END Procedure;
	BEGIN Procedure;
	END Test.

positive: access to local variable within nested procedure called from nested procedure

	MODULE Test;
	PROCEDURE Procedure;
	VAR l: INTEGER;
		PROCEDURE Nested0; BEGIN Nested1; END Nested0;
		PROCEDURE Nested1; BEGIN l := 45; END Nested1;
	BEGIN l := 0; Nested0; ASSERT (l = 45);
	END Procedure;
	BEGIN Procedure;
	END Test.

positive: access to parameter within nested procedure

	MODULE Test;
	PROCEDURE Procedure (p: INTEGER);
		PROCEDURE Nested; BEGIN p := 45; END Nested;
	BEGIN Nested; ASSERT (p = 45);
	END Procedure;
	BEGIN Procedure (0);
	END Test.

positive: access to parameter within nested procedure called from nested procedure

	MODULE Test;
	PROCEDURE Procedure (p: INTEGER);
		PROCEDURE Nested0; BEGIN Nested1; END Nested0;
		PROCEDURE Nested1; BEGIN p := 45; END Nested1;
	BEGIN Nested0; ASSERT (p = 45);
	END Procedure;
	BEGIN Procedure (0);
	END Test.


# methods

positive: single method call

	MODULE Test;
	VAR object: OBJECT
		PROCEDURE Method; BEGIN ASSERT (i = 0); i := 1; END Method;
	END; i: INTEGER;
	BEGIN i := 0; NEW (object); object.Method; ASSERT (i = 1);
	END Test.

positive: single super call

	MODULE Test;
	TYPE Object0 = OBJECT
		PROCEDURE Method; BEGIN ASSERT (i = 1); i := 2; END Method;
	END Object0;
	TYPE Object1 = OBJECT (Object0)
		PROCEDURE Method; BEGIN ASSERT (i = 0); i := 1; Method^; END Method;
	END Object1;
	VAR object: Object1; i: INTEGER;
	BEGIN i := 0; NEW (object); object.Method; ASSERT (i = 2);
	END Test.

positive: double method call

	MODULE Test;
	VAR object: OBJECT
		PROCEDURE Method0; BEGIN ASSERT (i = 0); i := 1; Method1; END Method0;
		PROCEDURE Method1; BEGIN ASSERT (i = 1); i := 2; END Method1;
	END; i: INTEGER;
	BEGIN i := 0; NEW (object); object.Method0; ASSERT (i = 2);
	END Test.

positive: double super call

	MODULE Test;
	TYPE Object0 = OBJECT
		PROCEDURE Method0; BEGIN ASSERT (i = 1); i := 2; Method1; END Method0;
		PROCEDURE Method1; BEGIN ASSERT (i = 3); i := 4; END Method1;
	END Object0;
	TYPE Object1 = OBJECT (Object0)
		PROCEDURE Method0; BEGIN ASSERT (i = 0); i := 1; Method0^; END Method0;
		PROCEDURE Method1; BEGIN ASSERT (i = 2); i := 3; Method1^; END Method1;
	END Object1;
	VAR object: Object1; i: INTEGER;
	BEGIN i := 0; NEW (object); object.Method0; ASSERT (i = 4);
	END Test.

positive: single method call with initializer

	MODULE Test;
	VAR object: OBJECT VAR i: INTEGER;
		PROCEDURE &Init (i: INTEGER); BEGIN SELF.i := i; END Init;
		PROCEDURE Method; BEGIN ASSERT (i = 0); i := 1; END Method;
	END;
	BEGIN NEW (object, 0); object.Method; ASSERT (object.i = 1);
	END Test.

positive: single super call with initializer

	MODULE Test;
	TYPE Object0 = OBJECT VAR i: INTEGER;
		PROCEDURE &Init (i: INTEGER); BEGIN SELF.i := i; END Init;
		PROCEDURE Method; BEGIN ASSERT (i = 1); i := 2; END Method;
	END Object0;
	TYPE Object1 = OBJECT (Object0)
		PROCEDURE &Init (i: INTEGER); BEGIN Init^ (i); END Init;
		PROCEDURE Method; BEGIN ASSERT (i = 0); i := 1; Method^; END Method;
	END Object1;
	VAR object: Object1;
	BEGIN NEW (object, 0); object.Method; ASSERT (object.i = 2);
	END Test.

positive: double method call with initializer

	MODULE Test;
	VAR object: OBJECT VAR i: INTEGER;
		PROCEDURE &Init (i: INTEGER); BEGIN SELF.i := i; END Init;
		PROCEDURE Method0; BEGIN ASSERT (i = 0); i := 1; Method1; END Method0;
		PROCEDURE Method1; BEGIN ASSERT (i = 1); i := 2; END Method1;
	END;
	BEGIN NEW (object, 0); object.Method0; ASSERT (object.i = 2);
	END Test.

positive: double super call with initializer

	MODULE Test;
	TYPE Object0 = OBJECT VAR i: INTEGER;
		PROCEDURE &Init (i: INTEGER); BEGIN SELF.i := i; END Init;
		PROCEDURE Method0; BEGIN ASSERT (i = 1); i := 2; Method1; END Method0;
		PROCEDURE Method1; BEGIN ASSERT (i = 3); i := 4; END Method1;
	END Object0;
	TYPE Object1 = OBJECT (Object0)
		PROCEDURE &Init (i: INTEGER); BEGIN Init^ (i); END Init;
		PROCEDURE Method0; BEGIN ASSERT (i = 0); i := 1; Method0^; END Method0;
		PROCEDURE Method1; BEGIN ASSERT (i = 2); i := 3; Method1^; END Method1;
	END Object1;
	VAR object: Object1;
	BEGIN NEW (object, 0); object.Method0; ASSERT (object.i = 4);
	END Test.

positive: single method call with initializer and body

	MODULE Test;
	VAR object: OBJECT VAR i: INTEGER;
		PROCEDURE &Init (i: INTEGER); BEGIN SELF.i := i; END Init;
		PROCEDURE Method; BEGIN ASSERT (i = 1); i := 2; END Method;
		BEGIN ASSERT (i = 0); i := 1;
	END;
	BEGIN NEW (object, 0); object.Method; ASSERT (object.i = 2);
	END Test.

positive: single super call with initializer and body

	MODULE Test;
	TYPE Object0 = OBJECT VAR i: INTEGER;
		PROCEDURE &Init (i: INTEGER); BEGIN SELF.i := i; END Init;
		PROCEDURE Method; BEGIN ASSERT (i = 3); i := 4; END Method;
		BEGIN ASSERT (i = 0); i := 1;
	END Object0;
	TYPE Object1 = OBJECT (Object0)
		PROCEDURE &Init (i: INTEGER); BEGIN Init^ (i); END Init;
		PROCEDURE Method; BEGIN ASSERT (i = 2); i := 3; Method^; END Method;
		BEGIN ASSERT (i = 1); i := 2;
	END Object1;
	VAR object: Object1;
	BEGIN NEW (object, 0); object.Method; ASSERT (object.i = 4);
	END Test.

positive: double method call with initializer and body

	MODULE Test;
	VAR object: OBJECT VAR i: INTEGER;
		PROCEDURE &Init (i: INTEGER); BEGIN SELF.i := i; END Init;
		PROCEDURE Method0; BEGIN ASSERT (i = 1); i := 2; Method1; END Method0;
		PROCEDURE Method1; BEGIN ASSERT (i = 2); i := 3; END Method1;
		BEGIN ASSERT (i = 0); i := 1;
	END;
	BEGIN NEW (object, 0); object.Method0; ASSERT (object.i = 3);
	END Test.

positive: double super call with initializer and body

	MODULE Test;
	TYPE Object0 = OBJECT VAR i: INTEGER;
		PROCEDURE &Init (i: INTEGER); BEGIN SELF.i := i; END Init;
		PROCEDURE Method0; BEGIN ASSERT (i = 3); i := 4; Method1; END Method0;
		PROCEDURE Method1; BEGIN ASSERT (i = 5); i := 6; END Method1;
		BEGIN ASSERT (i = 0); i := 1;
	END Object0;
	TYPE Object1 = OBJECT (Object0)
		PROCEDURE &Init (i: INTEGER); BEGIN Init^ (i); END Init;
		PROCEDURE Method0; BEGIN ASSERT (i = 2); i := 3; Method0^; END Method0;
		PROCEDURE Method1; BEGIN ASSERT (i = 4); i := 5; Method1^; END Method1;
		BEGIN ASSERT (i = 1); i := 2;
	END Object1;
	VAR object: Object1;
	BEGIN NEW (object, 0); object.Method0; ASSERT (object.i = 6);
	END Test.

positive: call of object body

	MODULE Test;
	VAR o: OBJECT BEGIN b := TRUE END;
	VAR b: BOOLEAN;
	BEGIN b := FALSE; NEW(o); ASSERT(b);
	END Test.

positive: call of object body chains

	MODULE Test;
	TYPE
		O = OBJECT	BEGIN b1 := TRUE END O;
		O2=OBJECT(O) BEGIN b2 := b1 END O2;
		O3=OBJECT(O2) BEGIN b3 := b2 END O3;

	VAR b1,b2,b3: BOOLEAN; o: O3;
	BEGIN
		b1 := FALSE; b2 := FALSE; b3 := FALSE;
		NEW(o);
		ASSERT(b1); ASSERT(b2);  ASSERT(b3);
	END Test.

positive: call of object body chains with initializer

	MODULE Test;
	TYPE
		O = OBJECT	BEGIN b1 := b0 END O;
		O2=OBJECT(O) BEGIN b2 := b1 END O2;
		O3=OBJECT(O2) PROCEDURE &Init; BEGIN b0 := TRUE END Init; BEGIN b3 := b2 END O3;

	VAR b0,b1,b2,b3: BOOLEAN; o: O3;
	BEGIN
		b0 := FALSE; b1 := FALSE; b2 := FALSE; b3 := FALSE;
		NEW(o);
		ASSERT(b0); ASSERT(b1); ASSERT(b2);  ASSERT(b3);
	END Test.



# copy statement

positive: copy statement on array of character

	MODULE Test;
	VAR source, dest: ARRAY 20 OF CHAR;
	BEGIN source := "source"; COPY (source, dest); ASSERT (dest = "source");
	END Test.

positive: copy statement on array of character and longer array of character

	MODULE Test;
	VAR source: ARRAY 20 OF CHAR; dest: ARRAY 30 OF CHAR;
	BEGIN source := "source"; COPY (source, dest); ASSERT (dest = "source");
	END Test.

positive: copy statement on array of character and shorter array of character

	MODULE Test;
	VAR source: ARRAY 30 OF CHAR; dest: ARRAY 20 OF CHAR;
	BEGIN source := "source"; COPY (source, dest); ASSERT (dest = "source");
	END Test.

positive: copy statement on string and longer array of character

	MODULE Test;
	CONST Source = "source";
	VAR dest: ARRAY 20 OF CHAR;
	BEGIN COPY (Source, dest); ASSERT (dest = Source);
	END Test.

positive: copy statement with array of character parameter as source

	MODULE Test;
	PROCEDURE Procedure (source: ARRAY 20 OF CHAR);
	VAR dest: ARRAY 20 OF CHAR;
	BEGIN COPY (source, dest); ASSERT (dest = "source");
	END Procedure;
	BEGIN Procedure ("source");
	END Test.

positive: copy statement with variable array of character parameter as source

	MODULE Test;
	VAR source: ARRAY 20 OF CHAR;
	PROCEDURE Procedure (VAR source: ARRAY 20 OF CHAR);
	VAR dest: ARRAY 20 OF CHAR;
	BEGIN COPY (source, dest); ASSERT (dest = "source");
	END Procedure;
	BEGIN source := "source"; Procedure (source);
	END Test.

positive: copy statement with constant array of character parameter as source

	MODULE Test;
	PROCEDURE Procedure (CONST source: ARRAY 20 OF CHAR);
	VAR dest: ARRAY 20 OF CHAR;
	BEGIN COPY (source, dest); ASSERT (dest = "source");
	END Procedure;
	BEGIN Procedure ("source");
	END Test.

positive: copy statement with open array of character parameter as source

	MODULE Test;
	PROCEDURE Procedure (source: ARRAY OF CHAR);
	VAR dest: ARRAY 20 OF CHAR;
	BEGIN COPY (source, dest); ASSERT (dest = "source");
	END Procedure;
	BEGIN Procedure ("source");
	END Test.

negative: copy statement with too long open array of character parameter as source

	MODULE Test;
	PROCEDURE Procedure (source: ARRAY OF CHAR);
	VAR dest: ARRAY 2 OF CHAR;
	BEGIN COPY (source, dest);
	END Procedure;
	BEGIN Procedure ("source");
	END Test.

positive: copy statement with open variable array of character parameter as source

	MODULE Test;
	VAR source: ARRAY 20 OF CHAR;
	PROCEDURE Procedure (VAR source: ARRAY OF CHAR);
	VAR dest: ARRAY 20 OF CHAR;
	BEGIN COPY (source, dest); ASSERT (dest = "source");
	END Procedure;
	BEGIN source := "source"; Procedure (source);
	END Test.

negative: copy statement with too long open variable array of character parameter as source

	MODULE Test;
	VAR source: ARRAY 20 OF CHAR;
	PROCEDURE Procedure (VAR source: ARRAY OF CHAR);
	VAR dest: ARRAY 2 OF CHAR;
	BEGIN COPY (source, dest);
	END Procedure;
	BEGIN source := "source"; Procedure (source);
	END Test.

positive: copy statement with open constant array of character parameter as source

	MODULE Test;
	PROCEDURE Procedure (CONST source: ARRAY OF CHAR);
	VAR dest: ARRAY 20 OF CHAR;
	BEGIN COPY (source, dest); ASSERT (dest = "source");
	END Procedure;
	BEGIN Procedure ("source");
	END Test.

negative: copy statement with too long open constant array of character parameter as source

	MODULE Test;
	PROCEDURE Procedure (CONST source: ARRAY OF CHAR);
	VAR dest: ARRAY 2 OF CHAR;
	BEGIN COPY (source, dest);
	END Procedure;
	BEGIN Procedure ("source");
	END Test.

positive: copy statement with array of character parameter as destination

	MODULE Test;
	PROCEDURE Procedure (dest: ARRAY 20 OF CHAR);
	VAR source: ARRAY 20 OF CHAR;
	BEGIN source := "source"; COPY (source, dest); ASSERT (dest = "source");
	END Procedure;
	BEGIN Procedure ("destination");
	END Test.

positive: copy statement with variable array of character parameter as destination

	MODULE Test;
	VAR dest: ARRAY 20 OF CHAR;
	PROCEDURE Procedure (VAR dest: ARRAY 20 OF CHAR);
	VAR source: ARRAY 20 OF CHAR;
	BEGIN source := "source"; COPY (source, dest);
	END Procedure;
	BEGIN Procedure (dest); ASSERT (dest = "source");
	END Test.

positive: copy statement with open array of character parameter as destination

	MODULE Test;
	PROCEDURE Procedure (dest: ARRAY OF CHAR);
	VAR source: ARRAY 20 OF CHAR;
	BEGIN source := "source"; COPY (source, dest); ASSERT (dest = "source");
	END Procedure;
	BEGIN Procedure ("destination");
	END Test.

negative: copy statement with too short open array of character parameter as destination

	MODULE Test;
	PROCEDURE Procedure (dest: ARRAY OF CHAR);
	VAR source: ARRAY 20 OF CHAR;
	BEGIN source := "source"; COPY (source, dest);
	END Procedure;
	BEGIN Procedure ("");
	END Test.

positive: copy statement with open variable array of character parameter as destination

	MODULE Test;
	VAR dest: ARRAY 20 OF CHAR;
	PROCEDURE Procedure (VAR dest: ARRAY OF CHAR);
	VAR source: ARRAY 20 OF CHAR;
	BEGIN source := "source"; COPY (source, dest);
	END Procedure;
	BEGIN Procedure (dest); ASSERT (dest = "source");
	END Test.

negative: copy statement with too short open variable array of character parameter as destination

	MODULE Test;
	VAR dest: ARRAY 2 OF CHAR;
	PROCEDURE Procedure (VAR dest: ARRAY OF CHAR);
	VAR source: ARRAY 20 OF CHAR;
	BEGIN source := "source"; COPY (source, dest);
	END Procedure;
	BEGIN Procedure (dest);
	END Test.

positive: copy statement with string as source and array of character parameter as destination

	MODULE Test;
	CONST Source = "source";
	PROCEDURE Procedure (dest: ARRAY 20 OF CHAR);
	BEGIN COPY (Source, dest); ASSERT (dest = Source);
	END Procedure;
	BEGIN Procedure ("destination");
	END Test.

positive: copy statement with string as source and variable array of character parameter as destination

	MODULE Test;
	CONST Source = "source";
	VAR dest: ARRAY 20 OF CHAR;
	PROCEDURE Procedure (VAR dest: ARRAY 20 OF CHAR);
	BEGIN COPY (Source, dest);
	END Procedure;
	BEGIN Procedure (dest); ASSERT (dest = Source);
	END Test.

positive: copy statement with string as source and open array of character parameter as destination

	MODULE Test;
	CONST Source = "source";
	PROCEDURE Procedure (dest: ARRAY OF CHAR);
	BEGIN COPY (Source, dest); ASSERT (dest = Source);
	END Procedure;
	BEGIN Procedure ("destination");
	END Test.

negative: copy statement with string as source and too short open array of character parameter as destination

	MODULE Test;
	CONST Source = "source";
	PROCEDURE Procedure (dest: ARRAY OF CHAR);
	BEGIN COPY (Source, dest); ASSERT (dest = Source);
	END Procedure;
	BEGIN Procedure ("");
	END Test.

positive: copy statement with string as source and open variable array of character parameter as destination

	MODULE Test;
	CONST Source = "source";
	VAR dest: ARRAY 20 OF CHAR;
	PROCEDURE Procedure (VAR dest: ARRAY OF CHAR);
	BEGIN COPY (Source, dest);
	END Procedure;
	BEGIN Procedure (dest); ASSERT (dest = Source);
	END Test.

negative: copy statement with string as source and too short open variable array of character parameter as destination

	MODULE Test;
	CONST Source = "source";
	VAR dest: ARRAY 2 OF CHAR;
	PROCEDURE Procedure (VAR dest: ARRAY OF CHAR);
	BEGIN COPY (Source, dest);
	END Procedure;
	BEGIN Procedure (dest);
	END Test.


# string assignment

positive: string assignment on array of character

	MODULE Test;
	CONST Source = "source";
	VAR dest: ARRAY 20 OF CHAR;
	BEGIN dest := Source; ASSERT (dest = Source);
	END Test.

positive: string assignment on array of character parameter

	MODULE Test;
	CONST Source = "source";
	PROCEDURE Procedure (dest: ARRAY 20 OF CHAR);
	BEGIN dest := Source; ASSERT (dest = Source);
	END Procedure;
	BEGIN Procedure ("destination");
	END Test.

positive: string assignment on variable array of character parameter

	MODULE Test;
	CONST Source = "source";
	VAR dest: ARRAY 20 OF CHAR;
	PROCEDURE Procedure (VAR dest: ARRAY 20 OF CHAR);
	BEGIN dest := Source;
	END Procedure;
	BEGIN Procedure (dest); ASSERT (dest = Source);
	END Test.

positive: string assignment on open array of character parameter

	MODULE Test;
	CONST Source = "source";
	PROCEDURE Procedure (dest: ARRAY OF CHAR);
	BEGIN dest := Source; ASSERT (dest = Source);
	END Procedure;
	BEGIN Procedure ("destination");
	END Test.

negative: string assignment on too short open array of character parameter

	MODULE Test;
	CONST Source = "source";
	PROCEDURE Procedure (dest: ARRAY OF CHAR);
	BEGIN dest := Source; ASSERT (dest = Source);
	END Procedure;
	BEGIN Procedure ("");
	END Test.

positive: string assignment on open variable array of character parameter

	MODULE Test;
	CONST Source = "source";
	VAR dest: ARRAY 20 OF CHAR;
	PROCEDURE Procedure (VAR dest: ARRAY OF CHAR);
	BEGIN dest := Source;
	END Procedure;
	BEGIN Procedure (dest); ASSERT (dest = Source);
	END Test.

negative: string assignment on too short open variable array of character parameter

	MODULE Test;
	CONST Source = "source";
	VAR dest: ARRAY 2 OF CHAR;
	PROCEDURE Procedure (VAR dest: ARRAY OF CHAR);
	BEGIN dest := Source;
	END Procedure;
	BEGIN Procedure (dest);
	END Test.


# increment statement

positive: increment statement with short integers

	MODULE Test;
	VAR a, b, c: SHORTINT;
	BEGIN a := 0; b := 3; c := -4;
		INC (a); ASSERT (a = 1); DEC (a); ASSERT (a = 0);
		INC (a, 2); ASSERT (a = 2); INC (a, -2); ASSERT (a = 0);
		INC (a, b); ASSERT (a = b); INC (a, -b); ASSERT (a = 0);
		INC (a, c); ASSERT (a = c); INC (a, -c); ASSERT (a = 0);
	END Test.

positive: increment statement with integers

	MODULE Test;
	VAR a, b: INTEGER; c: SHORTINT;
	BEGIN a := 0; b := 3; c := -4;
		INC (a); ASSERT (a = 1); DEC (a); ASSERT (a = 0);
		INC (a, 2); ASSERT (a = 2); INC (a, -2); ASSERT (a = 0);
		INC (a, b); ASSERT (a = b); INC (a, -b); ASSERT (a = 0);
		INC (a, c); ASSERT (a = c); INC (a, -c); ASSERT (a = 0);
	END Test.

positive: increment statement with long integers

	MODULE Test;
	VAR a, b: LONGINT; c: INTEGER; d: SHORTINT;
	BEGIN a := 0; b := 3; c := -4; d := 5;
		INC (a); ASSERT (a = 1); DEC (a); ASSERT (a = 0);
		INC (a, 2); ASSERT (a = 2); INC (a, -2); ASSERT (a = 0);
		INC (a, b); ASSERT (a = b); INC (a, -b); ASSERT (a = 0);
		INC (a, c); ASSERT (a = c); INC (a, -c); ASSERT (a = 0);
		INC (a, d); ASSERT (a = d); INC (a, -d); ASSERT (a = 0);
	END Test.

positive: increment statement with huge integers

	MODULE Test;
	VAR a, b: HUGEINT; c: LONGINT; d: INTEGER; e: SHORTINT;
	BEGIN a := 0; b := 3; c := -4; d := 5; e := -6;
		INC (a); ASSERT (a = 1); DEC (a); ASSERT (a = 0);
		INC (a, 2); ASSERT (a = 2); INC (a, -2); ASSERT (a = 0);
		INC (a, b); ASSERT (a = b); INC (a, -b); ASSERT (a = 0);
		INC (a, c); ASSERT (a = c); INC (a, -c); ASSERT (a = 0);
		INC (a, d); ASSERT (a = d); INC (a, -d); ASSERT (a = 0);
		INC (a, e); ASSERT (a = e); INC (a, -e); ASSERT (a = 0);
	END Test.


# decrement statement

positive: decrement statement with short integers

	MODULE Test;
	VAR a, b, c: SHORTINT;
	BEGIN a := 0; b := 3; c := -4;
		DEC (a); ASSERT (a = -1); INC (a); ASSERT (a = 0);
		DEC (a, 2); ASSERT (a = -2); DEC (a, -2); ASSERT (a = 0);
		DEC (a, b); ASSERT (a = -b); DEC (a, -b); ASSERT (a = 0);
		DEC (a, c); ASSERT (a = -c); DEC (a, -c); ASSERT (a = 0);
	END Test.

positive: decrement statement with integers

	MODULE Test;
	VAR a, b: INTEGER; c: SHORTINT;
	BEGIN a := 0; b := 3; c := -4;
		DEC (a); ASSERT (a = -1); INC (a); ASSERT (a = 0);
		DEC (a, 2); ASSERT (a = -2); DEC (a, -2); ASSERT (a = 0);
		DEC (a, b); ASSERT (a = -b); DEC (a, -b); ASSERT (a = 0);
		DEC (a, c); ASSERT (a = -c); DEC (a, -c); ASSERT (a = 0);
	END Test.

positive: decrement statement with long integers

	MODULE Test;
	VAR a, b: LONGINT; c: INTEGER; d: SHORTINT;
	BEGIN a := 0; b := 3; c := -4; d := 5;
		DEC (a); ASSERT (a = -1); INC (a); ASSERT (a = 0);
		DEC (a, 2); ASSERT (a = -2); DEC (a, -2); ASSERT (a = 0);
		DEC (a, b); ASSERT (a = -b); DEC (a, -b); ASSERT (a = 0);
		DEC (a, c); ASSERT (a = -c); DEC (a, -c); ASSERT (a = 0);
		DEC (a, d); ASSERT (a = -d); DEC (a, -d); ASSERT (a = 0);
	END Test.

positive: decrement statement with huge integers

	MODULE Test;
	VAR a, b: HUGEINT; c: LONGINT; d: INTEGER; e: SHORTINT;
	BEGIN a := 0; b := 3; c := -4; d := 5; e := -6;
		DEC (a); ASSERT (a = -1); INC (a); ASSERT (a = 0);
		DEC (a, 2); ASSERT (a = -2); DEC (a, -2); ASSERT (a = 0);
		DEC (a, b); ASSERT (a = -b); DEC (a, -b); ASSERT (a = 0);
		DEC (a, c); ASSERT (a = -c); DEC (a, -c); ASSERT (a = 0);
		DEC (a, d); ASSERT (a = -d); DEC (a, -d); ASSERT (a = 0);
		DEC (a, e); ASSERT (a = -e); DEC (a, -e); ASSERT (a = 0);
	END Test.


# include statement

positive: include statement with short integer as set element

	MODULE Test;
	VAR set: SET; element: SHORTINT;
	BEGIN
		set := {}; element := MIN (SET); INCL (set, element); ASSERT (set = {element}); ASSERT (set = {MIN (SET)}); ASSERT (element IN set);
		set := {}; element := MAX (SET); INCL (set, element); ASSERT (set = {element}); ASSERT (set = {MAX (SET)}); ASSERT (element IN set);
		element := MIN (SET); set := {element}; INCL (set, element); ASSERT (set = {element}); ASSERT (set = {MIN (SET)}); ASSERT (element IN set);
		element := MAX (SET); set := {element}; INCL (set, element); ASSERT (set = {element}); ASSERT (set = {MAX (SET)}); ASSERT (element IN set);
	END Test.

negative: include statement with too small short integer as set element

	MODULE Test;
	VAR set: SET; element: SHORTINT;
	BEGIN set := {}; element := MIN (SET) - 1; INCL (set, element);
	END Test.

negative: include statement with too large short integer as set element

	MODULE Test;
	VAR set: SET; element: SHORTINT;
	BEGIN set := {}; element := MAX (SET) + 1; INCL (set, element);
	END Test.

positive: include statement with integer as set element

	MODULE Test;
	VAR set: SET; element: INTEGER;
	BEGIN
		set := {}; element := MIN (SET); INCL (set, element); ASSERT (set = {element}); ASSERT (set = {MIN (SET)}); ASSERT (element IN set);
		set := {}; element := MAX (SET); INCL (set, element); ASSERT (set = {element}); ASSERT (set = {MAX (SET)}); ASSERT (element IN set);
		element := MIN (SET); set := {element}; INCL (set, element); ASSERT (set = {element}); ASSERT (set = {MIN (SET)}); ASSERT (element IN set);
		element := MAX (SET); set := {element}; INCL (set, element); ASSERT (set = {element}); ASSERT (set = {MAX (SET)}); ASSERT (element IN set);
	END Test.

negative: include statement with too small integer as set element

	MODULE Test;
	VAR set: SET; element: INTEGER;
	BEGIN set := {}; element := MIN (SET) - 1; INCL (set, element);
	END Test.

negative: include statement with too large integer as set element

	MODULE Test;
	VAR set: SET; element: INTEGER;
	BEGIN set := {}; element := MAX (SET) + 1; INCL (set, element);
	END Test.

positive: include statement with long integer as set element

	MODULE Test;
	VAR set: SET; element: LONGINT;
	BEGIN
		set := {}; element := MIN (SET); INCL (set, element); ASSERT (set = {element}); ASSERT (set = {MIN (SET)}); ASSERT (element IN set);
		set := {}; element := MAX (SET); INCL (set, element); ASSERT (set = {element}); ASSERT (set = {MAX (SET)}); ASSERT (element IN set);
		element := MIN (SET); set := {element}; INCL (set, element); ASSERT (set = {element}); ASSERT (set = {MIN (SET)}); ASSERT (element IN set);
		element := MAX (SET); set := {element}; INCL (set, element); ASSERT (set = {element}); ASSERT (set = {MAX (SET)}); ASSERT (element IN set);
	END Test.

negative: include statement with too small long integer as set element

	MODULE Test;
	VAR set: SET; element: LONGINT;
	BEGIN set := {}; element := MIN (SET) - 1; INCL (set, element);
	END Test.

negative: include statement with too large long integer as set element

	MODULE Test;
	VAR set: SET; element: LONGINT;
	BEGIN set := {}; element := MAX (SET) + 1; INCL (set, element);
	END Test.

positive: include statement with huge integer as set element

	MODULE Test;
	VAR set: SET; element: HUGEINT;
	BEGIN
		set := {}; element := MIN (SET); INCL (set, element); ASSERT (set = {element}); ASSERT (set = {MIN (SET)}); ASSERT (element IN set);
		set := {}; element := MAX (SET); INCL (set, element); ASSERT (set = {element}); ASSERT (set = {MAX (SET)}); ASSERT (element IN set);
		element := MIN (SET); set := {element}; INCL (set, element); ASSERT (set = {element}); ASSERT (set = {MIN (SET)}); ASSERT (element IN set);
		element := MAX (SET); set := {element}; INCL (set, element); ASSERT (set = {element}); ASSERT (set = {MAX (SET)}); ASSERT (element IN set);
	END Test.

negative: include statement with too small huge integer as set element

	MODULE Test;
	VAR set: SET; element: HUGEINT;
	BEGIN set := {}; element := MIN (SET) - 1; INCL (set, element);
	END Test.

negative: include statement with too large huge integer as set element

	MODULE Test;
	VAR set: SET; element: HUGEINT;
	BEGIN set := {}; element := MAX (SET) + 1; INCL (set, element);
	END Test.


# exclude statement

positive: exclude statement with short integer as set element

	MODULE Test;
	VAR set: SET; element: SHORTINT;
	BEGIN
		set := {}; element := MIN (SET); EXCL (set, element); ASSERT (set = {}); ASSERT (~(element IN set));
		set := {}; element := MAX (SET); EXCL (set, element); ASSERT (set = {}); ASSERT (~(element IN set));
		element := MIN (SET); set := {element}; EXCL (set, element); ASSERT (set = {}); ASSERT (~(element IN set));
		element := MAX (SET); set := {element}; EXCL (set, element); ASSERT (set = {}); ASSERT (~(element IN set));
	END Test.

negative: exclude statement with too small short integer as set element

	MODULE Test;
	VAR set: SET; element: SHORTINT;
	BEGIN set := {}; element := MIN (SET) - 1; EXCL (set, element);
	END Test.

negative: exclude statement with too large short integer as set element

	MODULE Test;
	VAR set: SET; element: SHORTINT;
	BEGIN set := {}; element := MAX (SET) + 1; EXCL (set, element);
	END Test.

positive: exclude statement with integer as set element

	MODULE Test;
	VAR set: SET; element: INTEGER;
	BEGIN
		set := {}; element := MIN (SET); EXCL (set, element); ASSERT (set = {}); ASSERT (~(element IN set));
		set := {}; element := MAX (SET); EXCL (set, element); ASSERT (set = {}); ASSERT (~(element IN set));
		element := MIN (SET); set := {element}; EXCL (set, element); ASSERT (set = {}); ASSERT (~(element IN set));
		element := MAX (SET); set := {element}; EXCL (set, element); ASSERT (set = {}); ASSERT (~(element IN set));
	END Test.

negative: exclude statement with too small integer as set element

	MODULE Test;
	VAR set: SET; element: INTEGER;
	BEGIN set := {}; element := MIN (SET) - 1; EXCL (set, element);
	END Test.

negative: exclude statement with too large integer as set element

	MODULE Test;
	VAR set: SET; element: INTEGER;
	BEGIN set := {}; element := MAX (SET) + 1; EXCL (set, element);
	END Test.

positive: exclude statement with long integer as set element

	MODULE Test;
	VAR set: SET; element: LONGINT;
	BEGIN
		set := {}; element := MIN (SET); EXCL (set, element); ASSERT (set = {}); ASSERT (~(element IN set));
		set := {}; element := MAX (SET); EXCL (set, element); ASSERT (set = {}); ASSERT (~(element IN set));
		element := MIN (SET); set := {element}; EXCL (set, element); ASSERT (set = {}); ASSERT (~(element IN set));
		element := MAX (SET); set := {element}; EXCL (set, element); ASSERT (set = {}); ASSERT (~(element IN set));
	END Test.

negative: exclude statement with too small long integer as set element

	MODULE Test;
	VAR set: SET; element: LONGINT;
	BEGIN set := {}; element := MIN (SET) - 1; EXCL (set, element);
	END Test.

negative: exclude statement with too large long integer as set element

	MODULE Test;
	VAR set: SET; element: LONGINT;
	BEGIN set := {}; element := MAX (SET) + 1; EXCL (set, element);
	END Test.

positive: exclude statement with huge integer as set element

	MODULE Test;
	VAR set: SET; element: HUGEINT;
	BEGIN
		set := {}; element := MIN (SET); EXCL (set, element); ASSERT (set = {}); ASSERT (~(element IN set));
		set := {}; element := MAX (SET); EXCL (set, element); ASSERT (set = {}); ASSERT (~(element IN set));
		element := MIN (SET); set := {element}; EXCL (set, element); ASSERT (set = {}); ASSERT (~(element IN set));
		element := MAX (SET); set := {element}; EXCL (set, element); ASSERT (set = {}); ASSERT (~(element IN set));
	END Test.

negative: exclude statement with too small huge integer as set element

	MODULE Test;
	VAR set: SET; element: HUGEINT;
	BEGIN set := {}; element := MIN (SET) - 1; EXCL (set, element);
	END Test.

negative: exclude statement with too large huge integer as set element

	MODULE Test;
	VAR set: SET; element: HUGEINT;
	BEGIN set := {}; element := MAX (SET) + 1; EXCL (set, element);
	END Test.


# await statement

positive: await statement in exclusive block

	MODULE Test;
	VAR condition: BOOLEAN;
	PROCEDURE Await; BEGIN AWAIT (condition) END Await;
	BEGIN {EXCLUSIVE} condition := TRUE; Await;
	END Test.

negative: await statement in non-exclusive block

	MODULE Test;
	VAR condition: BOOLEAN;
	PROCEDURE Await; BEGIN AWAIT (condition) END Await;
	BEGIN condition := FALSE; Await;
	END Test.


# procedure variables

positive: calling global procedure variable

	MODULE Test;
	VAR p: PROCEDURE (VAR x: INTEGER); i: INTEGER;
	PROCEDURE P (VAR x: INTEGER); BEGIN x := 4; END P;
	BEGIN i := 2; p := P; p (i); ASSERT (i = 4);
	END Test.

negative: calling global nil procedure variable

	MODULE Test;
	VAR p: PROCEDURE;
	BEGIN p := NIL; p;
	END Test.

positive: calling global procedure variable in array

	MODULE Test;
	VAR p: ARRAY 10 OF PROCEDURE (VAR x: INTEGER); i: INTEGER;
	PROCEDURE P (VAR x: INTEGER); BEGIN x := 4; END P;
	BEGIN i := 2; p[i] := P; p[i](i); ASSERT (i = 4);
	END Test.

negative: calling global nil procedure variable in array

	MODULE Test;
	VAR p: ARRAY 10 OF PROCEDURE; i: INTEGER;
	BEGIN i := 2; p[i] := NIL; p[i];
	END Test.

positive: calling local procedure variable

	MODULE Test;
	PROCEDURE P (VAR x: INTEGER); BEGIN x := 4; END P;
	PROCEDURE Procedure;
	VAR p: PROCEDURE (VAR x: INTEGER); i: INTEGER;
	BEGIN i := 2; p := P; p (i); ASSERT (i = 4);
	END Procedure;
	BEGIN Procedure;
	END Test.

negative: calling local nil procedure variable

	MODULE Test;
	PROCEDURE Procedure;
	VAR p: PROCEDURE;
	BEGIN p := NIL; p;
	END Procedure;
	BEGIN Procedure;
	END Test.

positive: calling local procedure variable in array

	MODULE Test;
	PROCEDURE P (VAR x: INTEGER); BEGIN x := 4; END P;
	PROCEDURE Procedure;
	VAR p: ARRAY 10 OF PROCEDURE (VAR x: INTEGER); i: INTEGER;
	BEGIN i := 2; p[i] := P; p[i](i); ASSERT (i = 4);
	END Procedure;
	BEGIN Procedure;
	END Test.

negative: calling local nil procedure variable in array

	MODULE Test;
	PROCEDURE Procedure;
	VAR p: ARRAY 10 OF PROCEDURE; i: INTEGER;
	BEGIN i := 2; p[i] := NIL; p[i];
	END Procedure;
	BEGIN Procedure;
	END Test.

positive: calling parameter procedure variable

	MODULE Test;
	PROCEDURE P (VAR x: INTEGER); BEGIN x := 4; END P;
	PROCEDURE Procedure (p: PROCEDURE (VAR x: INTEGER));
	VAR i: INTEGER;
	BEGIN i := 2; p := P; p (i); ASSERT (i = 4);
	END Procedure;
	BEGIN Procedure (P);
	END Test.

negative: calling parameter nil procedure variable

	MODULE Test;
	PROCEDURE Procedure (p: PROCEDURE);
	BEGIN p;
	END Procedure;
	BEGIN Procedure (NIL);
	END Test.

positive: calling variable parameter procedure variable

	MODULE Test;
	VAR p: PROCEDURE (VAR x: INTEGER);
	PROCEDURE P (VAR x: INTEGER); BEGIN x := 4; END P;
	PROCEDURE Procedure (VAR p: PROCEDURE (VAR x: INTEGER));
	VAR i: INTEGER;
	BEGIN i := 2; p := P; p (i); ASSERT (i = 4);
	END Procedure;
	BEGIN p := P; Procedure (p);
	END Test.

negative: calling variable parameter nil procedure variable

	MODULE Test;
	VAR p: PROCEDURE;
	PROCEDURE Procedure (VAR p: PROCEDURE);
	BEGIN p;
	END Procedure;
	BEGIN p := NIL; Procedure (p);
	END Test.

positive: calling parameter procedure variable of object

	MODULE Test;
	VAR i: INTEGER; o: OBJECT
		VAR p: PROCEDURE (VAR x: INTEGER);
	END;
	PROCEDURE P (VAR x: INTEGER); BEGIN x := 4; END P;
	BEGIN i := 2; NEW (o); o.p := P; o.p (i); ASSERT (i = 4);
	END Test.

negative: calling parameter nil procedure variable of object

	MODULE Test;
	VAR o: OBJECT
		VAR p: PROCEDURE;
	END;
	BEGIN NEW (o); o.p := NIL; o.p;
	END Test.

positive: calling parameter procedure variable within object

	MODULE Test;
	VAR o: OBJECT
		VAR p: PROCEDURE (VAR x: INTEGER);
		PROCEDURE &Procedure;
		VAR i: INTEGER;
		BEGIN i := 2; p := P; p (i); ASSERT (i = 4);
		END Procedure;
	END;
	PROCEDURE P (VAR x: INTEGER); BEGIN x := 4; END P;
	BEGIN NEW (o);
	END Test.

negative: calling parameter nil procedure variable within object

	MODULE Test;
	VAR o: OBJECT
		VAR p: PROCEDURE;
		PROCEDURE &Procedure;
		BEGIN p := NIL; p;
		END Procedure;
	END;
	BEGIN NEW (o);
	END Test.


# concurrency

positive: exclusive section in procedure in module scope
	MODULE Test;
	PROCEDURE P;
	BEGIN{EXCLUSIVE}
	END P;
	BEGIN P END Test.

positive: exclusive section in procedure in object scope

	MODULE Test;
	VAR a: OBJECT
		PROCEDURE P;
		BEGIN{EXCLUSIVE}
		END P;
	END;
	BEGIN NEW(a); a.P END Test.


positive: positive await statement in procedure in module scope
	MODULE Test;
	VAR done: BOOLEAN;
	PROCEDURE P;
	BEGIN{EXCLUSIVE}
		AWAIT(done)
	END P;
	BEGIN done := TRUE; P END Test.

negative: active body
	MODULE Test;
	VAR start,called: BOOLEAN;
	VAR o:OBJECT VAR i: LONGINT; BEGIN{ACTIVE} WHILE ~start DO END; called := TRUE  END;
	BEGIN
		start := FALSE; called := FALSE;
		NEW(o);
		start := TRUE;
		WHILE ~called DO END;
		HALT(100);
	END Test.

positive: negative await statement in procedure in module scope
	MODULE Test;
	VAR done: BOOLEAN;
	VAR o:OBJECT VAR i: LONGINT; BEGIN{ACTIVE} FOR i := 0 TO 10000 DO END; Done END;
	PROCEDURE Done;
	BEGIN{EXCLUSIVE}
		done := TRUE
	END Done;
	PROCEDURE P;
	BEGIN{EXCLUSIVE}
		AWAIT(done)
	END P;
	BEGIN done := FALSE; NEW(o); P END Test.

positive: positive await statement in procedure in object scope
	MODULE Test;
	VAR o:OBJECT
	VAR done: BOOLEAN;
	PROCEDURE P;
	BEGIN{EXCLUSIVE}
		AWAIT(done)
	END P;
	BEGIN done := TRUE;
	END;
	BEGIN NEW(o); o.P; END Test.

positive: negative await statement in procedure in object scope
	MODULE Test;
	VAR o:OBJECT
	VAR done: BOOLEAN; i: LONGINT;
	PROCEDURE & Init; BEGIN done := FALSE END Init;
	PROCEDURE P;
	BEGIN{EXCLUSIVE}
		AWAIT(done)
	END P;
	PROCEDURE Done;
	BEGIN{EXCLUSIVE}
		done := TRUE
	END Done;

	BEGIN{ACTIVE}  FOR i := 0 TO 10000 DO END; Done
	END;
	BEGIN NEW(o); o.P; END Test.


# programs

positive: Gaussian natural sum using arrays

	MODULE Test;
	CONST Count = 100;
	VAR i, sum: LONGINT; a: ARRAY Count OF LONGINT;
	BEGIN
		FOR i := 0 TO Count - 1 DO
			a[i] := i;
		END;
		i := 0; sum := 0;
		WHILE i < Count DO
			INC (sum, a[i]); INC (i);
		END;
		ASSERT (sum = Count * (Count-1) DIV 2);
	END Test.

positive: natural sum with several synchronous concurrent accumulators

	MODULE Test;
	TYPE Accumulator = OBJECT
		VAR i: INTEGER; done: BOOLEAN;
		PROCEDURE &Init; BEGIN done := FALSE; END Init;
		PROCEDURE Await; BEGIN {EXCLUSIVE} AWAIT (done); END Await;
		BEGIN {ACTIVE, EXCLUSIVE} FOR i := 1 TO 100 DO Add END; done := TRUE;
	END Accumulator;
	VAR acc0, acc1, acc2: Accumulator; sum: INTEGER;
	PROCEDURE Busy; VAR i: INTEGER; BEGIN FOR i := 1 TO 100 DO END; END Busy;
	PROCEDURE Add; VAR temp: INTEGER; BEGIN {EXCLUSIVE} temp := sum; Busy; sum := temp + 1 END Add;
	BEGIN sum := 0; NEW (acc0); NEW (acc1); NEW (acc2); acc0.Await; acc1.Await; acc2.Await; ASSERT (sum = 300);
	END Test.

negative: natural sum with several asynchronous concurrent accumulators

	MODULE Test;
	TYPE Accumulator = OBJECT
		VAR i: INTEGER; done: BOOLEAN;
		PROCEDURE &Init; BEGIN done := FALSE; END Init;
		PROCEDURE Await; BEGIN {EXCLUSIVE} AWAIT (done); END Await;
	BEGIN {ACTIVE, EXCLUSIVE} FOR i := 1 TO 100 DO Add END; done := TRUE;
	END Accumulator;
	VAR acc0, acc1, acc2: Accumulator; sum: INTEGER;
	PROCEDURE Busy; VAR i: INTEGER; BEGIN FOR i := 1 TO 100 DO END; END Busy;
	PROCEDURE Add; VAR temp: INTEGER; BEGIN temp := sum; Busy; sum := temp + 1 END Add;
	BEGIN sum := 0; NEW (acc0); NEW (acc1); NEW (acc2); acc0.Await; acc1.Await; acc2.Await; ASSERT (sum = 300);
	END Test.

positive: dining philosophers

	MODULE Test;
	CONST Forks = 5;
	TYPE Fork = OBJECT
		VAR taken: BOOLEAN;
		PROCEDURE &Init; BEGIN taken := FALSE; END Init;
		PROCEDURE PickUp; BEGIN {EXCLUSIVE} AWAIT (~taken); taken := TRUE; END PickUp;
		PROCEDURE PutDown; BEGIN {EXCLUSIVE} taken := FALSE; END PutDown;
	END Fork;
	TYPE Philosopher = OBJECT
		VAR first, second, i: INTEGER; done: BOOLEAN
		PROCEDURE &Init (id: INTEGER); BEGIN IF id # Forks - 1 THEN first := id; second := id + 1; ELSE first := 0; second := Forks - 1 END; done := FALSE; END Init;
		PROCEDURE Await; BEGIN {EXCLUSIVE} AWAIT (done); END Await;
		BEGIN {EXCLUSIVE, ACTIVE} FOR i := 1 TO 10 DO Think;
			fork[first].PickUp; fork[second].PickUp; Eat; fork[second].PutDown; fork[first].PutDown;
		END; done := TRUE;
	END Philosopher;
	VAR fork: ARRAY Forks OF Fork; philosopher: ARRAY Forks OF Philosopher; id: INTEGER;
	PROCEDURE Think; VAR i: INTEGER; BEGIN FOR i := 1 TO 100 DO END; END Think;
	PROCEDURE Eat; VAR i: INTEGER; BEGIN FOR i := 1 TO 1000 DO END; END Eat;
	BEGIN
		FOR id := 0 TO Forks - 1 DO NEW (fork[id]) END;
		FOR id := 0 TO Forks - 1 DO NEW (philosopher[id], id) END;
		FOR id := 0 TO Forks - 1 DO philosopher[id].Await END;
	END Test.

positive: bounded buffer

	MODULE Test;
	TYPE Buffer = OBJECT
		VAR in, out, size: LONGINT;
		VAR data: POINTER TO ARRAY OF INTEGER;
		PROCEDURE &Init (len: LONGINT); BEGIN in := 0; out := 0; size := 0; NEW (data, len); END Init;
		PROCEDURE Put (item: INTEGER); BEGIN {EXCLUSIVE} AWAIT (size # LEN (data)); data[in] := item; in := (in + 1) MOD LEN (data); INC (size) END Put;
		PROCEDURE Get (VAR item: INTEGER); BEGIN {EXCLUSIVE} AWAIT (size # 0); item := data[out]; out := (out + 1) MOD LEN (data); DEC (size) END Get;
	END Buffer;
	TYPE Process = OBJECT
		VAR count: INTEGER; buffer: Buffer; done: BOOLEAN;
		PROCEDURE &Init (count: INTEGER; buffer: Buffer); BEGIN SELF.count := count; SELF.buffer := buffer; done := FALSE; END Init;
		PROCEDURE Await; BEGIN {EXCLUSIVE} AWAIT (done); END Await;
		PROCEDURE Handle; END Handle;
		BEGIN {EXCLUSIVE, ACTIVE} Handle; done := TRUE;
	END Process;
	TYPE Producer = OBJECT (Process)
		PROCEDURE Handle; VAR i: INTEGER; BEGIN FOR i := 1 TO count DO buffer.Put (i); END; END Handle;
	END Producer;
	TYPE Consumer = OBJECT (Process)
		PROCEDURE Handle; VAR i, item: INTEGER; BEGIN FOR i := 1 TO count DO buffer.Get (item); ASSERT (item = i); END; END Handle;
	END Consumer;
	PROCEDURE Test (len, count: INTEGER);
	VAR buffer: Buffer; consumer: Consumer; producer: Producer;
	BEGIN NEW (buffer, len); NEW (consumer, count, buffer); NEW (producer, count, buffer); consumer.Await; producer.Await;
	END Test;
	BEGIN Test (1, 1000); Test (10, 1000); Test (1000, 1000); Test (1000, 100);
	END Test.

positive: sudoku solver

	MODULE Test;
	CONST Empty = '0'; Blocks = 3; Columns = Blocks * Blocks; Cells = Columns * Columns;
	TYPE Cell = INTEGER; Value = CHAR; Game = ARRAY Cells + 1 OF Value;
	PROCEDURE IsValidCell (CONST game: Game; cell: Cell): BOOLEAN;
	VAR value: Value; VAR row, column: Cell;
		PROCEDURE Check (start, stride: Cell): BOOLEAN;
		VAR cells, count: Cell;
		BEGIN count := stride; FOR cells := 0 TO Columns - 1 DO IF (start # cell) & (game[start] = value) THEN RETURN FALSE END;
			DEC (count); IF count = 0 THEN count := stride; INC (start, Columns + 1 - stride) ELSE INC (start) END; END; RETURN TRUE;
		END Check;
	BEGIN value := game[cell]; IF value = Empty THEN RETURN TRUE END; row := cell DIV Columns; column := cell MOD Columns;
		RETURN Check (cell - column, Columns) & Check (column, 1) & Check (cell - row MOD Blocks * Columns - column MOD Blocks, Blocks);
	END IsValidCell;
	PROCEDURE IsValid (CONST game: Game): BOOLEAN;
	VAR cell: Cell; BEGIN FOR cell := 0 TO Cells - 1 DO IF ~IsValidCell (game, cell) THEN RETURN FALSE END END; RETURN TRUE;
	END IsValid;
	PROCEDURE Solve (VAR game: Game): BOOLEAN;
	VAR cell: Cell; value: SHORTINT;
	BEGIN FOR cell := 0 TO Cells - 1 DO IF game[cell] = Empty THEN FOR value := ORD (Empty) + 1 TO ORD (Empty) + Columns DO game[cell] := CHR (value);
		IF IsValidCell (game, cell) & Solve (game) THEN RETURN TRUE END; END; game[cell] := Empty; RETURN FALSE; END END; RETURN IsValid (game);
	END Solve;
	PROCEDURE Check (CONST problem, solution: Game);
	VAR game: Game; BEGIN ASSERT (IsValid (problem)); ASSERT (IsValid (solution)); game := problem; ASSERT (Solve (game)); ASSERT (game = solution);
	END Check;
	BEGIN Check ("003020080090500000018609074600047390080205040059160007930402760000006010040070900", "563724189794581236218639574621847395387295641459163827935412768872956413146378952");
	END Test.


# miscellaneous

positive: SYSTEM.VAL on designator and non-designator expression

	MODULE Test;

	IMPORT SYSTEM;

	PROCEDURE P;
	VAR c1,c2,c3,c4: CHAR;
	BEGIN
		c1 := 0FFX;
		c2 := 0FFX;
		c3 := 0FFX;
		c4 := 0FFX;
		ASSERT(SYSTEM.VAL(LONGINT,c4) = -1);
		ASSERT(SYSTEM.VAL(LONGINT,ORD(c4)) = 255);
	END P;

	BEGIN P;
	END Test.

positive: reimporting an object type with initializer

	MODULE A;
	TYPE D1*= OBJECT END D1;
	END A.

	MODULE B;
	IMPORT A;
	TYPE
		D1*= OBJECT (A.D1)
			PROCEDURE &Init*;
			BEGIN
			END Init;
		END D1;
	END B.

	MODULE Test;
	IMPORT B;
	PROCEDURE P*;
	VAR o: B.D1;
	BEGIN NEW(o);
	END P;
	BEGIN P;
	END Test.

positive: reimporting objects and execute bodies

	MODULE A;
	TYPE O*= OBJECT
		VAR initZ-: LONGINT;
		BEGIN initZ := 999;
		END O;
	END A.

	MODULE B;
	IMPORT A;
	TYPE O*= OBJECT (A.O)
		VAR initY-: LONGINT;
		BEGIN initY := 998;
		END O;
	END B.

	MODULE Test;
	IMPORT B;
	TYPE O*=OBJECT (B.O)
		VAR initO: LONGINT;
		BEGIN initO := 997
		END O;
	VAR o: O;
	BEGIN
		NEW(o); ASSERT(o.initO=997); ASSERT(o.initY =998); ASSERT(o.initZ=999);
	END Test.

positive: importing protected object

	MODULE A;
	TYPE O*= OBJECT
			PROCEDURE P*;
			BEGIN{EXCLUSIVE}
			END P;
		END O;
	END A.

	MODULE Test;
	IMPORT A;
	VAR o: A.O;
	BEGIN
		NEW(o); o.P;
	END Test.

positive: importing and extending protected object

	MODULE Test;
	IMPORT A;
		TYPE O*= OBJECT (A.O)
			VAR
				PROCEDURE Q*;
				BEGIN
					P;
				END Q;
		END O;
	VAR o: O;
	BEGIN
		NEW(o); o.Q;
	END Test.

positive: passing string parameter to procedure returning pointer

	MODULE Test;

	TYPE String= POINTER TO ARRAY OF CHAR;

	PROCEDURE TestString*(CONST str: ARRAY OF CHAR): String;
	VAR ch: CHAR;
	BEGIN
		ch := str[0];
		RETURN NIL
	END TestString;

	PROCEDURE Test*;
	VAR str: String;
	BEGIN
		str := TestString("TestStr");
	END Test;

	BEGIN Test
	END Test.

positive: passing array parameter to nested procedure
	MODULE Test;

		PROCEDURE Enum();
		VAR name: ARRAY 256 OF CHAR;

			PROCEDURE GetNextSymbol(VAR s: ARRAY OF CHAR );
			BEGIN
				s[0] := 0X;
			END GetNextSymbol;

		BEGIN
			GetNextSymbol(name);
		END Enum;

	BEGIN Enum();
	END Test.

positive: nested procedure calls itself with parameter

	MODULE Test;

		PROCEDURE Test;
		VAR k: LONGINT;

			PROCEDURE Test0(l: LONGINT);
			BEGIN
				ASSERT(l = 999);
				INC(k);
				IF k < 10 THEN Test0(l) END;
			END Test0;

		BEGIN
			k := 0;
			Test0(999);
		END Test;

	BEGIN Test;
	END Test.

positive: object type declared in procedure scope
	MODULE Test;

		PROCEDURE Test;
		TYPE
			O=OBJECT
			VAR i:LONGINT;

				PROCEDURE &Init;
				BEGIN
					i := 999;
				END Init;

				PROCEDURE P;
				BEGIN
					ASSERT(i=999);
				END P;
			END O;
		VAR o:O;
		BEGIN
			NEW(o); o.P;
		END Test;

	BEGIN Test;
	END Test.

positive: expression involving multiple register savings on stack

	MODULE Test;

	PROCEDURE Test;
	VAR a: POINTER TO ARRAY OF LONGINT; i : LONGINT;

		PROCEDURE Add(i: LONGINT): LONGINT;
		BEGIN
			RETURN i+10
		END Add;

	BEGIN
		NEW(a,10);
		i := 5;
		a[i] := 10;
		a[i] := a[i]+Add(a[i]+Add(a[i] + Add(a[i])));
		ASSERT(a[i] = 70);
	END Test;

	BEGIN Test;
	END Test.

positive:  GETPROCEDURE with procedure returning an object

	MODULE A;
	TYPE Object*=OBJECT VAR a-: LONGINT; END Object;
		PROCEDURE TheProcedure*(): Object;
		VAR o: Object;
		BEGIN
			NEW(o); o.a := 100;  RETURN o;
		END TheProcedure;
	END A.

	MODULE Test;
	IMPORT A;
	PROCEDURE Test;
	VAR p: PROCEDURE(): A.Object; o: A.Object;
	BEGIN
		GETPROCEDURE("A","TheProcedure",p);
		o := p();
		ASSERT(o.a = 100);
	END Test;
	BEGIN Test;
	END Test.

positive: import object and use initializer on alias

	MODULE A;
	TYPE
	O*= OBJECT
	VAR a*: LONGINT;

	PROCEDURE &Init*;
	BEGIN
	END Init;
	END O;

	O2*=O;
	END A.

	MODULE Test;

	IMPORT X :=A;
	VAR o: X.O2;
	BEGIN
		NEW(o); o.a :=10;
	END Test.


positive: procedure returning record

	MODULE Test;
	TYPE R= RECORD a,b: LONGINT END;
	VAR r: R;
	PROCEDURE P(b,a: LONGINT): R;
	VAR r: R;
	BEGIN
		r.a := a; r.b := b;
		RETURN r
	END P;
	BEGIN
		r := P(10,20);
		ASSERT(r.a =20); ASSERT(r.b = 10);
	END Test.

positive: procedure returning static array
	MODULE Test;
	TYPE S= ARRAY 128 OF CHAR;
	VAR s:S;

	PROCEDURE Q(CONST name: ARRAY OF CHAR): S;
	VAR s:S;
	BEGIN
		COPY(name,s);
		RETURN s;
	END Q;

	BEGIN
		s := Q("TestText");
		ASSERT(s= "TestText");
	END Test.

positive: assign static array of char to static VAR parameter arrray of char
	MODULE Test;

	TYPE String = ARRAY 1024 OF CHAR;
	VAR o:OBJECT
		VAR
			x,y,z: LONGINT;
			string:String;
		END;
		name: String;

	PROCEDURE P(VAR name: String);
	BEGIN
		name := o.string;
	END P;

	BEGIN
		NEW(o); o.string := "test";  P(name);  ASSERT(name = "test");
	END Test.

positive: procedure returning record containing pointer
	MODULE Test;
	TYPE R= RECORD any: POINTER TO R; a,b: LONGINT END;
	VAR r: R;
	PROCEDURE P(b,a: LONGINT): R;
	VAR r: R;
	BEGIN
		r.a := a; r.b := b;
		RETURN r
	END P;
	BEGIN
		r := P(10,20);
		ASSERT(r.a =20); ASSERT(r.b = 10);
	END Test.

positive: pass record by value, variable and as a constant
	MODULE Test;
	TYPE Record= RECORD min,max: LONGINT END;

	PROCEDURE P(x: Record);
	BEGIN
		ASSERT(x.min = -123); ASSERT(x.max = 123);
	END P;

	PROCEDURE Q(VAR x: Record);
	BEGIN
		ASSERT(x.min = -123); ASSERT(x.max = 123);
	END Q;

	PROCEDURE R(CONST x: Record);
	BEGIN
		ASSERT(x.min = -123); ASSERT(x.max = 123);
	END R;

	PROCEDURE T;
	VAR r: Record;
	BEGIN
		r.min := -123; r.max := 123;
		P(r); Q(r); R(r);
	END T;

	BEGIN
		T
	END Test.

positive: procedure returning record called as parameter
	MODULE Test;

	TYPE
	Rectangle=RECORD l,t,r,b: LONGINT END;
	Object = OBJECT VAR w: LONGINT END Object;

	PROCEDURE Check(y: Object; r1: Rectangle; x: Object; CONST  r2: Rectangle);
	BEGIN
		ASSERT(r1.l = r2.l); ASSERT(r1.t = r2.t);
		ASSERT(r1.r = 10); ASSERT(r1.b = 20);
		ASSERT(r2.r = 101); ASSERT(r2.b = 102);
		ASSERT(x.w = 10);
	END Check;



	PROCEDURE Q(l,t,r,b: LONGINT): Rectangle;
	VAR R: Rectangle;
	BEGIN
		R.l := l; R.t := t; R.r := r; R.b := b;
		RETURN R
	END Q;

	PROCEDURE P;
	VAR r1,r2: Rectangle; o: Object;
	BEGIN
		NEW(o); o.w := 10;
		r1.l := 0; r2.l := 0; r1.t := -100; r2.t := -100;
		r1.r := 10; r1.b := 20;
		r2.r := 101; r2.b := 102;
		Check(o,r1,o,r2);
		Check(o,Q(0,-100,10,20),o,Q(0,-100,101,102));
	END P;

	BEGIN P
	END Test.

positive: pass delegate as parameter
	MODULE Test;

	TYPE
	Procedure = PROCEDURE {DELEGATE}(): LONGINT;

	TYPE
	O= OBJECT
	VAR g: LONGINT;

		PROCEDURE Test;
		BEGIN
			CallProc(OProc);
			CallProc(GProc);
		END Test;

		PROCEDURE OProc(): LONGINT;
		BEGIN
			RETURN g
		END OProc;

	BEGIN g := 10;
	END O;

	PROCEDURE CallProc(p: Procedure);
	BEGIN
		ASSERT(p() = 10);
	END CallProc;

	PROCEDURE GProc(): LONGINT;
	BEGIN
		RETURN 10
	END GProc;


	PROCEDURE P;
	VAR o: O;
	BEGIN
		NEW(o); o.Test;
	END P;


	BEGIN P
	END Test.

positive: reimport indirectly published procedure
	MODULE A;
	TYPE AO*= OBJECT
			VAR called*: BOOLEAN;
			PROCEDURE P*;
			BEGIN called := TRUE;
			END P;
		BEGIN
			called := FALSE;
		END AO;

		 AO2*= OBJECT(AO);

			PROCEDURE P;
			BEGIN P^
			END P;
		END AO2;
	END A.

	MODULE B;
	IMPORT A;
	TYPE BO*= OBJECT(A.AO2);

			PROCEDURE P;
			BEGIN P^
			END P;
		END BO;
	END B.

	MODULE Test;
	IMPORT B;
	TYPE O*= OBJECT(B.BO);
			PROCEDURE P;
			BEGIN
				P^;
			END P;
		END O;

		PROCEDURE P;
		VAR o:O;
		BEGIN
			NEW(o);
			o.P; ASSERT(o.called);
		END P;
	BEGIN P;
	END Test.

positive: pass static array by value, reference and as constant
	MODULE Test;
	TYPE Array= ARRAY 10 OF LONGINT;

	PROCEDURE P(x: Array);
	BEGIN
		ASSERT(x[5] = -123); ASSERT(x[8] = 123);
	END P;

	PROCEDURE Q(VAR x: Array);
	BEGIN
		ASSERT(x[5] = -123); ASSERT(x[8] = 123);
	END Q;

	PROCEDURE R(CONST x: Array);
	BEGIN
		ASSERT(x[5] = -123); ASSERT(x[8] = 123);
	END R;

	PROCEDURE T;
	VAR r: Array;
	BEGIN
		r[5] := -123; r[8] := 123;
		P(r); Q(r); R(r);
	END T;

	BEGIN
		T
	END Test.

positive: procedure returning static array called as parameter
	MODULE Test;

	TYPE
	Rectangle=ARRAY 10 OF LONGINT;
	Object = OBJECT VAR w: LONGINT END Object;

	PROCEDURE Check(y: Object; r1: Rectangle; x: Object; CONST  r2: Rectangle);
	BEGIN
		ASSERT(r1[3] = r2[3]); ASSERT(r1[5] = r2[5]);
		ASSERT(r1[6] = 10); ASSERT(r1[7] = 20);
		ASSERT(r2[6] = 101); ASSERT(r2[7] = 102);
		ASSERT(x.w = 10);
	END Check;

	PROCEDURE Q(l,t,r,b: LONGINT): Rectangle;
	VAR R: Rectangle;
	BEGIN
		R[3] := l; R[5] := t; R[6] := r; R[7] := b;
		RETURN R
	END Q;

	PROCEDURE P;
	VAR r1,r2: Rectangle; o: Object;
	BEGIN
		NEW(o); o.w := 10;
		r1[3] := 0; r2[3] := 0; r1[5] := -100; r2[5] := -100;
		r1[6] := 10; r1[7] := 20;
		r2[6] := 101; r2[7] := 102;
		Check(o,r1,o,r2);
		Check(o,Q(0,-100,10,20),o,Q(0,-100,101,102));
	END P;

	BEGIN P
	END Test.

positive: new on var parameter object

	MODULE Test;

	TYPE O = OBJECT
		VAR x: LONGINT;
		PROCEDURE &init;
		BEGIN x := 10;
		END init;
	END O;

	PROCEDURE Q(VAR o: O);
	BEGIN
		NEW(o); ASSERT(o # NIL,101); ASSERT(o.x = 10,102);
	END Q;

	PROCEDURE P;
	VAR o: O;
	BEGIN
		Q(o); ASSERT(o.x = 10,103);
	END P;

	BEGIN P
	END Test.

positive: new on var parameter array

	MODULE Test;

	TYPE O=POINTER TO ARRAY OF INTEGER;

	PROCEDURE Q(VAR o: O);
	BEGIN
		NEW(o,10); o[5] := 10;
	END Q;


	PROCEDURE P;
	VAR o: O;
	BEGIN
		Q(o); ASSERT(o[5] = 10); ASSERT(LEN(o)=10);
	END P;

	BEGIN P
	END Test.

positive: call procedure returning a basic type within an exclusive section
	MODULE Test;

	TYPE
		O= OBJECT
			PROCEDURE P(): LONGINT;
			VAR a: LONGINT;
			BEGIN{EXCLUSIVE}
				a := 4;
				RETURN a*a
			END P;
		END O;

		PROCEDURE P;
		VAR o: O;
		BEGIN
			NEW(o);
			ASSERT(o.P() = 16);
		END P;


	BEGIN P
	END Test.

positive: pass Delegate nil value

	MODULE Test;
	TYPE
		Delegate= PROCEDURE{DELEGATE};

		PROCEDURE P(p: Delegate);
		BEGIN
			ASSERT(p=NIL);
		END P;

	BEGIN
		P(NIL); (* if incorrect then stack will be invalid => hard brakedown *)
	END Test.

positive: type tests and guards on records and pointers on direct and indirect parameters

	MODULE Test;

	TYPE
		R0=RECORD END;
		R1=RECORD(R0) v: LONGINT END;
		R2=RECORD(R0) END;

		P0=POINTER TO RECORD END;
		P1=POINTER TO RECORD(P0) v: LONGINT; END;
		P2=POINTER TO RECORD(P1) END;

	PROCEDURE R(VAR r: R0);
	BEGIN
		ASSERT(r IS R1);
		ASSERT(~(r IS R2));
		WITH r: R1 DO
			r.v := 10;
		END;
		r(R1).v := 10;
	END R;

	PROCEDURE S(VAR r: R0);
	BEGIN
		R(r);
	END S;

	PROCEDURE RC(CONST r: R0);
	VAR i: LONGINT;
	BEGIN
		ASSERT(r IS R1);
		ASSERT(~(r IS R2));
		WITH r: R1 DO
			i := r.v
		END;
		i := r(R1).v;
	END RC;

	PROCEDURE SC(CONST r: R0);
	BEGIN
		RC(r);
	END SC;

	PROCEDURE P(p: P0);
	BEGIN
		ASSERT(p IS P1);
		ASSERT(~(p IS P2));
		WITH p: P1 DO
			p.v := 10;
		END;
		p(P1).v := 10;
	END P;

	PROCEDURE PV(VAR p: P0);
	BEGIN
		ASSERT(p IS P1);
		ASSERT(~(p IS P2));
		WITH p: P1 DO
			p.v := 10;
		END;
		p(P1).v := 10;
	END PV;

	PROCEDURE PC(CONST p: P0);
	BEGIN
		ASSERT(p IS P1);
		ASSERT(~(p IS P2));
		WITH p: P1 DO
			p.v := 10;
		END;
		p(P1).v := 10;
	END PC;

	PROCEDURE Test;
	VAR r: R1; p: P1; p0: P0;
	BEGIN
		R(r); S(r); RC(r); SC(r);
		NEW(p);
		p0 := p;
		P(p); PC(p); PV(p0);
	END Test;

	BEGIN
		Test;
	END Test.

positive: inline procedure with fixups

	MODULE Test;

	IMPORT SYSTEM;

	CONST const = 123;
	VAR a, b: LONGINT;

	PROCEDURE -P(): LONGINT;
	CODE{SYSTEM.i386}
		MOV EAX,b
		MOV a,const
		JMP end
		MOV EAX,10
		end:
	END P;

	PROCEDURE Q;
	VAR b: LONGINT;
	BEGIN
		b := P();
		ASSERT(a=123);
		ASSERT(b=1234);
	END Q;

	BEGIN
		b := 1234;
		Q;
		a := P();
		ASSERT(a=1234);
	END Test.

positive: import inline assembler procedure

	MODULE A;

	IMPORT SYSTEM;

	PROCEDURE -P*(a: LONGINT): LONGINT;
	CODE{SYSTEM.i386}
		POP EAX
		ADD EAX,10
	END P;

	BEGIN
		ASSERT(P(10) = 20);
	END A.

	MODULE Test;
	IMPORT A;
	BEGIN
		ASSERT(A.P(10)=20)
	END Test.

positive: call a winapi procedure with an array of system byte

	MODULE Test;

	IMPORT SYSTEM;

	PROCEDURE{WINAPI}  ReadFile (VAR lpBuffer: ARRAY   OF SYSTEM.BYTE);
	BEGIN
		ASSERT(SYSTEM.VAL(CHAR,lpBuffer[0]) = 'A');
	END ReadFile;

	PROCEDURE P;
	VAR a: ARRAY 2 OF CHAR;
	BEGIN
		a[0] := 'A';
		ReadFile(a);
	END P;

	BEGIN P
	END Test.

positive: unlock with or without return statements
	MODULE Test;

	VAR q: LONGINT;

	PROCEDURE P;
	BEGIN{EXCLUSIVE}
	END P;

	PROCEDURE P2;
	BEGIN{EXCLUSIVE}
		RETURN
	END P2;

	PROCEDURE Q(): LONGINT;
	BEGIN{EXCLUSIVE}
		RETURN 0
	END Q;

	BEGIN P; P2; P; q := Q(); P;
	END Test.

positive: conversion to 32 bit in ash

	MODULE Test;

	PROCEDURE P;
	VAR l: LONGINT; ch: CHAR;
	BEGIN
		ch := CHR(237); l := 8;
		l := ASH(ORD(ch),l); ASSERT(l=60672);
	END P;

	BEGIN
	P
	END Test.

positive: pass delegate as variable or value parameter

	MODULE Test;

	TYPE
		Array = POINTER TO ARRAY OF CHAR;
		Delegate = PROCEDURE{DELEGATE}(): LONGINT;
		O= OBJECT
		VAR a: Array;

			PROCEDURE P(): LONGINT;
			BEGIN
				ASSERT(a # NIL);
				RETURN LEN(a);
			END P;

			PROCEDURE &Init(a: Array);
			BEGIN
				SELF.a := a;
			END Init;

		END O;

	VAR dd: Delegate; o: O; a: Array;

		PROCEDURE SetDelegate(d: Delegate);
		BEGIN
			dd := d;
		END SetDelegate;

		PROCEDURE GetDelegate(VAR d: Delegate);
		BEGIN
			d := o.P;
		END GetDelegate;

		PROCEDURE P;
		VAR d: Delegate;
		BEGIN
			GetDelegate(d);
			SetDelegate(d);
			ASSERT(dd() = 123);
		END P;

	BEGIN NEW(a,123); NEW(o,a); P;
	END Test.

positive: import same module with different aliases

	MODULE A;
	PROCEDURE P*; BEGIN END P;
	END A.

	MODULE Test;
	IMPORT A,B := A;

	PROCEDURE P;
	BEGIN
		A.P;
		B.P;
	END P;

	BEGIN P
	END Test.


positive: procedures returning a record (checks correct return parameter size)

	MODULE Test;

	TYPE
		Rectangle=RECORD t,l,r,b: LONGINT END;
		Container= POINTER TO RECORD r: Rectangle END;

	PROCEDURE GetWMCoordinates(VAR r : Rectangle) : Rectangle;
	VAR rect : Rectangle;
	BEGIN
		rect.l := r.l+1;
		rect.r := r.r+2;
		rect.t := r.t+3;
		rect.b := r.b+4;
		RETURN rect;
	END GetWMCoordinates;

	PROCEDURE GetWMCoordinates2() : Rectangle;
	VAR rect : Rectangle;
	BEGIN
		rect.l := 1;
		rect.r := 2;
		rect.t := 3;
		rect.b := 4;
		RETURN rect;
	END GetWMCoordinates2;


	PROCEDURE P1;
	VAR r2: Rectangle;
	BEGIN
		r2 := GetWMCoordinates2();
		ASSERT(r2.l = 1,101);
		ASSERT(r2.r = 2,102);
		ASSERT(r2.t = 3,103);
		ASSERT(r2.b = 4,104);
	END P1;

	PROCEDURE P2;
	VAR r1,r2: Rectangle;
	BEGIN
		r1.l := 1; r1.r := 2; r1.t := 3; r1.b := 4;
		r2 := GetWMCoordinates(r1);
		ASSERT(r2.l = 2,201);
		ASSERT(r2.r = 4,202);
		ASSERT(r2.t = 6,203);
		ASSERT(r2.b = 8,204);
	END P2;


	PROCEDURE P3;
	VAR c1,c2: Container;
	BEGIN
		NEW(c1); NEW(c2);
		c1.r.l := 1; c1.r.r := 2; c1.r.t := 3; c1.r.b := 4;
		c2.r := GetWMCoordinates(c1.r);
		ASSERT(c2.r.l = 2);
		ASSERT(c2.r.r = 4);
		ASSERT(c2.r.t = 6);
		ASSERT(c2.r.b = 8);
	END P3;

	BEGIN P1;P2;P3;
	END Test.

positive: conversion on return types

	MODULE Test;

		PROCEDURE GetInt () : LONGINT;
		VAR integer: INTEGER;
		BEGIN
			integer := -56;
			RETURN integer
		END GetInt;

		PROCEDURE GetShortint () : LONGINT;
		VAR integer: INTEGER;
		BEGIN
			integer := -56;
			RETURN integer
		END GetShortint;

		PROCEDURE P;
		VAR i: LONGINT;
		BEGIN
			i := GetInt();
			ASSERT(i=-56);
			i := GetShortint();
			ASSERT(i=-56);
		END P;

	BEGIN P;
	END Test.

positive: allocate imported variable

	MODULE A;

	TYPE Record*= RECORD a*: LONGINT; p*: POINTER TO ARRAY OF CHAR; c*: LONGINT; END;
	VAR a*: Record;
	END A.

	MODULE Test;

	IMPORT A;

		PROCEDURE P;
		BEGIN
			NEW(A.a.p,10);
			ASSERT(A.a.p # NIL,101);
		END P;

	BEGIN P;
	END Test.

positive: bitwise rotate

	MODULE Test;

	IMPORT SYSTEM;


	PROCEDURE P;
	VAR val,rot: SET; by: LONGINT;
	BEGIN
		val := {1,2,3,30,31};
		rot := SYSTEM.VAL(SET,SYSTEM.ROT(SYSTEM.VAL(LONGINT,val),7));
		ASSERT(rot ={5..6,8..10});
		rot :=  SYSTEM.VAL(SET,SYSTEM.ROT(SYSTEM.VAL(LONGINT,val),-7));
		ASSERT(rot={23..24,26..28});
		val := {1,2,3,30,31};
		by := 7;
		rot := SYSTEM.VAL(SET,SYSTEM.ROT(SYSTEM.VAL(LONGINT,val),by));
		ASSERT(rot ={5..6,8..10});
		by := -7;
		rot := SYSTEM.VAL(SET,SYSTEM.ROT(SYSTEM.VAL(LONGINT,val),by));
		ASSERT(rot={23..24,26..28});

	END P;


	BEGIN P;
	END Test.

positive: huge stack frames to check for ensured stack allocation

	MODULE Test;

	PROCEDURE P(count: LONGINT);
	VAR x: ARRAY 16000 OF CHAR;
	BEGIN
		IF count > 5 THEN RETURN END;
		P(count+1);
	END P;

	BEGIN P(0);
	END Test.

positive: finally statement, direct and indirect

	MODULE Test;

	VAR b: BOOLEAN;

	PROCEDURE P;
	BEGIN
		HALT(100);
		RETURN
	FINALLY
		b := TRUE
	END P;

	PROCEDURE R;
	BEGIN
		HALT(100);
	END R;

	PROCEDURE Q;
	BEGIN
		R; RETURN
	FINALLY
		b := TRUE
	END Q;

	PROCEDURE S;
		PROCEDURE R;
		BEGIN
			HALT(100);
		END R;
	BEGIN
		R; RETURN
	FINALLY
		b := TRUE
	END S;

	BEGIN
		b := FALSE; P(); ASSERT(b=TRUE);
		b := FALSE; Q(); ASSERT(b=TRUE);
		b := FALSE; S(); ASSERT(b=TRUE);
	END Test.

positive: negate hugeint zero

	MODULE Test;
	PROCEDURE Test;
	VAR x: INTEGER; h,j: HUGEINT;
	BEGIN
		h := 0;
		j := -h;
		ASSERT(j=0);
	END Test;
	BEGIN Test
	END Test.

positive: allocation of a partially exported record type

	MODULE A;

	TYPE
	P*=POINTER TO Desc;
	Desc=RECORD a*,b: LONGINT END;

	END A.

	MODULE Test;

	IMPORT A;

	PROCEDURE Test;
	VAR a: A.P;
	BEGIN
		NEW(a); a.a := 10; ASSERT(a.a = 10);
	END Test;


	BEGIN Test
	END Test.

positive: allocation of a partially exported record type in a multiply imported module

	MODULE A;

	TYPE
	P*=POINTER TO Desc;
	Desc=RECORD a*,b: LONGINT END;

	END A.

	MODULE B;
	END B.

	MODULE Test;

	IMPORT BB := B, BBB := B, AA := A, BBBB := B, AAA := A, B, A;

	PROCEDURE Test;
	VAR a: AAA.P;
	BEGIN
		NEW(a); a.a := 10; ASSERT(a.a = 10);
	END Test;


	BEGIN Test
	END Test.


positive: pass sub-array (computation of address needs multiplication with base size)
	MODULE Test;
	VAR a: ARRAY 10 OF ARRAY 10 OF INTEGER;
	PROCEDURE Q(VAR a: ARRAY OF INTEGER; i: INTEGER);
	VAR j: INTEGER;
	BEGIN
		FOR j := 0 TO SHORT(LEN(a)-1 ) DO
			ASSERT(a[j] = i*10+j);
		END;
	END Q;
	PROCEDURE P(VAR a: ARRAY OF ARRAY OF INTEGER);
	VAR i,j: INTEGER;
	BEGIN
		FOR i := 0 TO SHORT(LEN(a,0)-1) DO
		FOR j := 0 TO SHORT(LEN(a,1)-1) DO
			a[i,j] := i*10+j;
		END;
		END;
		FOR i := 0 TO SHORT(LEN(a,0)-1) DO
			Q(a[i],i);
		END;
	END P;
	BEGIN P(a);
	END Test.

positive: array length operator for static and dynamic arrays with static and dynamic dimension parameter
	MODULE Test;

	PROCEDURE Test;
	VAR a: ARRAY 1,2,3,4 OF LONGINT;
		b: POINTER TO ARRAY OF ARRAY OF ARRAY 3,4 OF LONGINT;
		c: POINTER TO ARRAY OF ARRAY OF ARRAY OF ARRAY OF LONGINT;
		l0,l1,l2,l3,lv,v: LONGINT;
	BEGIN
		v := 2;
		NEW(b,1,2);
		NEW(c,1,2,3,4);

		l0 := LEN(a,0);
		ASSERT(l0=1,1000);
		l1 := LEN(a,1);
		ASSERT(l1=2,1001);
		l2 := LEN(a,2);
		ASSERT(l2=3,1002);
		l3 := LEN(a,3);
		ASSERT(l3=4,1003);
		FOR v := 0 TO 3 DO
			lv := LEN(a,v);
			ASSERT(lv=v+1,1004);
		END;

		l0 := LEN(b,0);
		ASSERT(l0=1,2000);
		l1 := LEN(b,1);
		ASSERT(l1=2,2001);
		l2 := LEN(b,2);
		ASSERT(l2=3,2002);
		l3 := LEN(b,3);
		ASSERT(l3=4,2003);
		FOR v := 0 TO 3 DO
			lv := LEN(b,v);
			ASSERT(lv=v+1,2004);
		END;

		l0 := LEN(c,0);
		ASSERT(l0=1,3000);
		l1 := LEN(c,1);
		ASSERT(l1=2,3001);
		l2 := LEN(c,2);
		ASSERT(l2=3,3002);
		l3 := LEN(c,3);
		ASSERT(l3=4,3003);
		FOR v := 0 TO 3 DO
			lv := LEN(c,v);
			ASSERT(lv=v+1,3004);
		END;

	END Test;

	BEGIN Test
	END Test.

positive: assignment of extended record type to base type (check destination size)

	MODULE Test;

	TYPE
		R= RECORD a,b,c: LONGINT END;
		S= RECORD (R) d,e: LONGINT END;

	PROCEDURE Test;
	VAR a0,a1,a2: LONGINT; b: R; c: LONGINT; d: S;
	BEGIN
		a0 := 0;
		a1 := 0;
		a2 := 0;
		c := 0;
		d.a := MAX(LONGINT);
		d.b := MAX(LONGINT);
		d.c := MAX(LONGINT);
		d.d := MAX(LONGINT);
		d.e := MAX(LONGINT);
		b := d;
		ASSERT(c=0);
		ASSERT(a0=0);
		ASSERT(a1=0);
		ASSERT(a2=0);
		ASSERT(b.a = MAX(LONGINT));
		ASSERT(b.b = MAX(LONGINT));
		ASSERT(b.c = MAX(LONGINT));

	END Test;


	BEGIN Test
	END Test.

