--* From postmaster%watson.vnet.ibm.com@yktvmv.watson.ibm.com  Tue Jun  1 10:37:30 1993
--* Received: from yktvmv2.watson.ibm.com by radical.watson.ibm.com (AIX 3.2/UCB 5.64/900524)
--*           id AA17428; Tue, 1 Jun 1993 10:37:30 -0400
--* X-External-Networks: yes
--* Received: from watson.vnet.ibm.com by yktvmv.watson.ibm.com (IBM VM SMTP V2R3)
--*    with BSMTP id 8983; Tue, 01 Jun 93 10:38:04 EDT
--* Received: from YKTVMV by watson.vnet.ibm.com with "VAGENT.V1.0"
--*           id <A.SANTAS.NOTE.YKTVMV.0757.Jun.01.10:38:02.-0400>
--*           for asbugs@watson; Tue, 01 Jun 93 10:38:03 -0400
--* Received: from bernina.ethz.ch by watson.ibm.com (IBM VM SMTP V2R3) with TCP;
--*    Tue, 01 Jun 93 10:38:01 EDT
--* Received: from neptune by bernina.ethz.ch with SMTP inbound id <2735-0@bernina.ethz.ch>; Tue, 1 Jun 1993 16:37:45 +0200
--* From: Philip Santas <santas@inf.ethz.ch>
--* Received: from rutishauser.inf.ethz.ch (rutishauser-gw.inf.ethz.ch) by neptune id AA16151; Tue, 1 Jun 93 16:37:36 +0200
--* Date: Tue, 1 Jun 93 16:37:34 +0200
--* Message-Id: <9306011437.AA17507@rutishauser.inf.ethz.ch>
--* Received: from ru7.inf.ethz.ch.rutishauser by rutishauser.inf.ethz.ch id AA17507; Tue, 1 Jun 93 16:37:35 +0200
--* To: asbugs@watson.ibm.com
--* Subject: list
--* Cc: bronstein

--@ Fixed  by: SMW Wed Oct 13 16:21:05 1993
--@ Tested by: n/a
--@ Summary:   Handled by other fixes




-- The following program returns
-- "Bad foam reference in const 35:"
-- and many pages of foam code.
-- 
-- (the program is actually a small modification
-- of the code found in list.as)
-- 
-- Philip

----- Your original text is given second.  The text immediately below has
----- been updated with some name changes.   [SMW]
#assert UpdatedText

#if UpdatedText
------------------------------------------------------------------------------
--
-- list.as:  linked lists
--

#assert UseBasic
#include "aslib.as"

ListCategory S ==>

    nil: %
    empty: () -> %
    cons: (S, %) -> %
    list: Tuple S -> %
    list: Generator S -> %
    first: % -> S
    rest: % -> %
    setFirst!: (%, S) -> S
    setRest!: (%, %) -> %
    copy: % -> %
    last: % -> S
    reverse: % -> %
    reverse!: % -> %
    concat!: (%, %) -> %
    concat: (%, %) -> %
    reduce: ((S, S) -> S, %, S)  -> S
--    member?: (S, %) -> Boolean
    apply: (%, SingleInteger) -> S
    rest: (%, SingleInteger)  -> %

List(S: Type): with ListCategory S == add

    macro Rep0== P
    macro Rep == P
    macro R   == Record(first: S, rest: Rep0)

    P: with
            nil?:    % -> Boolean
            nilptr:  %
            recptr:  R -> %
            value:   % -> R
        == add
            macro  Rep == Pointer
            import Rep
            nil? (p: %): Boolean == nil? rep p
            nilptr: %        == per nil
            recptr(r: R): %  == r pretend %
            value(p: %): R   == p pretend R

    import R
    import S
    import Rep
    import Boolean
    import String

    default n: SingleInteger

    rec(x: %): R             == value rep x
    empty?(l: %): Boolean        == nil? rep l
    #(l: %): SingleInteger   == (n:=0; for i in l repeat n:=n+1; n)
    nil: %                   == per nilptr
    empty():%                == nil
    cons(a: S, l: %): %      == per recptr [a, rep l]
    list(its: Generator S): % == [its]
    list(tup: Tuple S): %    == [tup]
    map(f: S->S,   l: %): %      == [f(a)   for a in l]
    map(f:(S,S)->S,l1:%,l2:%): % == [f(a,b) for a in l1 for b in l2]
    first (l: %): S          == rec(l).first
    rest  (l: %): %          == per rec(l).rest
    setFirst!(l: %, a: S): S == rec(l).first := a
    setRest! (l: %, t: %): % == per (rec(l).rest := rep t)
    tail (l: %): % ==
       import String
       empty? l => error "empty list"
       x := l
       y := rest l
       while not empty? y repeat
          y := rest(x := y)
       x

    last (l: %): S == first tail l
    copy(l: %): % ==
       empty? l => l
       cons(first l, copy rest l)
    reverse(l: %): % ==
       revl := nil
       for e in l repeat revl := cons(e, revl)
       revl
    reverse!(l: %): % ==
            r := nil
            while l repeat
                    t := rest l
                    setRest!(l, r)
                    r := l
                    l := t
            r
    concat!(l1: %, l2: %): % ==
        empty? l1 => l2
        l := l1
        while (t := rest l) repeat l:=t
        setRest!(l, l2)
        l1
    concat(l1: %, l2: %): % ==
        empty? l1 => l2
        cons(first l1, concat(rest l1, l2))
    reduce(f: (S,S)->S, l: %, v: S): S ==
        ans := v
        for x in l repeat ans := f(ans, x)
        ans
    apply(l: %, i: SingleInteger): S ==
        import String
        for j in 1..(i-1) while l repeat l := rest l
        l => first l
        error "apply: too few elements in list"
    rest(l: %, i: SingleInteger): % ==
        for j in 1..i while l repeat l := rest l
        l
    test(l: %): Boolean == not empty? l
    generator(l: %): Generator S == generate
            while l repeat
                    yield first l
                    l := rest l
    [tu: Tuple S]: % ==
            l := nil
            for i in length tu..1 by -1 repeat
                    l := cons(element(tu,i), l)
            l
    [it: Generator S]: % ==
            h := l := nil
            for a in it repeat
                    t := l
                    l := cons(a, nil)
                    empty? t => h := l
                    setRest!(t, l)
            h

#else 
------------------------------------------------------------------------------
--
-- list.as:  linked lists
--

#assert UseBasic
#include "aslib.as"

ListCategory S ==>

    nil: %
    empty: () -> %
    cons: (S, %) -> %
    list: Tuple S -> %
    list: Iterator S -> %
    first: % -> S
    rest: % -> %
    setFirst!: (%, S) -> S
    setRest!: (%, %) -> %
    copy: % -> %
    last: % -> S
    reverse: % -> %
    reverse!: % -> %
    concat!: (%, %) -> %
    concat: (%, %) -> %
    reduce: ((S, S) -> S, %, S)  -> S
    member?: (S, %) -> Bit
    apply: (%, SingleInteger) -> S
    rest: (%, SingleInteger)  -> %

List(S: Type): with ListCategory S == add

    macro Rep0== P
    macro Rep == P
    macro R   == Record(first: S, rest: Rep0)

    P: with
            nil?:    % -> Bit
            nilptr:  %
            recptr:  R -> %
            value:   % -> R
        == add
            macro  Rep == Pointer
            import Rep
            nil? (p: %): Bit == nil? rep p
            nilptr: %        == per nil
            recptr(r: R): %  == r pretend %
            value(p: %): R   == p pretend R

    import R
    import S
    import Rep
    import Bit
    import String

    default n: SingleInteger

    rec(x: %): R             == value rep x
    empty?(l: %): Bit        == nil? rep l
    #(l: %): SingleInteger   == (n:=0; for i in l repeat n:=n+1; n)
    nil: %                   == per nilptr
    empty():%                == nil
    cons(a: S, l: %): %      == per recptr [a, rep l]
    list(its: Iterator S): % == [its]
    list(tup: Tuple S): %    == [tup]
    map(f: S->S,   l: %): %      == [f(a)   for a in l]
    map(f:(S,S)->S,l1:%,l2:%): % == [f(a,b) for a in l1 for b in l2]
    first (l: %): S          == rec(l).first
    rest  (l: %): %          == per rec(l).rest
    setFirst!(l: %, a: S): S == rec(l).first := a
    setRest! (l: %, t: %): % == per (rec(l).rest := rep t)
    tail (l: %): % ==
       import String
       empty? l => error "empty list"
       y := rest l
       while not empty? y repeat
          y := rest(x := y)
       x

    last (l: %): S == first tail l
    copy(l: %): % ==
       empty? l => l
       cons(first l, copy rest l)
    reverse(l: %): % ==
       revl := nil
       for e in l repeat revl := cons(e, revl)
       revl
    reverse!(l: %): % ==
            r := nil
            while l repeat
                    t := rest l
                    setRest!(l, r)
                    r := l
                    l := t
            r
    concat!(l1: %, l2: %): % ==
        empty? l1 => l2
        l := l1
        while (t := rest l) repeat l:=t
        setRest!(l, l2)
        l1
    concat(l1: %, l2: %): % ==
        empty? l1 => l2
        cons(first l1, concat(rest l1, l2))
    reduce(f: (S,S)->S, l: %, v: S): S ==
        ans := v
        for x in l repeat ans := f(ans, x)
        ans
    apply(l: %, i: SingleInteger): S ==
        import String
        for j in 1..(i-1) while l repeat l := rest l
        l => first l
        error "apply: too few elements in list"
    rest(l: %, i: SingleInteger): % ==
        for j in 1..i while l repeat l := rest l
        l
    test(l: %): Bit == not empty? l
    iterator(l: %): Iterator S == iterate
            while l repeat
                    yield first l
                    l := rest l
    [tu: Tuple S]: % ==
            l := nil
            for i in #tu..1 by -1 repeat
                    l := cons(tu.i, l)
            l
    [it: Iterator S]: % ==
            h := l := nil
            for a in it repeat
                    t := l
                    l := cons(a, nil)
                    empty? t => h := l
                    setRest!(t, l)
            h
#endif
 
--+ Script started on Wed Oct 13 16:19:33 1993$ asharp -O -M2 -Wcheck bug298.as
--+ $ ^D
--+ 
