program nasty(input, output);

label 1, 2, 3, 4;

{L. Allison, Department of Computer Science, Monash University
	     http://www.cs.monash.edu.au/
 Puzzles to exercise the mind first and the compiler later.  Try to predict
 which of the following very dubious bits of code are in fact syntactically
 wrong and which are correct according to the Pascal standard. Then check with
 the Pascal standard, then try your Pascal compiler to see if it is correct.
 PS. The Berkeley Unix Pascal compiler is usually pretty good.

Ref:
 Australian Standard 2580-1983 Programming Language Pascal
 from Australian Standards Association
      Clunies Ross House
      191 Royal Parade
      Parkville 3052
      Victoria         $34.93+$3.50 pp 1987
}

var a, b, c :set of 0..9;
{-----------------------------------------------------------------------------}

pRoCeDuRe LoOkSfUnNy;
   vAr XyZ :iNtEgEr;
BeGiN xYz:=7
eNd;

{-----------------------------------------------------------------------------}
procedure PointerTypes;
   type i=integer;
   procedure p;
      type r = record pif:^i;
                      ifd:i
               end;
           i = char;
      var x:r;
   begin  {p} x.ifd:=7;  x.ifd:='7';    {which is correct?}
              new(x.pif);
              x.pif^:=7; x.pif^:='7'    {which is correct?}
   end    {p};
begin p
end { PointerTypes };
{-----------------------------------------------------------------------------}

procedure Compatibility;                       {which assignments are correct?}
   type arr1=array[1..3]of integer;
        arr2=array[1..3]of integer;
        str1=packed array[1..3]of char;
   var  a1, a2:arr1;
        a3:arr2;
        a4:array[1..3]of integer;
        s1:str1;
        s2:packed array[1..3]of char;
	s3:packed array[1..4]of char;
   procedure p(procedure q(x:real; y:real));
   begin q(3.14, 2.7)
   end;
   procedure r(x,y :real);
   begin write(x+y)
   end;
begin a1:=a2; a1:=a3; a1:=a4;
      a2:=a3; a2:=a4;
      a3:=a4;
      s1:='abc'; s2:=s1;
      s3:=s2; s2:=s3;
      p(r);                                               {is this call valid?}
      r(1, 2)
end   {Compatibility};
{-----------------------------------------------------------------------------}

procedure Redefine;
   const maxint=true;
         true=7;
   type integer=boolean;
   var  read:integer;
begin read:=maxint or false
end   { Redefine };
{-----------------------------------------------------------------------------}

procedure Declarations;
   const averylongidentifierindeed1 = 1;
	 averylongidentifierindeed2 = 2;

   type digit =0..9;
        day=(sunday,monday,tuesday,wednesday,thursday,friday,saturday);
        char = record c:char end;
        r =record end;
        xtype = ^xtr; xtr = record x:xtype end;

   var d:day;
       r:r;
       x:xtype;

   procedure p;
      type day = (monday, tuesday, wednesday, thursday, friday);
      var digit: digit;
          weekday:day;
   begin {p} digit := 7;
             d:=sunday; d:=succ(sunday); d:=monday;
             weekday:=monday; weekday:=succ(sunday)
   end   {p};

   procedure q;
      procedure digit(digit:digit);
      begin write(digit)
      end;
   begin digit(5)
   end   {q};

   function integer(integer:integer):integer;
      type digit = record digit:digit
                   end;
   begin integer:=5
   end;

begin {Declarations}
      p;
      q;
      write(integer(6));
      new(x); x^.x:=x; x^.x^.x^.x^.x^.x^.x:=nil
end   {Declarations};
{-----------------------------------------------------------------------------}

function NoResult:integer;
begin goto 1
end;

function NoResult2:integer; begin end;

function StillNoResult:integer;
begin if false then StillNoResult:=7
end;

function Result :integer;           
   procedure SetResult;
   begin Result:=7
   end;
begin SetResult
end   {Result};
{-----------------------------------------------------------------------------}

procedure Loops;         {which of the loops and other constructs are correct?}
   var j:integer;

   function f( i:integer; var ri:integer):integer;
      var k:integer;
   begin for  k:=1 to 3 do; {local}
         for  i:=1 to 3 do; {val param}
         for ri:=1 to 3 do; {ref param}
         for  j:=1 to 3 do; {outer}
         for  f:=1 to 3 do; {fn}
   end   {f};

begin j := f(1, j);
end   {Loops};
{-----------------------------------------------------------------------------}

procedure Leap;
label 11,22,33,44;
begin goto 11; begin 11: end;
      if 1=2 then 22: else 33:goto 22;
      goto 044; 0044:
end   {Leap};

{-----------------------------------------------------------------------------}

begin {main}
   a:=[1..5]; b:=[2,3]; c:=[3,4];

   ;;;
   
   if [[[1..2]<=[1..3]]<=[true]]=[true] then
   else case 1 of
           1,3:2:3: goto 1;
           4:1:4: goto 2;
	   2:
        end;

   if a-b+c = a+c-b then write('yes') else write('no')
(*comment}
end.
