--* From BMT%WATSON.vnet.ibm.com@yktvmh.watson.ibm.com  Thu Dec  9 18:10:27 1993
--* Received: from yktvmh.watson.ibm.com by leonardo.watson.ibm.com (AIX 3.2/UCB 5.64/4.03)
--*           id AA14494; Thu, 9 Dec 1993 18:10:27 -0500
--* Received: from watson.vnet.ibm.com by yktvmh.watson.ibm.com (IBM VM SMTP V2R3)
--*    with BSMTP id 1871; Thu, 09 Dec 93 18:16:40 EST
--* Received: from YKTVMH by watson.vnet.ibm.com with "VAGENT.V1.0"
--*           id <A.BMT.NOTE.VAGENT2.9387.Dec.09.18:16:39.-0500>
--*           for asbugs@watson; Thu, 09 Dec 93 18:16:40 -0500
--* Received: from YKTVMH by watson.vnet.ibm.com with "VAGENT.V1.0"
--*           id 9385; Thu, 9 Dec 1993 18:16:39 EST
--* Received: from cyst.watson.ibm.com by yktvmh.watson.ibm.com (IBM VM SMTP V2R3)
--*    with TCP; Thu, 09 Dec 93 18:16:38 EST
--* Received: from spadserv.watson.ibm.com by cyst.watson.ibm.com (AIX 3.2/UCB 5.64/900528)
--*   id AA65592; Thu, 9 Dec 1993 18:16:13 -0500
--* Received: by spadserv.watson.ibm.com (AIX 3.2/UCB 5.64/900524)
--*           id AA12288; Thu, 9 Dec 1993 18:17:56 -0500
--* Date: Thu, 9 Dec 1993 18:17:56 -0500
--* From: bmt@spadserv.watson.ibm.com
--* X-External-Networks: yes
--* Message-Id: <9312092317.AA12288@spadserv.watson.ibm.com>
--* To: asbugs@watson.ibm.com
--* Subject: [5] compiler takes a program fault (segmentation violation) [axlib.as][33.0 (current)]

--@ Fixed  by:  PI   Mon Apr 25 20:53:42 EDT 1994 
--@ Tested by:  none 
--@ Summary:    It should be no more a bug (I tested also on Linux, that is Sun-like). 


--
-- axlib.as
--

--#include "asmacros"
macro {
	rep x == x @ % pretend Rep;
	per r == r @ Rep pretend %;

	BBool == Bool$Machine;
	BChar == Char$Machine;
	BArr  == Arr$Machine;
	BPtr  == Ptr$Machine;
	BByte == XByte$Machine;
	BHInt == HInt$Machine;
	BSInt == SInt$Machine;
	BBInt == BInt$Machine;
	BSFlo == SFlo$Machine;
	BDFlo == DFlo$Machine;
}

--#include "asbase"
#	library LangLib "lang.aso"
#	library MachLib "machine.aso"
--#	library TupleLib "tuple.aso"
	import LangLib;
	import MachLib;
--	import TupleLib;


export Integer:OrderedRing();
export SmallInteger:OrderedRing();
export DoubleFloat:with;
export Float : with;
export String : with;
export Boolean : with;

export SingleInteger:OrderedRing()
SingleInteger:OrderedRing() == SmallInteger add;

--- Literal support ------
import Foreign(Lisp) : with {
    litToString: Literal -> String; -- strips trailing null
    stringToFloat: String -> Float;
}

integer(l: Literal): Integer == convert(l pretend BArr)$Machine@BBInt pretend Integer;
integer(l: Literal): SingleInteger ==
    convert(l pretend BArr)$Machine@BSInt pretend SingleInteger;
string(l: Literal): String == litToString l;
float(l: Literal): DoubleFloat == convert(l pretend BArr)$Machine@BDFlo pretend DoubleFloat;
float(l: Literal): Float == stringToFloat string l;

--------- Generator support ---------------------------

Generator(T: Type): with == add;

OrderedRing() : Category ==  with {
                0     : % ;
                1     : % ;
                +     : (%,%) -> % ;
                -     : (%,%) -> % ;
                -     : % -> % ;
                <     : (%,%) -> Boolean ;
                <=    : (%,%) -> Boolean ;
                >=    : (%,%) -> Boolean ;
}

export UniversalSegment: (S:Type) -> with {
    low: % -> S;
    high: % -> S;
    incr: % -> S;
    hasHi: % -> Boolean;
    ..: S -> %;
    by: (%, S) -> %;
}

UniSegGen(S:OrderedRing()) : with {generator : UniversalSegment(S) -> Generator(S)} == add
   import S
   generator( s: UniversalSegment(S)): Generator S == generate {
	a := low  s;
	b := high s;
	d := incr s;
	hasHi s =>		repeat (yield a; a := a + d);
	d >= 0	=> while a <= b repeat (yield a; a := a + d);
	d <  0	=> while a >= b repeat (yield a; a := a + d);
	}

export Segment: (S:Type) -> with {
    low: % -> S;
    high: % -> S;
    incr: % -> S;
    ..: (S, S) -> %;
    by: (%, S) -> %;
}

SegGen(S:OrderedRing()) : with {generator : Segment(S) -> Generator(S)} == add
   import S
   generator( s: Segment(S)): Generator S == generate {
	a := low  s;
	b := high s;
	d := incr s;
	d >= 0	=> while a <= b repeat (yield a; a := a + d);
	d <  0	=> while a >= b repeat (yield a; a := a + d);
	}

import SegGen(Integer)
--import SegGen(SingleInteger)
import UniSegGen(Integer)
--import UniSegGen(SingleInteger)

UnaryRecursiveAggregate(S:Type):Category == with {
   empty? : % -> Boolean;
   first  : % -> S;
   rest   : % -> %;
   empty  : () -> %;
   concat : (S, %) -> %;
   setrest! : (%, %) -> %;
}

ListGen(S:Type, LS : UnaryRecursiveAggregate(S)) : with
     generator : LS -> Generator S
     bracket:  Generator S -> LS;
--     bracket:  Tuple S -> LS;

  == add {
        generator(l: LS): Generator S == generate {
                while not empty? l repeat {
                        yield first l;
                        l := rest l;
                }
        }
--        [t: Tuple S]: LS == {
--                l := empty();
--                import SingleInteger;
--                import Segment SingleInteger;
--                for i in length t..1 by -1 repeat
--                        l := concat(element(t, i), l);
--                l;
--        }

        [g: Generator S]: LS == {
                h := l := empty();
                for a in g repeat {
                        t := l;
                        l := concat(a, empty());
                        empty? t => h := l;
                        setrest!(t, l);
                }
                h;
        }

}
 
