--
--	cgtest91.occ -- RECURSIVE PROCs
--	Copyright (C) 2007 University of Kent
--
--	This program is free software; you can redistribute it and/or modify
--	it under the terms of the GNU General Public License as published by
--	the Free Software Foundation; either version 2 of the License, or
--	(at your option) any later version.
--
--	This program is distributed in the hope that it will be useful,
--	but WITHOUT ANY WARRANTY; without even the implied warranty of
--	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--	GNU General Public License for more details.
--
--	You should have received a copy of the GNU General Public License
--	along with this program; if not, write to the Free Software
--	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
--



PROC cgtest91 (CHAN OF BYTE keyb?, scr!, err!)

  #INCLUDE "cgmain.occ"
  #INCLUDE "cgreal.occ"

  --{{{  tests
  --{{{  test0 -- function-like recursive procs
  PROC test0 ()
    --{{{  simple recursive procs (both syntaxes)
    REC PROC sum (VAL INT n, INT result)
      IF
        n < 2
          result := 1
        TRUE
          SEQ
            sum (n - 1, result)
            result := result + n
    :
    RECURSIVE PROC factorial (VAL INT n, INT result)
      IF
        n < 2
          result := 1
        TRUE
          SEQ
            factorial (n - 1, result)
            result := result * n
    :
    --}}}
    --{{{  Ackermann's function
    RECURSIVE PROC ackermann (VAL INT64 m, n, INT64 result)
      IF
        m = 0
          result := n + 1
        n = 0
          ackermann (m - 1, 1, result)
        TRUE
          INT64 t:
          SEQ
            ackermann (m, n - 1, t)
            ackermann (m - 1, t, result)
    :
    --}}}

    INT r:
    INT64 r64:
    SEQ
      sum (1, r)
      check.INT (r, 1, "t0 sum (1)")
      sum (10, r)
      check.INT (r, 55, "t0 sum (10)")
      factorial (1, r)
      check.INT (r, 1, "t0 factorial (1)")
      factorial (6, r)
      check.INT (r, 720, "t0 factorial")
      ackermann (4, 0, r64)
      check.INT64 (r64, 13, "t0 ackermann (4, 0)")
      ackermann (3, 4, r64)
      check.INT64 (r64, 125, "t0 ackermann (3, 4)")
  :
  --}}}
  --{{{  test1 -- different argument types
  PROC test1 ()
    CHAN TYPE MY.CT
      MOBILE RECORD
        CHAN BYTE b?:
        CHAN INT i!:
    :

    REC PROC various (VAL INT n, BYTE b, INT i, INT64 iw, VAL INT64 cw,
                      []BYTE s, VAL []BYTE vs,
                      MOBILE []BYTE ms1, VAL []BYTE ms2,
                      CHAN INT c?, SHARED CHAN INT cs!,
                      MY.CT! cli, SHARED MY.CT? svr,
                      BARRIER bar, MOBILE BARRIER mbar)
      IF
        n < 20
          various (n + 1, b, i, iw, cw, s, vs, ms1, ms2, c, cs!, cli, svr, bar, mbar)
        TRUE
          BYTE vb:
          INT v:
          SEQ
            b := 42
            i := 12345678
            iw := 123456789012
            check.INT64 (cw, 1234567890123, "t1 VAL INT64 arg")
            s := "occamlives"
            check.string (vs, "tockrocks", "t1 VAL []BYTE arg")
            check.string (ms1, "lay by your pleading", "t1 MOBILE []BYTE arg in")
            ms1 := "put down your studies"
            check.string (ms2, "the law lies a-bleeding", "t1 MOBILE []BYTE arg as VAL []BYTE")
            c ? v
            check.INT (v, 4231, "t1 CHAN INT arg")
            CLAIM cs!
              cs ! 4321
            PAR
              SEQ
                cli[b] ! 65
                cli[i] ? v
              CLAIM svr
                SEQ
                  svr[b] ? vb
                  svr[i] ! 250981
            check.BYTE (vb, 65, "t1 MY.CT CHAN BYTE arg")
            check.INT (v, 250981, "t1 MY.CT CHAN INT arg")
            SYNC bar
            SYNC mbar
    :

    BYTE b:
    INT i:
    INT64 iw:
    [10]BYTE s:
    MOBILE []BYTE ms1, ms2:
    CHAN INT c:
    SHARED! CHAN INT cs:
    INT cs.v:
    MY.CT! cli:
    SHARED MY.CT? svr:
    BARRIER bar:
    MOBILE BARRIER mbar:
    SEQ
      ms1 := "lay by your pleading"
      ms2 := "the law lies a-bleeding"
      cli, svr := MOBILE MY.CT
      mbar := MOBILE BARRIER
      PAR
        various (0, b, i, iw, 1234567890123, s, "tockrocks", ms1, ms2,
                 c?, cs!, cli, svr, bar, mbar)
        c ! 4231
        cs ? cs.v
      check.BYTE (b, 42, "t1 BYTE arg")
      check.INT (i, 12345678, "t1 INT arg")
      check.INT64 (iw, 123456789012, "t1 INT64 arg")
      check.string (s, "occamlives", "t1 []BYTE arg")
      check.string (ms1, "put down your studies", "t1 MOBILE BYTE arg out")
      check.INT (cs.v, 4321, "t1 SHARED CHAN INT arg")
  :
  --}}}
  --{{{  test2 -- recursive PAR
  PROC test2 ()
    REC PROC factorial (VAL INT n, CHAN INT in?, out!)
      IF
        n < 2
          INT v:
          SEQ
            in ? v
            out ! v
        TRUE
          CHAN INT thru:
          PAR
            factorial (n - 1, in?, thru!)
            INT v:
            SEQ
              thru ? v
              out ! v * n
    :

    CHAN INT in, out:
    INT v:
    SEQ
      PAR
        in ! 1
        factorial (1, in?, out!)
        out ? v
      check.INT (v, 1, "t2 factorial (1)")
      PAR
        in ! 1
        factorial (6, in?, out!)
        out ? v
      check.INT (v, 720, "t2 factorial (6)")
  :
  --}}}
  --}}}

  SEQ
    init ("CG test 91", "RECURSIVE PROCs")
    test0 ()
    test1 ()
    test2 ()
    finish ()
:

