root/trunk/Library/FortressLibrary.fss @ 2715

Revision 2715, 156.8 KB (checked in by nbeckman, 15 months ago)

[typechecker,useful] Three changes:
- New class TypeCheckerOutput? will hold the old Node to TypeEnv? mapping.
- Created empty and singleton versions of MultiMap?.
- Improved error messages in the typechecker.

Line 
1(*******************************************************************************
2    Copyright 2008 Sun Microsystems, Inc.,
3    4150 Network Circle, Santa Clara, California 95054, U.S.A.
4    All rights reserved.
5
6    U.S. Government Rights - Commercial software.
7    Government users are subject to the Sun Microsystems, Inc. standard
8    license agreement and applicable provisions of the FAR and its supplements.
9
10    Use is subject to license terms.
11
12    This distribution may include materials developed by third parties.
13
14    Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered
15    trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
16 ******************************************************************************)
17
18component FortressLibrary
19import NativeArray.{...}
20import NatReflect.{...}
21import JavaString.{...}
22import List.{AnyList}
23
24export FortressLibrary
25
26(************************************************************
27* Simple Combinators
28************************************************************)
29
30(** Casting *)
31
32cast[\T extends Any\](x:Any):T =
33  typecase x of
34    T => x
35    else => throw CastError
36  end
37
38instanceOf[\T extends Any\](x:Any):Boolean =
39  typecase x of
40    T => true
41    else => false
42  end
43
44(** Useful functions *)
45
46ignore(_:Any):() = ()
47
48identity[\T extends Any\](x:T):T = x
49
50(* Should we depracate tuple and use identity instead?  Decision: no. *)
51tuple[\T\](x:T):T = x
52
53(* Function composition *)
54opr COMPOSE[\A,B,C\](f: B->C, g: A->B): A->C = fn (a:A): C => f(g(a))
55
56(** Reflection of static type parameters for overloading purposes.
57    Works around shortcomings in the story on parametric overloading
58    (all overloadings must have the same parameters with the same
59    bounds).  Allows us to overload a function based on the parametric
60    type of an output. *)
61
62object __Proxy[\T extends (* U *) Any\]
63    (* extends { __Proxy[\U\], Object } where { U extends Any } *)
64  getter toString() = "__Proxy object, should not be user-visible."
65end
66
67fail[\T\](s:String):T = do
68   println("FAIL: " s)
69   (* throwError(s) *)
70   throw FailCalled(s)
71end
72
73(************************************************************
74* Control over locality and location
75************************************************************)
76
77(* At the moment all Fortress objects are immediately shared by default. *)
78
79shared[\T extends Any\](x:T): T = x
80
81isShared(x:Any): Boolean = true
82
83localize[\T extends Any\](x:T): T = x
84
85(* copy is presently unimplemented.
86copy[\T extends Any\](x:T): T =
87*)
88
89trait Region extends Equality[\Region\]
90    getter toString(): String
91    isLocalTo(r: Region): Boolean = false
92    opr =(self, other:Region): Boolean = self SEQV other
93end
94
95object Global extends Region
96    getter toString(): String = "Global"
97    isLocalTo(_: Region): Boolean = true
98end
99
100region(a:Any): Region = Global
101
102here(): Region = Global
103
104(************************************************************
105* Equality and ordering
106************************************************************)
107
108opr =(a:Any, b:Any):Boolean = a SEQV b
109
110opr =/=(a:Any, b:Any):Boolean = NOT (a=b)
111
112trait Equality[\Self extends Equality[\Self\]\]
113    opr =(self, other:Self): Boolean
114end
115
116(** Total ordering *)
117
118object LexicographicPartialReduction
119        extends { MonoidReduction[\Comparison\],
120                  ReductionWithZeroes[\Comparison, Comparison\] }
121    getter toString():String = "Lexicographic reduction on partial order"
122    empty(): Comparison = EqualTo
123    join(a:Comparison, b:Comparison):Comparison = a LEXICO b
124    isZero(_:Unordered): Boolean = true
125    isZero(_:Comparison): Boolean = false
126end
127
128object LexicographicReduction
129        extends { MonoidReduction[\TotalComparison\],
130                  ReductionWithZeroes[\TotalComparison, TotalComparison\] }
131    getter toString():String = "Lexicographic reduction on total order"
132    empty(): TotalComparison = EqualTo
133    join(a:TotalComparison, b:TotalComparison):TotalComparison = a LEXICO b
134    isLeftZero(_:EqualTo): Boolean = false
135    isLeftZero(_:Comparison): Boolean = true
136end
137
138trait Comparison
139        extends { StandardPartialOrder[\Comparison\] }
140        comprises { Unordered, TotalComparison }
141    getter toString(): String
142    opr =(self, other:Comparison): Boolean = false
143    opr LEXICO(self, other:Comparison): Comparison = Unordered
144    opr INVERSE(self): Comparison
145end
146
147(** Unordered is the outcome of a CMP b when a and b are partially
148    ordered and no ordering relationship exists between them. **)
149object Unordered extends Comparison
150    getter toString(): String = "Unordered"
151    opr =(self, other:Unordered): Boolean = true
152    opr <(self, other:Comparison): Boolean = false
153    opr INVERSE(self): Comparison = Unordered
154end
155
156trait TotalComparison
157        extends { Comparison, StandardTotalOrder[\TotalComparison\] }
158        comprises { LessThan, EqualTo, GreaterThan }
159    (* We're both a partial order (including Unordered) and a total
160       order (TotalComparison alone).  Avoid ambiguity between the
161       default definitions of CMP and >=. *)
162    opr =(self, other:TotalComparison): Boolean = false
163    opr =(self, other:Unordered): Boolean = false
164    opr CMP(self, other:Unordered): Comparison = Unordered
165    opr <(self, other:Unordered): Boolean = false
166    opr >=(self, other:Unordered): Boolean = false
167    opr >=(self, other:Comparison): Boolean = NOT (other < self)
168    opr LEXICO(self, other:TotalComparison): TotalComparison = self
169    opr LEXICO(self, other:()->TotalComparison): TotalComparison = self
170    opr INVERSE(self): TotalComparison
171end
172
173object LessThan extends TotalComparison
174    getter toString(): String = "LessThan"
175    opr =(self, other:LessThan): Boolean = true
176    opr CMP(self, other:LessThan): TotalComparison = EqualTo
177    opr CMP(self, other:TotalComparison): TotalComparison = GreaterThan
178    opr <(self, other:LessThan): Boolean = false
179    opr <(self, other:TotalComparison): Boolean = true
180    opr INVERSE(self): TotalComparison = GreaterThan
181end
182
183object GreaterThan extends TotalComparison
184    getter toString(): String = "GreaterThan"
185    opr =(self, other:GreaterThan): Boolean = true
186    opr CMP(self, other:GreaterThan): TotalComparison = EqualTo
187    opr CMP(self, other:TotalComparison): TotalComparison = LessThan
188    opr <(self, other:TotalComparison): Boolean = false
189    opr INVERSE(self): TotalComparison = LessThan
190end
191
192object EqualTo extends TotalComparison
193    getter toString(): String = "EqualTo"
194    opr =(self, other:EqualTo): Boolean = true
195    opr CMP(self, other:TotalComparison): TotalComparison = INVERSE other
196    opr <(self, other:GreaterThan): Boolean = true
197    opr <(self, other:TotalComparison): Boolean = false
198    opr LEXICO(self, other:TotalComparison): TotalComparison = other
199    opr LEXICO(self, other:()->TotalComparison): TotalComparison = other()
200    opr INVERSE(self): TotalComparison = EqualTo
201end
202
203(** StandardPartialOrder is partial ordering using <,>,<=,>=,=, and CMP.
204    This is primarily for floating-point values.  Minimal complete
205    definition: CMP or { <, = }. **)
206trait StandardPartialOrder[\Self extends StandardPartialOrder[\Self\]\]
207        extends { Equality[\Self\] }
208    opr CMP(self, other:Self): Comparison =
209        if self < other then LessThan
210        elif other > self then GreaterThan
211        elif self = other then EqualTo
212        else Unordered
213        end
214    opr <(self, other:Self): Boolean = LessThan = (self CMP other)
215    opr >(self, other:Self): Boolean = other < self
216    opr =(self, other:Self): Boolean = EqualTo = (self CMP other)
217    opr <=(self, other:Self): Boolean = other >= self
218    opr >=(self, other:Self): Boolean = (self = other OR: self > other)
219end
220
221(** %StandardMin% is a MIN operator; most types that implement %MIN%
222    will implement a corresponding total order.  It's a separate type
223    to account for the existence of floating point numbers, for which
224    NaN counts as a bottom that is less than anything else but doesn't
225    actually participate in the standard total ordering.  It is
226    otherwise the case that %a MIN b = a% when %a <= b% and that
227    %a MIN b = b MIN a%. **)
228trait StandardMin[\T extends StandardMin[\T\]\]
229    opr MIN(self, other:T): T
230end
231
232(** %StandardMax% is a MAX operator; most types that implement %MAX%
233    will implement a corresponding total order.  It's a separate type
234    to account for the existence of floating point numbers, for which
235    NaN counts as a bottom that is less than anything else but doesn't
236    actually participate in the standard total ordering.  It is
237    otherwise the case that %a MAX b = a% when %a <= b% and that
238    %a MAX b = b MAX a%. **)
239trait StandardMax[\T extends StandardMax[\T\]\]
240    opr MAX(self, other:T): T
241end
242
243(** StandardTotalOrder is the usual total order using <,>,<=,>=,=, and
244    CMP.  Most values that define a comparison should do so using
245    this.  Minimal complete definition: either CMP or < (it's
246    advisable to define = in the latter case).  As noted above, %MIN%
247    and %MAX% respect the total order and are defined in the obvious
248    way. **)
249trait StandardTotalOrder[\Self extends StandardTotalOrder[\Self\]\]
250        extends { StandardPartialOrder[\Self\], StandardMin[\Self\], StandardMax[\Self\] }
251    opr CMP(self, other:Self): TotalComparison =
252        if self < other then LessThan
253        elif other < self then GreaterThan
254        else EqualTo
255        end
256    opr >=(self, other:Self): Boolean = NOT (self < other)
257    opr <=(self, other:Self): Boolean = NOT (other < self)
258    opr MIN(self, other:Self): Self = if other < self then other else self end
259    opr MAX(self, other:Self): Self = if self < other then other else self end
260end
261
262(** Assertion *)
263assert(flag:Boolean): () =
264    if NOT flag then
265        fail("Assertion failed!")
266    end
267
268assert(flag: Boolean, failMsg: String): () =
269    if NOT flag then
270        fail(failMsg)
271    end
272
273assert(x:Any, y:Any, failMsg: Any...): () =
274    if x =/= y then
275        msg = x " =/= " y "; " (BIG || failMsg)
276        fail(msg)
277    end
278   
279deny(flag:Boolean): () = assert(NOT flag)
280
281deny(flag: Boolean, failMsg: String): () = assert(NOT flag, failMsg)
282
283deny(x:Any, y:Any, failMsg: Any...): () =
284    if x = y then
285        msg = x " = " y "; " (BIG || failMsg)
286        fail(msg)
287    end
288   
289shouldRaise⟦Ex extends Exception⟧ (expr: ()→()): () = do
290    try
291        expr()
292        throw ForbiddenException
293    catch x
294        Ex => assert(true) (* This is what we hope for *)
295    forbid Exception
296    end
297end
298       
299
300(************************************************************
301* Numeric hierarchy
302************************************************************)
303
304(** Additive group making use of +.  Must define + and either unary or binary -. **)
305trait AdditiveGroup[\Self extends AdditiveGroup[\Self\]\]
306    getter zero(): Self = self - self
307    opr +(self, other: Self): Self
308    opr -(self, other: Self): Self = self + (-other)
309    opr -(self) : Self = self.zero - self
310end
311
312(** Place holder for exclusions of MultiplicativeRing **)
313trait AnyMultiplicativeRing end
314
315(** Multiplicative ring using TIMES and juxtaposition.
316    Define opr TIMES; juxtaposition is defined in terms of TIMES. **)
317trait MultiplicativeRing[\Self extends MultiplicativeRing[\Self\]\]
318        extends { AdditiveGroup[\Self\], AnyMultiplicativeRing }
319    getter one(): Self
320    opr TIMES(self, other:Self): Self
321    opr juxtaposition(self, other:Self): Self = self TIMES other
322    (** Exponentiation need only deal with natural exponents. **)
323    opr ^(self, other:AnyIntegral): Self
324end
325
326(** The use of StandardTotalOrder here is a lie; it will have to suffice
327    until we can deal gracefully with NaNs disobeying the ordering rules
328    (and even the equivalence rules for = and =/=). **)
329trait Number
330        extends { StandardPartialOrder[\Number\], StandardMin[\Number\], StandardMax[\Number\],
331                  AdditiveGroup[\Number\], MultiplicativeRing[\Number\] }
332        comprises { RR64 }
333    getter zero(): Number = 0.0
334    getter one(): Number = 1.0
335    getter toString(): String
336    opr |self| : Number =
337        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Abs")
338    opr =(self, b:Number):Boolean =
339        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Eq")
340    opr =/=(self, b:Number):Boolean =
341        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$NEq")
342    opr <(self, b:Number):Boolean =
343        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Less")
344    opr <=(self, b:Number):Boolean =
345        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$LessEq")
346    opr >(self, b:Number):Boolean =
347        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Greater")
348    opr >=(self, b:Number):Boolean =
349        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$GreaterEq")
350    opr CMP(self, b:Number):Comparison =
351        if self<b then LessThan
352        elif self>b then GreaterThan
353        elif self=b then EqualTo
354        else Unordered
355        end
356    (** In case of NaN, %MIN% and %MAX% return a NaN, otherwise it respects the
357        total order. **)
358    opr MIN(self, b:Number):Number =
359        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Min")
360    opr MAX(self, b:Number):Number =
361        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Max")
362
363    opr -(self):RR64 =
364        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Negate")
365    opr +(self,b:Number):RR64 =
366        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Add")
367    opr -(self,b:Number):RR64 =
368        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Sub")
369    opr DOT(self,b:Number):RR64 =
370        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Mul")
371    opr TIMES(self,b:Number):RR64 =
372        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Mul")
373    opr juxtaposition
374         (self,b:Number):RR64 =
375        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Mul")
376    opr /(self,b:Number):RR64 =
377        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Div")
378    opr SQRT(self):RR64 =
379        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Sqrt")
380    opr PLUS_UP(self,b:Number):RR64 =
381        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$AddUpNoNaN")
382    opr MINUS_UP(self,b:Number):RR64 =
383        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$SubUpNoNaN")
384    opr DOT_UP(self,b:Number):RR64 =
385        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$MulUpNoNaN")
386    opr SLASH_UP(self,b:Number):RR64 =
387        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$DivUpNoNaN")
388    opr SQRT_UP(self):RR64 =
389        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$SqrtUp")
390    opr PLUS_DOWN(self,b:Number):RR64 =
391        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$AddDownNoNaN")
392    opr MINUS_DOWN(self,b:Number):RR64 =
393        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$SubDownNoNaN")
394    opr DOT_DOWN(self,b:Number):RR64 =
395        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$MulDownNoNaN")
396    opr SLASH_DOWN(self,b:Number):RR64 =
397        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$DivDownNoNaN")
398    opr SQRT_DOWN(self):RR64 =
399        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$SqrtDown")
400    opr IEEE_PLUS_UP(self,b:Number):RR64 =
401        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$AddUp")
402    opr IEEE_MINUS_UP(self,b:Number):RR64 =
403        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$SubUp")
404    opr IEEE_DOT_UP(self,b:Number):RR64 =
405        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$MulUp")
406    opr IEEE_SLASH_UP(self,b:Number):RR64 =
407        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$DivUp")
408    opr IEEE_PLUS_DOWN(self,b:Number):RR64 =
409        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$AddDown")
410    opr IEEE_MINUS_DOWN(self,b:Number):RR64 =
411        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$SubDown")
412    opr IEEE_DOT_DOWN(self,b:Number):RR64 =
413        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$MulDown")
414    opr IEEE_SLASH_DOWN(self,b:Number):RR64 =
415        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$DivDown")
416    opr ^(self, b:Number):RR64 =
417        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Pow")
418    (** Shouldn't need this extra declaration. **)
419    opr ^(self, b:AnyIntegral):RR64 =
420        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Pow")
421    sin(self):RR64 =
422        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Sin")
423    cos(self):RR64 =
424        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Cos")
425    tan(self):RR64 =
426        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Tan")
427    asin(self):RR64 =
428        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$ASin")
429    acos(self):RR64 =
430        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$ACos")
431    atan(self):RR64 =
432        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$ATan")
433    atan2(self,x:Number):RR64 =
434        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$ATan2")
435    log(self):RR64 =
436        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Log")
437    exp(self):RR64 =
438        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Exp")
439    floor(self):RR64 =
440        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Floor")
441    opr |\self/| : ZZ64 =
442        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$IFloor")
443    ceiling(self):RR64 =
444        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Ceiling")
445    opr |/self\| : ZZ64 =
446        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$ICeiling")
447    truncate(self):ZZ64 =
448        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Truncate")
449end
450
451trait RR64 extends Number comprises { Float, AnyIntegral, FloatLiteral }
452    (** returns true if the value is an IEEE NaN **)
453    getter isNaN(): Boolean =
454        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$isNaN")
455    (** returns true if the value is an IEEE infinity **)
456    getter isInfinite(): Boolean =
457        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$isInfinite")
458    (** returns true if the value is a valid number (not NaN) **)
459    getter isNumber(): Boolean = NOT self.isNaN
460    (** returns true if the value is finite **)
461    getter isFinite(): Boolean = NOT (self.isInfinite OR self.isNaN)
462    (** check returns Just(its argument) if it is finite, otherwise Nothing. **)
463    getter check(): Maybe[\RR64\] =
464        if self.isFinite then Just[\RR64\](self) else Nothing[\RR64\] end
465    (** check_star returns Just(its argument) if it is non-NaN, otherwise Nothing. **)
466    getter check_star(): Maybe[\RR64\] =
467        if self.isNaN then Nothing[\RR64\] else Just[\RR64\](self) end
468    (** obtain the raw bits of the IEEE floating-point representation of this value. **)
469    getter rawBits():ZZ64 =
470        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$RawBits")
471    getter signBit():ZZ32 = if rawBits() < 0 then 1 else 0 end
472    (** next higher IEEE float **)
473    getter nextUp():RR64 =
474        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$NextUp")
475    (** next lower IEEE float **)
476    getter nextDown():RR64 =
477        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$NextDown")
478    (** %MINNUM% and %MAXNUM% return a numeric result where possible (avoiding NaN).
479        Note that %MINNUM% and %MAX% form a lattice with NaN at the top, and
480        that %MAXNUM% and %MIN% form a lattice with NaN at the bottom.  **)
481    opr MINNUM(self, b:RR64):RR64 = do
482        r = self MIN b
483        if r.isNaN then
484            if self.isNumber then self
485            elif b.isNumber then b
486            else r end
487        else
488            r
489        end
490      end
491    opr MAXNUM(self, b:RR64):RR64 = do
492        r = self MAX b
493        if r.isNaN then
494            if self.isNumber then self
495            elif b.isNumber then b
496            else r end
497        else
498            r
499        end
500      end
501    (** returns a value of type RR32 **)
502    narrow(self): RR32 =
503        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Narrow")
504end
505
506trait QQ extends { RR64, StandardPartialOrder[\QQ\] }
507    getter zero(): QQ = 0
508    getter one(): QQ = 1
509    getter isNaN(): Boolean
510    getter isInfinite(): Boolean
511    getter isNumber(): Boolean = NOT self.isNaN
512    getter isFinite(): Boolean = (denominator(self) =/= 0)
513    numerator(self): ZZ
514    denominator(self): ZZ  (* Ideally would be NN *)
515    opr |self| : QQ = |numerator(self)| / denominator(self)
516    (* Note that 0/0 = 0/0 is supposed to be true (//unlike// the behavior of floating-point NaN) *)
517    opr =(self, other:QQ):Boolean =
518        numerator(self) = numerator(other) AND: denominator(self) = denominator(other)
519    opr =/=(self, other:QQ):Boolean = NOT (self = other)
520    opr <(self, other:QQ):Boolean = do
521        (a, b) = (numerator(self), denominator(self))
522        (c, d) = (numerator(other), denominator(other))
523        (b=0 AND d=0 AND a=-1 AND c=1) OR (a d < b c)
524    end
525    opr <=(self, other:QQ):Boolean = (self < other) OR (self = other)
526    opr >(self, other:QQ):Boolean = (other < self)
527    opr >=(self, other:QQ):Boolean = (other <= self)
528    (** In case of 0/0, %MIN% and %MAX% return 0/0, otherwise it respects the
529        total order. **)
530    opr MIN(self, other:QQ):QQ =
531        if self < other then self elif other < self then other elif self = 0/0 then self else other end
532    opr MAX(self, other:QQ):QQ =
533        if self > other then self elif other > self then other elif self = 0/0 then self else other end
534
535    opr -(self):QQ = (-numerator(self)) / denominator(self)
536    opr +(self,other:QQ):QQ =
537        if self = other AND denominator(self) = 0 then self else
538            (a, b) = (numerator(self), denominator(self))
539            (c, d) = (numerator(other), denominator(other))
540            (a d + b c) / b d
541        end
542    opr -(self,other:QQ):QQ = self + (-other)
543    opr DOT(self,other:QQ):QQ = do
544        (a, b) = (numerator(self), denominator(self))
545        (c, d) = (numerator(other), denominator(other))
546        a c / b d
547    end
548    opr TIMES(self,other:QQ):QQ = self DOT other
549    opr juxtaposition (self,other:QQ):QQ = self DOT other
550    opr /(self,other:QQ):QQ = do
551        (a, b) = (numerator(self), denominator(self))
552        (c, d) = (numerator(other), denominator(other))
553        a d / b c
554    end
555    opr ^(self, other:AnyIntegral):QQ =
556        if -other > 0 then   (* Way too clever by half (to avoid infinite recursion on 2^(-63)) *)
557            (denominator(self)/numerator(self))^(-other)
558        else
559            (numerator(self))^other / (denominator(self))^other
560        end
561    floor(self):ZZ = if self < 0 then -ceiling(-self) else truncate(self) end
562    opr |\self/| : ZZ = floor(self)
563    ceiling(self):ZZ = if denominator(self) = 0 then self else
564        (a, b) = (numerator(self), denominator(self))
565        if a < 0 then -floor(-self) else (a + b - 1) DIV b end
566    end
567    opr |/self\| : ZZ = ceiling(self)
568    truncate(self):ZZ = if denominator(self) = 0 then self else numerator(self) DIV denominator(self) end
569    round(self): ZZ = do x = self + 1/2; z = floor(x); if z = x AND odd z then z-1 else z end end
570    opr MINNUM(self, other:QQ):QQ =
571        if self < other then self elif other < self then other elif self = 0/0 then other else self end
572    opr MAXNUM(self, other:QQ):QQ =
573        if self > other then self elif other > self then other elif self = 0/0 then other else self end
574end
575
576object Ratio(num: ZZ, den: ZZ) extends { QQ }
577    getter toString(): String = num.toString || "/" || den.toString
578    getter isNaN(): Boolean = (numerator(self) = 0 AND denominator(self) = 0)
579    getter isInfinite(): Boolean = (numerator(self) =/= 0 AND denominator(self) = 0)
580    numerator(self):ZZ = num
581    denominator(self):ZZ = den
582end
583
584trait AnyIntegral extends { QQ } end
585
586trait Integral[\I extends Integral[\I\]\] extends { StandardTotalOrder[\I\], AnyIntegral }
587    getter zero(): I
588    getter one(): I
589    getter isNaN(): Boolean = false
590    getter isInfinite(): Boolean = false  (* For now, no infinite integers. *)
591    denominator(self):ZZ = 1
592    opr -(self):I
593    opr +(self,b:I):I
594    opr -(self,b:I):I
595    opr DOT(self,b:I):I
596    opr TIMES(self,b:I):I
597    opr juxtaposition(self,b:I):I
598    opr DIV(self,b:I):I
599    opr REM(self,b:I):I
600    opr MOD(self,b:I):I
601    opr GCD(self,b:I):I
602    opr LCM(self,b:I):I
603    opr DIVIDES(self,b:I):Boolean = b =/= zero() AND: (b MOD self) = zero()
604    opr CHOOSE(self,b:I):I
605    opr BITAND(self,b:I):I
606    opr BITOR(self,b:I):I
607    opr BITXOR(self,b:I):I
608    opr LSHIFT(self,b:AnyIntegral):I
609    opr RSHIFT(self,b:AnyIntegral):I
610    opr BITNOT(self):I
611    opr ^(self, b:AnyIntegral):RR64
612end
613
614trait ZZ32 extends { ZZ64, Integral[\ZZ32\] } comprises { Int, IntLiteral }
615    getter zero(): ZZ32 = 0
616    getter one(): ZZ32 = 1
617    getter minimum(): ZZ32 = -2147483647 - 1
618    getter maximum(): ZZ32 = 2147483647
619       
620    opr |self| : ZZ32 = if self>=0 then self else -self end
621    opr =(self, b:ZZ32):Boolean =
622        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Eq")
623    opr <(self, b:ZZ32):Boolean =
624        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Less")
625
626    opr -(self):ZZ32 =
627        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Negate")
628    opr +(self,b:ZZ32):ZZ32 =
629        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Add")
630    opr -(self,b:ZZ32):ZZ32 =
631        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Sub")
632    opr DOT(self,b:ZZ32):ZZ32 =
633        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Mul")
634    opr TIMES(self,b:ZZ32):ZZ32 =
635        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Mul")
636    opr juxtaposition(self,b:ZZ32):ZZ32 =
637        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Mul")
638    opr DIV(self,b:ZZ32):ZZ32 =
639        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Div")
640    opr REM(self,b:ZZ32):ZZ32 =
641        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Rem")
642    opr MOD(self,b:ZZ32):ZZ32 =
643        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Mod")
644    opr GCD(self,b:ZZ32):ZZ32 =
645        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Gcd")
646    opr LCM(self,b:ZZ32):ZZ32 =
647        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Lcm")
648    opr CHOOSE(self,b:ZZ32):ZZ32 =
649        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Choose")
650    opr BITAND(self,b:ZZ32):ZZ32 =
651        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$BitAnd")
652    opr BITOR(self,b:ZZ32):ZZ32 =
653        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$BitOr")
654    opr BITXOR(self,b:ZZ32):ZZ32 =
655        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$BitXor")
656    opr LSHIFT(self,b:ZZ64):ZZ32 =
657        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$LShift")
658    opr RSHIFT(self,b:ZZ64):ZZ32 =
659        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$RShift")
660    opr BITNOT(self):ZZ32 =
661        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$BitNot")
662    opr ^(self, b:AnyIntegral):RR64 =
663        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Pow")
664    widen(self):ZZ64 =
665        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$ToLong")
666    partitionL(self):ZZ32 =
667        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Int$Partition")
668    unsigned(self):NN32 =
669        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.ZZ32$ToNN32")
670end
671
672trait ZZ64 extends { ZZ, Integral[\ZZ64\] } comprises { Long, ZZ32 }
673    getter zero(): ZZ64 = widen(0)
674    getter one(): ZZ64 = widen(1)
675    getter minimum(): ZZ64 = -9223372036854775807 - 1
676    getter maximum(): ZZ64 = 9223372036854775807
677
678    opr |x:ZZ64| : ZZ64 = if x>=0 then x else -x end
679
680    opr =(self, b:ZZ64):Boolean =
681        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Eq")
682    opr <(self, b:ZZ64):Boolean =
683        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Less")
684    (* Argh!  Due to method ambiguities with ZZ, these definitions must be given
685       explicitly here. *)
686    opr >(self, b:ZZ64):Boolean = b < self
687    opr >=(self, b:ZZ64):Boolean = NOT (self < b)
688    opr <=(self, b:ZZ64):Boolean = NOT (b < self)
689    opr CMP(self, b:ZZ64): TotalComparison =
690        if self < b then LessThan
691        elif b < self then GreaterThan
692        else EqualTo end
693
694    opr -(self):ZZ64 =
695        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Negate")
696    opr +(self,b:ZZ64):ZZ64 =
697        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Add")
698    opr -(self,b:ZZ64):ZZ64 =
699        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Sub")
700    opr DOT(self,b:ZZ64):ZZ64 =
701        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Mul")
702    opr TIMES(self,b:ZZ64):ZZ64 =
703        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Mul")
704    opr juxtaposition(self,b:ZZ64):ZZ64 =
705        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Mul")
706    opr DIV(self,b:ZZ64):ZZ64 =
707        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Div")
708    opr REM(self,b:ZZ64):ZZ64 =
709        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Rem")
710    opr MOD(self,b:ZZ64):ZZ64 =
711        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Mod")
712    opr GCD(self,b:ZZ64):ZZ64 =
713        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Gcd")
714    opr LCM(self,b:ZZ64):ZZ64 =
715        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Lcm")
716    opr CHOOSE(self,b:ZZ64):ZZ64 =
717        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Choose")
718    opr BITAND(self,b:ZZ64):ZZ64 =
719        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$BitAnd")
720    opr BITOR(self,b:ZZ64):ZZ64 =
721        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$BitOr")
722    opr BITXOR(self,b:ZZ64):ZZ64 =
723        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$BitXor")
724    opr LSHIFT(self,b:AnyIntegral):ZZ64 =
725        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$LShift")
726    opr RSHIFT(self,b:AnyIntegral):ZZ64 =
727        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$RShift")
728    opr BITNOT(self):ZZ64 =
729        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$BitNot")
730    opr ^(self, b:AnyIntegral):RR64 =
731        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Pow")
732    partitionL(self):ZZ64 =
733        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$Partition")
734    narrow(self):ZZ32 =
735        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$FromLong")
736    unsigned(self):NN64 =
737        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$ToUnsignedLong")
738    big(self):ZZ =
739        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$ToBigNum")
740end
741
742trait NN64 extends { ZZ, Integral[\NN64\] } comprises { UnsignedLong, NN32 }
743    opr |self| : NN64 = self
744    opr =(self, b:NN64):Boolean =
745        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Eq")
746    opr <(self, b:NN64):Boolean =
747        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Less")
748    opr -(self):NN64 =
749        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Negate")
750    opr +(self,b:NN64):NN64 =
751        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Add")
752    opr -(self,b:NN64):NN64 =
753        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Sub")
754    opr DOT(self,b:NN64):NN64 =
755        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Mul")
756    opr TIMES(self,b:NN64):NN64 =
757        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Mul")
758    opr juxtaposition(self,b:NN64):NN64 =
759        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Mul")
760    opr DIV(self,b:NN64):NN64 =
761        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Div")
762    opr REM(self,b:NN64):NN64 =
763        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Rem")
764    opr MOD(self,b:NN64):NN64 =
765        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Mod")
766    opr GCD(self,b:NN64):NN64 =
767        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Gcd")
768    opr LCM(self,b:NN64):NN64 =
769        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Lcm")
770    opr CHOOSE(self,b:NN64):NN64 =
771        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Choose")
772    opr BITAND(self,b:NN64):NN64 =
773        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$BitAnd")
774    opr BITOR(self,b:NN64):NN64 =
775        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$BitOr")
776    opr BITXOR(self,b:NN64):NN64 =
777        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$BitXor")
778    opr LSHIFT(self,b:AnyIntegral):NN64 =
779        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$LShift")
780    opr RSHIFT(self,b:AnyIntegral):NN64 =
781        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$RShift")
782    opr BITNOT(self):NN64 =
783        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$BitNot")
784    opr ^(self, b:AnyIntegral):RR64 =
785        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Pow")
786    partitionL(self):NN64 =
787        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$Partition")
788    narrow(self):NN32 =
789        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$FromLong")
790    signed(self):NN64 =
791        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.UnsignedLong$ToLong")
792end
793
794trait ZZ extends Integral[\ZZ\]
795        comprises { BigNum, ZZ64 }
796    getter zero(): ZZ =
797        1934791870947204798109283471902037419 - 1934791870947204798109283471902037419
798    getter one(): ZZ = zero() + 1
799    numerator(self):ZZ = self
800    opr |self| : ZZ32 = if self>=0 then self else -self end
801    opr =(self, b: ZZ):Boolean =
802        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Eq")
803    opr <(self, other:ZZ): Boolean = self.cmp(other) < 0
804    opr <=(self, other:ZZ): Boolean = self.cmp(other) <= 0
805    opr >(self, other:ZZ): Boolean = self.cmp(other) > 0
806    opr >=(self, other:ZZ): Boolean = self.cmp(other) >= 0
807    opr CMP(self, other:ZZ): TotalComparison = self.cmp(other) CMP 0
808    cmp(b:ZZ): ZZ32 =
809        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Cmp")
810
811    opr -(self): ZZ =
812        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Negate")
813    opr +(self, b: ZZ): ZZ =
814        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Add")
815    opr -(self, b: ZZ): ZZ =
816        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Sub")
817    opr DOT(self, b: ZZ): ZZ =
818        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Mul")
819    opr juxtaposition(self, b: ZZ): ZZ =
820        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Mul")
821    opr TIMES(self, b: ZZ): ZZ =
822        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Mul")
823    opr /(self,other:ZZ):QQ = if other < 0 then (-self)/(-other) else
824        g = self GCD other
825        if g=0 then Ratio(0,0) else
826            a = self DIV g
827            b = other DIV g
828            if b = 1 then a else Ratio(a,b) end
829        end
830    end
831    opr DIV(self, b: ZZ): ZZ =
832        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Div")
833    opr REM(self, b: ZZ): ZZ =
834        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Rem")
835    opr MOD(self, b: ZZ): ZZ =
836        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Mod")
837    opr GCD(self, b: ZZ): ZZ =
838        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Gcd")
839    opr LCM(self, b: ZZ): ZZ =
840        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Lcm")
841    opr CHOOSE(self, b: ZZ): ZZ =
842        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Choose")
843    opr BITAND(self, b: ZZ): ZZ =
844        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$BitAnd")
845    opr BITOR(self, b: ZZ): ZZ =
846        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$BitOr")
847    opr BITXOR(self, b: ZZ): ZZ =
848        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$BitXor")
849    opr LSHIFT(self, b:AnyIntegral): ZZ =
850        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$LShift")
851    opr RSHIFT(self, b:AnyIntegral): ZZ =
852        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$RShift")
853    opr BITNOT(self): ZZ =
854        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$BitNot")
855    opr ^(self, b:AnyIntegral):RR64 =
856        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.BigNum$Pow")
857    odd(self): Boolean = NOT (even self)
858    even(self): Boolean = (self MOD 2) = 0
859end
860
861(************************************************************
862* Generator support
863************************************************************)
864
865(** Generator
866 *
867 * We say an object which extends Generator[\T\] "generates objects of
868 * type T."
869 *
870 * Generators are used to express iteration in Fortress.  Every
871 * generated expression in Fortress (eg for loop, comprehension) is
872 * desugared into calls to methods of Generator, chiefly the generate
873 * method.
874 *
875 * Every generator has a notion of a "natural order" (which by default is
876 * unspecified), which describes the ordering of reduction operations,
877 * and also describes the order in which elements are produced by the
878 * sequential version of the same generator (given by the seq(self)
879 * method).  The default implementation of seq(self) guarantees that these
880 * orders will match.
881 *
882 * Note in particular that the natural order of a Generator must be
883 * consistent; that is, if a SEQV b then a and b must yield SEQV
884 * elements in the same natural order.  However, note that unless a type
885 * specifically documents otherwise, no particular element ordering is
886 * guaranteed, nor is it necessary to guarantee that a=b have the same
887 * natural order when equality is defined.
888 *
889 * Note that more complex derived generators are specified further
890 * down in the definition of Generator.  These have the same notions
891 * of natural order and by default are defined in terms of the
892 * generate() method.
893 *
894 * Minimal complete definition of a Generator is the generate(...) method.
895 *)
896trait Generator[\E\]
897    excludes { Number }
898    (** generate is the core of Generator.  It generates elements of
899        type E and passes them to the body function.  This generation
900        can occur using any mixture of serial and parallel execution
901        desired by the author of the generator; by default uses of a
902        generator must assume every call to the body occurs in
903        parallel.
904
905        The results of generation are combined using the reduction
906        object R, which specifies a monoidal operation (associative
907        and with an identity).  Body results must be combined together
908        following the natural order of the generator.  The author of
909        the generator is free to use the identity element anywhere
910        desired in this computation, and to group reductions in any
911        way desired; if no elements are generated the identity must be
912        returned. *)
913    generate[\R\](r: Reduction[\R\], body: E->R): R
914
915    (** Transforming generators into new generators *)
916    (** map applies a function f to each element generated and yields
917        the result.  The resulting generator must have the same
918        ordering and cross product properties as the generator from
919        which it is derived. *)
920    map[\G\](f: E->G): Generator[\G\] = SimpleMappedGenerator[\E,G\](self,f)
921    (** seq produces a sequential version of the same generator, in
922        which elements are produced in the generator's natural order. *)
923    seq(self): SequentialGenerator[\E\] = NaiveSeqGenerator[\E\](self)
924
925    (** Nesting of two generators; the innermost is data-dependent
926        upon the outer one.  This is specifically designed to be
927        overloaded so that the combined generators have properties
928        appropriate to the pairing.  Because of the data dependency
929        the natural order of the nesting is the natural order of the
930        inner generators, in the natural order the outer nesting
931        produces them.  So for example, if we write:
932          (0#3).nest[\ZZ32\](\(n:ZZ32):Generator[\ZZ32\] => (n*100#4))
933        then the natural order is 0,1,2,3,100,101,102,103,200,201,202,203
934     **)
935    nest[\G\](f: E -> Generator[\G\]): Generator[\G\] =
936        SimpleNestedGenerator[\E,G\](self,f)
937
938    (** Filtering data from a generator.  Only elements that satisfy
939        the predicate p are retained.  Natural order and cross product
940        properties are otherwise preserved. **)
941    filter(f: E -> Condition[\()\]): Generator[\E\] =
942        SimpleFilterGenerator[\E\](self,f)
943
944    (** Cross product of two generators.  This is specifically
945        designed to be overloaded, such that pairs of independent
946        generators can be combined to produce a generator which
947        possibly interleaves the iteration spaces of the two
948        generators.  For example, we might combine (0#16).cross(0#32)
949        such that it first splits the second range in half, then the
950        first range in half, then the second, and so forth.
951
952        Consider a grid for which the rows are labeled from top to
953        bottom with the elements of a in natural order, and the
954        columns are labeled from left to right with the elements of g
955        in natural order.  Each point in the grid corresponds to a
956        pair (a,b) that must be generated by self.cross(g).  In the
957        natural order of the cross product, an element must occur
958        after those that lie above and to the left of it in the grid.
959        By default the natural order of the cross product is
960        left-to-right, top to bottom.  Programmers must not rely on
961        the default order, except that cross products involving one or
962        more sequential generators are always performed in the default
963        order.  Note that this means that the following have the same
964        natural order:
965           seq(a).cross(b)
966           a.cross(seq(b))
967           seq(a).cross(seq(b))
968        But seq(a.cross(b)) may have a different natural order. *)
969    cross[\G\](g: Generator[\G\]): Generator[\(E,G)\] =
970        SimplePairGenerator[\E,G\](self, g)
971
972    (** Derived generation operations *)
973    (** mapReduce is equivalent to generate, but takes an explicit join
974        and zero which can have any type.  It still assumes join is
975        associative and that zero is the identity of join. **)
976    mapReduce[\R\](body: E->R, join:(R,R)->R, id:R): R =
977        generate[\R\](MapReduceReduction[\R\](join,id), body)
978    (** reduce works much like generate or mapReduce,
979        but has no body expression **)
980    reduce(j:(E,E)->E, z:E):E = mapReduce[\E\](fn (e:E)=>e, j, z)
981    reduce(r: Reduction[\E\]):E = generate[\E\](r, fn(e:E)=>e)
982    (** loop is a version of generate which discards the void results
983        of the body computation.  It is used to translated
984        reduction-variable-free for loops. **)
985    loop(f:E->()): () = generate[\()\](VoidReduction, f)
986    (** Is x generated by this generator? **)
987    opr IN(x:E, self): Boolean = BIG OR [y <- self] x=y
988    (** The MATCH operator is used (as a temporary hack) by CASE when the
989        match clause is a Generator[\E\].  We must choose either =, SEQV, or
990        IN as appropriate, depending on the type of the LHS. **)
991    opr MATCH(x:Any, self): Boolean =
992        typecase x of
993            E => (x IN self)
994            Generator[\E\] => (x = self)
995            else => fail("Type error in MATCH of Generator")
996        end
997end
998
999(** The following top-level functions are used as glue in the
1000    desugaring of generated expressions (comprehensions, BIG
1001    operators, and loops).  They exist at the top level in part to
1002    work around shortcomings in the ablity of the Fortress interpreter
1003    to check types dynamically for anything except top-level
1004    non-overloaded function calls. **)
1005__generate[\E,R\](g:Generator[\E\], r: Reduction[\R\], b:E->R): R =
1006    g.generate[\R\](r,b)
1007
1008__nest[\E1,E2\](g:Generator[\E1\], f:E1->Generator[\E2\]):Generator[\E2\] =
1009    g.nest[\E2\](f)
1010
1011__singleton[\E\](body:E): Generator[\E\] = Just[\E\](body)
1012
1013__loop[\E,R\](g:Generator[\E\], body:E->R): () = g.loop(body)
1014
1015__cond[\E,R\](c:Condition[\E\], t:E->R, e:()->R): R = c.cond[\R\](t,e)
1016__cond[\E\](c:Condition[\E\], t:E->()): () = c.cond[\()\](t, fn () => ())
1017
1018(** Used in desugaring binding %while% **)
1019__whileCond[\E\](c:Condition[\E\], b:E->()): () =
1020    c.cond[\Boolean\](fn (e): Boolean => do b(e); true end, fn ():Boolean => false)
1021
1022(** Unlike the user-visible dotted map method, this method is used for
1023    the internals of comprehension desugaring [except that at present
1024    it is not actually in use, but we're planning to use it].  As a
1025    result we know that its result will immediately be consumed, and
1026    we should *not* create an intermediate collection if we're passed
1027    a collection. **)
1028__map[\E,R\](g:Generator[\E\], f:E->R): Generator[\R\] =
1029    typecase g of
1030        SomeMappedGenerator[\E\] => g.map[\R\](f)
1031        SequentialGenerator[\E\] => SimpleMappedSeqGenerator[\E,R\](g,f)
1032        else => SimpleMappedGenerator[\E,R\](g,f)
1033    end
1034
1035(** Unlike the user-visible dotted filter method, but like the __map
1036    method, this method is intended for use in the internals of
1037    comprehension desugaring.  Again its result will immediately be
1038    consumed, and we do not create an intermediate collection but
1039    perform the filtering lazily on demand. **)
1040__filter[\E\](g:Generator[\E\], p:E->Condition[\()\]): Generator[\E\] =
1041    typecase g of
1042        FilterGenerator[\E\] => g.filter(p)
1043        SequentialGenerator[\E\] => SimpleSeqFilterGenerator[\E\](g,p)
1044        else => SimpleFilterGenerator[\E\](g,p)
1045    end
1046
1047(** Application of a BIG operator, the topmost level of comprehension desugaring. **)
1048__bigOperator[\I,O,R,L\](o:BigOperator[\I,O,R,L\],desugaredClauses:(Reduction[\L\],I->L)->L): O = do
1049    r = o.reduction()
1050    body(i): L = r.lift((o.body())(i))
1051    (o.unwrap())(r.unlift(desugaredClauses(r,body)))
1052  end
1053
1054(** Application of two nested BIG operators, possibly with fusion.  This only covers
1055    a comprehension of the form:
1056       BIG outer [ xs <- expr_o ] (BIG inner [x <- xs] expr_i)
1057    The desugarer extracts comprehensions of this form from more complex nests of
1058    comprehensions, using a combination of splitting:
1059        BIG OP [ gs_1, gs_2 ] expr = BIG OP [ gs_1 ] (BIG OP [ gs_2 ] expr)
1060    and filter squeezing:
1061        BIG OP [ xs <- g, p(xs) ] expr = BIG OP [ xs <- g.filter(p) ] expr
1062    There are some big caveats to this explanation in practice.  Most important is that
1063    we don't unlift and lift or do input/output conversion except where neccessary, so
1064    splitting skips these operations in between the inner and outer comprehension.
1065    **)
1066__bigOperator2[\I,M,O,R1,L1,R2,L2,E\](outer:BigOperator[\M,O,R1,L1\],
1067                                    inner:BigOperator[\I,M,R2,L2\],
1068                                    gg: Generator[\Generator[\E\]\],
1069                                    innerBody:E->L2): L1 = do
1070    o = outer.reduction()
1071    i = inner.reduction()
1072    gg.generate(o,fn (xs) =>
1073                   o.lift((outer.wrap())((inner.unwrap())(i.unlift(
1074                                                xs.generate(i,innerBody))))))
1075  end
1076
1077trait SequentialGenerator[\E\] extends { Generator[\E\] }
1078    seq(self) = self
1079    map[\G\](f: E->G): SequentialGenerator[\G\] =
1080        SimpleMappedSeqGenerator[\E,G\](self,f)
1081    (* TODO: make overloaded *)
1082    nest[\G\](f: E -> Generator[\G\]): Generator[\G\] =
1083        typecase f of
1084            E -> SequentialGenerator[\G\] =>
1085                SimpleNestedSeqGenerator[\E,G\](self,f)
1086            else => SimpleNestedGenerator[\E,G\](self,f)
1087        end
1088    (* TODO: make overloaded *)
1089    cross[\F\](g:Generator[\F\]): Generator[\(E,F)\] =
1090        typecase g of
1091            SequentialGenerator[\F\] =>
1092                    SimplePairSeqGenerator[\E,F\](self,g)
1093            else => SimplePairGenerator[\E,F\](self,g)
1094        end
1095end
1096
1097(** A Condition is a Generator that generates 0 or 1 element.
1098    Conditions can be used as nullary comprehension generators or
1099    as predicates in an if expression. **)
1100trait Condition[\E\] extends { ZeroIndexed[\E\], SequentialGenerator[\E\] }
1101    getter isEmpty(): Boolean = NOT holds()
1102    getter holds(): Boolean = cond[\Boolean\](fn (_:E):Boolean => true, fn () => false)
1103    getter size(): ZZ32 = if holds() then 1 else 0 end
1104    getter get(): E throws NotFound = cond[\E\](identity[\E\], fn () => throw NotFound)
1105    getter bounds(): FullRange[\ZZ32,true\] = 0 # |self|
1106    getter indices(): FullRange[\ZZ32,true\] = bounds()
1107    getter indexValuePairs(): Condition[\(ZZ32,E)\] =
1108        cond[\E\](fn (e:E) => Just[\(ZZ32,E)\](0,e), fn () => Nothing[\(ZZ32,E)\])
1109    opr |self|: ZZ32 = if holds() then 1 else 0 end
1110    opr [i:ZZ32]:E throws NotFound = if i=0 then get() else throw NotFound end
1111    opr [r:Range[\ZZ32\]]: Condition[\E\] =
1112        cond[\E\](fn (e:E): Condition[\E\] => do
1113                    r1 = (0#1)[r]
1114                    if r1.isEmpty then Nothing[\E\] else self end
1115                  end,
1116                fn (): Condition[\E\] => do r1 = (0#0)[r]; self end)
1117    getDefault(e:E): E = cond[\E\](identity[\E\], fn () => e)
1118    cond[\G\](t: E -> G, e: () -> G): G
1119    generate[\G\](r:Reduction[\G\], body: E -> G): G = cond[\G\](body,fn () => r.empty())
1120
1121    (** For a Condition, these methods run eagerly. **)
1122    map[\G\](f: E->G): Condition[\G\] =
1123        cond[\G\](fn (e:E) => Just[\G\](f(e)), fn () => Nothing[\G\])
1124    ivmap[\G\](f: (ZZ32,E)->G): Condition[\G\] =
1125        cond[\G\](fn (e:E) => Just[\G\](f(0,e)), fn () => Nothing[\G\])
1126    nest[\G\](f: E -> Generator[\G\]): Generator[\G\] =
1127        cond[\G\](f, fn () => Nothing[\G\])
1128    cross[\G\](g: Generator[\G\]): Generator[\(E,G)\] =
1129        cond[\G\](fn (e:E):Generator[\(E,G)\] => g.map[\(E,G)\](fn (g':G):(E,G) => (e,g')),
1130               fn () => Nothing[\(E,G)\])
1131    mapReduce[\R\](body: E->R, _:(R,R)->R, id:R): R =
1132        cond[\R\](body, fn () => id)
1133    reduce(_:(E,E)->E, z:E):E = cond[\E\](identity[\E\], fn ():E => z)
1134    reduce(r: Reduction[\E\]):E = cond[\E\](identity[\E\], fn ():E => r.empty())
1135    loop(f:E->()): () = cond[\()\](f,fn ():() => ())
1136    opr IN(x:E, self):Boolean = cond[\Boolean\](fn (e:E):Boolean => x=e, fn () => false)
1137end
1138
1139(** Conjunction and disjunction of condition functions **)
1140opr ANDCOND[\I\](p1:I->Condition[\()\], p2:I->Condition[\()\]): I->Condition[\()\] =
1141    fn (i:I):Boolean => p1(i).holds AND: p2(i).holds
1142
1143(** Conjunction and disjunction of condition functions **)
1144opr ORCOND[\I\](p1:I->Condition[\()\], p2:I->Condition[\()\]): I->Condition[\()\] =
1145    fn (i:I):Boolean => p1(i).holds OR: p2(i).holds
1146
1147(** Operations which use generation internally.  Should be functional
1148    methods of Generator, but that didn't work when last tested. **)
1149
1150(** IN returns true if any element generated by its second argument is
1151    = to its first argument.  x NOTIN g is simply NOT (x IN g).
1152    Unless documented otherwise, this is O(n) for an n-element
1153    Generator (it simply performs naive matching).  **)
1154opr NOTIN[\E\](x: E, this: Generator[\E\]): Boolean = NOT (x IN this)
1155
1156(* seq[\T\](g:Generator[\T\]):SequentialGenerator[\T\] = g.seq() *)
1157sequential[\T\](g:Generator[\T\]):SequentialGenerator[\T\] = seq(g)
1158
1159(************************************************************
1160* Meta-generators: BIG GENERATOR
1161************************************************************)
1162
1163(** The problem: Your code is sprinkled with the same generator code,
1164    over and over again.  Maybe it looks something like this:
1165    % for (i,v) <- a.indexValuePairs, v =/= 0, j <- 0:i do (code using i and j) %
1166    You goal: abstract this into a single generator.  You can do this as follows:
1167    % usefulGen = BIG GENERATOR[(i,v) <- a.indexValuePairs, v =/= 0, j <- 0:i] (i,j) %
1168    Not much savings there, but the important part is that you can just
1169    cut and paste the generators from the original code.  And all occurrences
1170    can be cleaned up:
1171    % for (i,j) <- usefulGen do (code using i and j) %
1172    This is possible using %map%, %filter%, and %nest%, but you end up
1173    effectively desugaring the code by hand.  Using BIG GENERATOR is much easier.
1174 **)
1175
1176(** TODO
1177
1178The big problem here is that the new desugaring story actually gets in
1179the way.  We can't simply package up a function passed in, because
1180that's being done by the __bigOperator functionality directly.
1181
1182How do we deal with reduction properties?  It's all very sticky.  And
1183we're already running into difficulties with co- and contra-variance
1184of the type parameters floating around that force us to use Any in
1185awkward places.
1186
1187In particular, we don't want to generate the data when creating the
1188generator, as that misses the whole point.  We want to defer the
1189object traversals until the moment the resulting generator is used.
1190**)
1191
1192(************************************************************
1193* The Maybe type, used instead of null
1194************************************************************)
1195
1196(* This makes excludes work without where clauses, and allows opr =()
1197   to remain non-parametric. *)
1198value trait AnyMaybe extends Equality[\AnyMaybe\] excludes Number
1199        (** \vspace{-4ex} NOT YET: %comprises Maybe[\T\] where [\T\]% *)
1200    getter holds() : Boolean
1201    opr =(self, other:AnyMaybe): Boolean = false
1202end
1203
1204just(t:Any):AnyMaybe = Just(t)
1205
1206(** %Maybe% represents either %Nothing% or a single element of type
1207    %T% (%Just[\T\]%), which may be retrieved by calling %get%.  An
1208    object of type %Maybe[\T\]% can be used as a generator; it is either
1209    empty (%Nothing%) or generates the single element yielded by
1210    %get%, so there is no issue of canonical order or parallelism.
1211
1212    Thus, %Just[\T\]% can be used as a single-element generator, and
1213    %Nothing% can be used as an empty generator. *)
1214value trait Maybe[\T\]
1215        extends { AnyMaybe, Condition[\T\] }
1216        comprises { Nothing[\T\], Just[\T\] }
1217end
1218
1219value object Just[\T\](x:T) extends Maybe[\T\]
1220    getter size()=1
1221    getter toString():String = "Just(" x ")"
1222    getter holds() = true
1223    getter get() = x
1224    opr |self| : ZZ32 = 1
1225    getDefault(_:T): T = x
1226    cond[\R\](t:T->R, _:()->R): R = t(x)
1227    generate[\R\](_:Reduction[\R\],m:T->R): R = m(x)
1228    opr[i:ZZ32]:T = if i=0 then x else fail("Maybe[" i "] nonzero index") end
1229
1230    map[\G\](f: T->G): Just[\G\] = Just[\G\](f(x))
1231    cross[\G\](g: Generator[\G\]): Generator[\(T,G)\] =
1232        g.map[\(T,G)\](fn (e:G):(T,G) => (x,e))
1233
1234    mapReduce[\R\](m: T->R, _:(R,R)->R, _:R): R = m(x)
1235    reduce(_:(T,T)->T, _:T):T = x
1236    reduce(_: Reduction[\T\]):T = x
1237    loop(f:T->()): () = f(x)
1238    opr IN(y:T, self): Boolean = x=y
1239    opr =(self,o:Just[\T\]): Boolean = x=o.get
1240end
1241
1242(* Obviously ought to be a non-parametric singleton when we get where
1243   clauses working. *)
1244value object Nothing[\T\] extends Maybe[\T\]
1245    getter size()=0
1246    getter holds() = false
1247    getter get() = throw NotFound
1248    getter toString():String = "Nothing"
1249    opr |self| : ZZ32 = 0
1250    getDefault(t:T):T = t
1251    cond[\R\](_:T->R, e:()->R): R = e()
1252    generate[\R\](r:Reduction[\R\],_:T->R): R = r.empty()
1253    opr[_:ZZ32]: T = fail("Cannot index Nothing")
1254
1255    map[\G\](f: T->G): Nothing[\G\] = Nothing[\G\]
1256    cross[\G\](g: Generator[\G\]): Generator[\(T,G)\] = Nothing[\(T,G)\]
1257
1258    mapReduce[\R\](_: T->R, _:(R,R)->R, z:R): R = z
1259    reduce(_:(T,T)->T, z:T):T = z
1260    reduce(r: Reduction[\T\]):T = r.empty()
1261    loop(f:T->()): () = ()
1262    opr IN(x:T, self): Boolean = false
1263    opr =(self,_:Nothing[\T\]) = true
1264end
1265
1266(************************************************************
1267* Exception hierarchy
1268************************************************************)
1269
1270trait Exception comprises { UncheckedException, CheckedException }
1271end
1272
1273(* Exceptions which are not checked *)
1274
1275trait UncheckedException extends Exception excludes CheckedException
1276end
1277
1278object FailCalled(s:String) extends UncheckedException
1279  toString(): String = "FAIL: " s
1280end
1281
1282object DivisionByZero extends UncheckedException
1283    toString(): String = "Division by zero"
1284end
1285
1286object UnpastingError extends UncheckedException
1287    toString(): String = "Unpasting error"
1288end
1289
1290object CallerViolation extends UncheckedException
1291    toString(): String = "Caller violation"
1292end
1293
1294object CalleeViolation extends UncheckedException
1295    toString(): String = "Callee violation"
1296end
1297
1298object TestFailure extends UncheckedException
1299    toString(): String = "Test failure"
1300end
1301
1302object ContractHierarchyViolation extends UncheckedException
1303    toString(): String = "Contract hierarchy violation"
1304end
1305
1306object NoEqualityOnFunctions extends UncheckedException
1307    toString(): String = "No equality on functions"
1308end
1309
1310object InvalidRange extends UncheckedException
1311    toString(): String = "Invalid range"
1312end
1313
1314object ForbiddenException(chain : Exception) extends UncheckedException
1315    toString(): String = "Forbidden exception"
1316end
1317
1318(* Should this be called "IndexNotFound" instead? *)
1319object NotFound extends UncheckedException
1320    toString(): String = "Not found"
1321end
1322
1323object IndexOutOfBounds(min:ZZ32,max:ZZ32,index:ZZ32) extends UncheckedException
1324    toString(): String = index " is outside the range " min " to " max
1325end
1326
1327object NegativeLength extends UncheckedException
1328    toString(): String = "Negative length"
1329end
1330
1331object IntegerOverflow extends UncheckedException
1332    toString(): String = "Integer Overflow"
1333end
1334
1335object RationalComparisonError extends UncheckedException
1336    toString(): String = "Rational comparison error"
1337end
1338
1339object FloatingComparisonError extends UncheckedException
1340    toString(): String = "Floating comparison error"
1341end
1342
1343(* Checked Exceptions *)
1344
1345trait CheckedException extends Exception excludes UncheckedException
1346end
1347
1348object CastError extends CheckedException
1349    toString(): String = "Cast error"
1350end
1351
1352object IOFailure extends CheckedException
1353    toString(): String = "I/O error"
1354end
1355
1356object MatchFailure extends CheckedException
1357    toString(): String = "Match failure"
1358end
1359
1360(* SetsNotDisjoint? *)
1361object DisjointUnionError extends CheckedException
1362    toString(): String = "Disjoint union error"
1363end
1364
1365object APIMissing extends CheckedException
1366    toString(): String = "Api is missing"
1367end
1368
1369object APINameCollision extends CheckedException
1370    toString(): String = "Api name collides with another"
1371end
1372
1373object ExportedAPIMissing extends CheckedException
1374    toString(): String = "Exported api is missing"
1375end
1376
1377object HiddenAPIMissing extends CheckedException
1378    toString(): String = "Hidden api is missing"
1379end
1380
1381object TryAtomicFailure extends CheckedException
1382    toString(): String = "Try/atomic failure"
1383end
1384
1385(* Should take a spawned thread as an argument *)
1386object AtomicSpawnSynchronization extends {UncheckedException}
1387    toString(): String = "Atomic spawn synchronization"
1388end
1389
1390(************************************************************
1391* Array support
1392************************************************************)
1393
1394oops(s:ZZ32, l:ZZ32, sz:ZZ32, got:ZZ32):() = do
1395   fail("Index of dimension " s " out of bounds; got " got
1396        " which is not in " l "#" sz);
1397end
1398
1399trait HasRank extends Equality[\HasRank\] excludes { Number, AnyMaybe }
1400  (** \vspace{-4ex} NOT YET: %comprises Array[\T,E,I\]
1401                              where [\T,E,I\]{ T extends Array[\T,E,I\] }% *)
1402  rank():ZZ32
1403  opr =(self, other:HasRank): Boolean = false
1404end
1405
1406(* Declared Rank-n-ness *)
1407trait Rank[\ nat n \] extends HasRank
1408  rank():ZZ32 = n
1409end
1410
1411(* Potemkin exclusion traits.  Really we just want to say that
1412 * Rank[\n\] excludes Rank[\m\] where { m =/= n }, but we can't yet. *)
1413
1414trait Rank1 extends { Rank[\1\]} excludes { Rank2, Rank3, Number, String }
1415end
1416
1417trait Rank2 extends { Rank[\2\]} excludes { Rank3, Number, String }
1418end
1419
1420trait Rank3 extends { Rank[\3\]} excludes { Number, String }
1421end
1422
1423(* The trait Indexed_i[\n\] indicates that something has an i^th
1424 * dimension of size n.  In general anything which extends Indexed_i
1425 * must also extend Indexed_j for j < i. *)
1426
1427trait Indexed1[\ nat n \] extends HasRank end
1428
1429trait Indexed2[\ nat n \] extends HasRank end
1430
1431trait Indexed3[\ nat n \] extends HasRank end
1432
1433(** The indexed trait indicates that an object of type T can be
1434indexed using type I to obtain elements with type E.
1435
1436An object i that's an instance of Indexed defines three basic things:
1437  The indexing operator opr [], which must be defined for every instance of
1438    the type.
1439
1440  A suite of generators: i.indices generates the index space of the
1441    array.  i itself generates the values contained at those indices.
1442    i.indexValuePairs yields pairs of (index,value).  All of these
1443    share the same natural order.  It is necessary to define one of
1444    indices() and indexValuePairs(), in addition to generate() (but
1445    the latter requirement can be dispensed by instead extending
1446    DelegatedIndexed).
1447
1448  A set of utility functions, assign, fill, and copy.  Only fill and
1449    copy need to be defined.
1450**)
1451trait Indexed[\E, I\] extends Generator[\E\]
1452    (** isEmpty indicates whether there are any valid indices.  It is
1453        defined as size=0 *)
1454    getter isEmpty(): Boolean = |self| = 0
1455    (** %size()% is depracated; use %|self|%. *)
1456    getter size(): ZZ32
1457    (** bounds() yields a range of indices that are valid for the
1458        indexed generator. *)
1459    getter bounds(): FullRange[\I,true\]
1460    (** indexValuePairs() generates the elements of the indexed object
1461        (exactly those elements that are generated by the object itself),
1462        but each element is paired with its index.  When we obtain
1463        (i,v) from indexValuePairs we know that:
1464           self[i] = v
1465           the i are distinct and i IN bounds()
1466           stripping away the i yields exactly the results of v <- self
1467        This generator attempts to follow the structure of the
1468        underlying object as closely as possible.  *)
1469    getter indexValuePairs(): Indexed[\(I,E),I\] =
1470        indices().map[\(I,E)\](fn (i:I): (I,E) => (i,self[i]))
1471    (** indices() yields the indices corresponding to the elements of
1472        the indexed object---it corresponds to the index component of
1473        indexValuePairs().  This may in general be a subset of all the
1474        valid indices represented by bounds().  This generator
1475        attempts to follow the structure of the underlying object as
1476        closely as possible. *)
1477    getter indices(): Indexed[\I,I\] =
1478        indexValuePairs().map[\I\](fn (i:I, e:E): I => i)
1479
1480    (** %|self|% indicates the number of distinct valid indices that may
1481        be passed to indexing operations. *)
1482    opr |self| : ZZ32
1483
1484    (** Indexing.  i IN bounds() must hold. *)
1485    opr[i:I] : E
1486
1487    (** Locality of a particular index (NOT of its contents!). *)
1488    region(i:I): Region = Global
1489
1490    (** Indexing by ranges.  The results are 0-based when the
1491        underlying index type has a notion of 0.  This ensures
1492        consistency of behavior between types such as vectors that
1493        *only* support 0 indexing and types such as arrays that permit
1494        other choices of lower bounds.  The easiest way to write the
1495        index by ranges operation for an instance of Indexed is to
1496        take advantage of indexing on the ranges themselves by writing
1497        (bounds())[r] in order to narrow and bounds check the range r
1498        and obtain a closed range of indices on the underlying
1499        data. **)
1500    opr[r:Range[\I\]] : Indexed[\E,I\]
1501    opr[_:OpenRange[\Any\]] : Indexed[\E,I\] = self[OpenRange[\I\]]
1502
1503    (** Roughly speaking, ivmap(f) is equivalent to
1504        indexValuePairs.map(f).  However ivmap function isn't merely a
1505        convenient shortcut.  It's actually intended to create a copy
1506        of the underlying indexed structure when that is appropriate.
1507
1508        The usual map function in Generator should do the same (and
1509        does for the instances in this library).  Copying can be bad
1510        for space, but is complexity-preserving if the mapped
1511        generator is used more than once. **)
1512    ivmap[\R\](f:(I,E)->R): Indexed[\R, I\] = indexValuePairs().map[\R\](f)
1513    map[\R\](f:E->R): Indexed[\R, I\] = SimpleMappedIndexed[\E,R,I\](self,f)
1514
1515    (** indexOf(e) returns an index at which e can be found,
1516        or Nothing if no such index exists. **)
1517    indexOf(e:E): Maybe[\I\] =
1518        label found
1519            for (i,v) <- indexValuePairs(), v=e do
1520                exit found with Just[\I\](i)
1521            end
1522            Nothing[\I\]
1523        end found
1524end
1525
1526trait ZeroIndexed[\E\] extends Indexed[\E,ZZ32\]
1527    bounds(): FullRange[\ZZ32,true\] = 0 # |self|
1528    zip[\F\](g:ZeroIndexed[\F\]):ZeroIndexed[\(E,F)\] =
1529        DefaultZip[\E,F\](self,g)
1530end
1531
1532object DefaultZip[\E,F\](e:ZeroIndexed[\E\],f:ZeroIndexed[\F\])
1533        extends { ZeroIndexed[\(E,F)\], DelegatedIndexed[\(E,F),ZZ32\] }
1534    getter size(): ZZ32 = |self|
1535    getter indices(): Generator[\ZZ32\] =
1536        if |e| <= |f| then e.indices else f.indices end
1537    opr |self| : ZZ32 = |e| MIN |f|
1538    opr[i:ZZ32]:(E,F) = (e[i],f[i])
1539    opr[r:Range[\ZZ32\]] : ZeroIndexed[\(E,F)\] =
1540        DefaultZip[\E,F\](e[r],f[r])
1541end
1542
1543trait LexicographicOrder[\T extends LexicographicOrder[\T,E\],E\]
1544        extends { StandardTotalOrder[\T\], ZeroIndexed[\E\] }
1545    opr CMP(self, other:T): TotalComparison =
1546        self.zip[\E\](other).generate[\TotalComparison\](
1547            LexicographicReduction,
1548            fn(a:E,b:E): TotalComparison => a CMP b) LEXICO
1549        (|self| CMP |other|)
1550    (** We give a specialized version of = because it can fail faster
1551        than CMP by checking sizes early. **)
1552    opr =(self,other:T): Boolean =
1553        (|self| = |other|) AND:
1554          (BIG AND [(a,b)<-self.zip[\E\](other)] a=b)
1555end
1556
1557toArray[\E\](g:Indexed[\E,ZZ32\]): Array[\E,ZZ32\] = do
1558    bnds = g.bounds
1559    r = array[\E\](|bnds|).shift(bnds.lower())
1560    for (i,v) <- g.indexValuePairs do
1561        r.init(i,v)
1562    end
1563    r
1564  end
1565
1566(** DelegatedIndexed is an Indexed generator that has recourse to
1567    another Indexed generator() internally.  By default this in turn
1568    is defined in terms of indexValuePairs().  Thus it's only
1569    necessary to define either indexValuePairs() or indices().
1570
1571    This class is designed for convenience; it shouldn't be used as a
1572    type in runing code, but only as a supertype in lieu of Indexed.
1573**)
1574trait DelegatedIndexed[\E,I\] extends Indexed[\E,I\]
1575    getter generator(): Generator[\E\] =
1576        indexValuePairs().map[\E\](fn (i:I, e:E): E => e)
1577    getter size(): ZZ32 = |generator()|
1578    opr |self| : ZZ32 = |generator()|
1579    generate[\R\](r: Reduction[\R\], body: E->R): R =
1580        generator().generate[\R\](r,body)
1581    seq(self): SequentialGenerator[\E\] = seq(generator())
1582    cross[\G\](g: Generator[\G\]): Generator[\(E,G)\] =
1583        generator().cross[\G\](g)
1584    mapReduce[\R\](body: E->R, join:(R,R)->R, id:R): R =
1585        generator().mapReduce[\R\](body,join,id)
1586    reduce(j:(E,E)->E, z:E):E = generator().reduce(j,z)
1587    reduce(r: Reduction[\E\]):E = generator().reduce(r)
1588    loop(f:E->()): () = generator().loop(f)
1589end
1590
1591(** The MutableIndexed trait is an indexed trait whose elements can be
1592    mutated using indexed assignment.  Right now we're using this type
1593    in a somewhat dangerous way, since eg Array1[\E,b0,s0\] extends
1594    both Indexed[\Array1[\E,b0,s0\],E,ZZ32\] and
1595    Indexed[\Array[\E,ZZ32\],E,ZZ32\].  We will need to find a
1596    solution to this at some point.
1597**)
1598trait MutableIndexed[\E, I\]
1599        extends { Indexed[\E,I\] }
1600    opr[i:I]:=(v:E) : ()
1601
1602    (** For Ranged assignment, the extents of r and v.bounds must
1603        match, but the lower bounds need not. **)
1604    opr[r:Range[\I\]]:=(v:Indexed[\E,I\]) : ()
1605    opr[_:OpenRange[\Any\]]:=(v:Indexed[\E,I\]) : () =
1606        do self[bounds()] := v end
1607end
1608
1609(* Array whose bounds are implicit rather than static, and which may
1610   be either mutable or immutable. *)
1611trait ReadableArray[\E,I\]
1612        extends { HasRank, Indexed[\E,I\], DelegatedIndexed[\E,I\] }
1613        comprises { Array[\E,I\], ImmutableArray[\E,I\] }
1614    (** CONCRETE GETTERS
1615        Default implementations of getters based on abstract methods
1616        below. **)
1617    getter indices(): Indexed[\I,I\] = bounds()
1618    getter indexValuePairs(): Indexed[\(I,E),I\] =
1619        zeroIndices().map[\(I,E)\](fn (i:I):(I,E) => (toIndex(i),get(i)))
1620    getter generator(): Indexed[\E,I\] =
1621        zeroIndices().map[\E\](fn (i:I):E => get(i))
1622
1623    (** CONCRETE METHODS
1624        Default implementations of most array stuff based on the above.
1625        The things we can't provide are anything involving replica. **)
1626
1627    opr[i:I]:E = get(offset(i))
1628
1629    (** Initialize element at index i with value v.  This should occur
1630        once, before any other access or assignment occurs to element
1631        i.  An error will be signaled if an uninitialized element is
1632        read or an initialized element is re-initialized. **)
1633    init(i:I, v:E) = init0(offset(i),v)
1634
1635    generate[\R\](r: Reduction[\R\], body: E->R): R =
1636        generator().generate[\R\](r,body)
1637    seq(self): SequentialGenerator[\E\] = seq(generator())
1638
1639    (** 0-based non-bounds-checked indexing **)
1640    get(i:I): E
1641    init0(i:I, e:E): ()
1642    zeroIndices(): FullRange[\I,true\]
1643    (** Convert from base()-based indexing to 0-based indexing,
1644        performing bounds checking. **)
1645    offset(i:I): I
1646    (** Convert from 0-based indexing to base()-based indexing **)
1647    toIndex(i:I): I
1648
1649    (** Indexed functionality with more specific type information **)
1650    opr[r:Range[\I\]] : ReadableArray[\E,I\]
1651    opr[_:OpenRange[\Any\]] : ReadableArray[\E,I\]
1652    ivmap[\R\](f:(I,E)->R): ReadableArray[\R, I\]
1653    map[\R\](f:E->R): ReadableArray[\R, I\]
1654
1655    (** Shift the origin of an array.  This should yield a new view of
1656        the same array; ie initialization and/or update to either will
1657        be reflected in the other. **)
1658    shift(newOrigin:I):ReadableArray[\E,I\]
1659
1660    (** Bulk initialization of an array using a given function or
1661        value.  These are defined with more specific self types in
1662        StandardImmutableArrayType. **)
1663    fill(f:I->E):ReadableArray[\E,I\]
1664    fill(v:E):ReadableArray[\E,I\]
1665
1666    copy():ReadableArray[\E,I\]
1667
1668    (** Create a fresh array structurally identical to the present
1669        one, but holding elements of type U. **)
1670    replica[\U\]():ReadableArray[\U,I\]
1671
1672    opr =(self, other:HasRank): Boolean =
1673        typecase other of
1674            ReadableArray[\E,I\] => indices().generate[\Boolean\](AndReduction,
1675                                           fn (i:I):Boolean => (self[i]=other[i]))
1676            else => false
1677        end
1678
1679end
1680
1681trait ImmutableArray[\E,I\] extends { ReadableArray[\E,I\] }
1682        excludes { Array[\E,I\] }
1683    opr[r:Range[\I\]] : ImmutableArray[\E,I\]
1684    opr[_:OpenRange[\Any\]] : ImmutableArray[\E,I\]
1685    ivmap[\R\](f:(I,E)->R): ImmutableArray[\R, I\]
1686    map[\R\](f:E->R): ImmutableArray[\R, I\]
1687    shift(newOrigin:I):ImmutableArray[\E,I\]
1688    fill(f:I->E):ImmutableArray[\E,I\]
1689    fill(v:E):ImmutableArray[\E,I\]
1690    copy():ImmutableArray[\E,I\]
1691    replica[\U\]():ImmutableArray[\U,I\]
1692
1693    (** Thaw array (return mutable copy) **)
1694    thaw():Array[\E,I\]
1695end
1696
1697trait Array[\E,I\] extends { ReadableArray[\E,I\], MutableIndexed[\E,I\] }
1698    (** 0-based non-bounds-checked indexing **)
1699    put(i:I, e:E): ()
1700    opr[i:I]:=(v:E):() = put(offset(i),v)
1701
1702    opr[r:Range[\I\]]:=(a:Indexed[\E,I\]):() = do
1703        a0 = a[a.bounds]        (* Make a have 0 origin *)
1704        s0 = self[r]            (* Make self have 0 origin *)
1705        if a0.bounds = s0.bounds then
1706            for (i,v) <- a0.indexValuePairs do
1707                s0.put(i,v)
1708            end
1709        else
1710            fail("Can't assign indexed with bounds " a.bounds //
1711                 " to differently-sized subarray " self.bounds)
1712        end
1713      end
1714
1715    (** The following are repetition with better return type info. **)
1716    opr[r:Range[\I\]] : Array[\E,I\]
1717    opr[_:OpenRange[\Any\]] : Array[\E,I\]
1718    ivmap[\R\](f:(I,E)->R): Array[\R, I\]
1719    map[\R\](f:E->R): Array[\R, I\]
1720    shift(newOrigin:I):Array[\E,I\]
1721    fill(f:I->E):Array[\E,I\]
1722    fill(v:E):Array[\E,I\]
1723    assign(f:I->E):Array[\E,I\]
1724    copy():Array[\E,I\]
1725    replica[\U\]():Array[\U,I\]
1726
1727    (** Freeze array (return mutable copy) **)
1728    freeze(): ImmutableArray[\E,I\]
1729end
1730
1731(** Factory for arrays that returns an empty 0-indexed array of a given
1732    run-time-determined size. **)
1733array[\E\](x:ZZ32):Array[\E,ZZ32\] = __arr1(__Proxy[\E\],reflect(x))
1734array[\E\](x:ZZ32,y:ZZ32):Array[\E,(ZZ32,ZZ32)\] =
1735    __arr2(__Proxy[\E\],reflect(x), reflect(y))
1736array[\E\](x:ZZ32,y:ZZ32,z:ZZ32):Array[\E,(ZZ32,ZZ32,ZZ32)\] =
1737    __arr3(__Proxy[\E\],reflect(x), reflect(y), reflect(z))
1738
1739(* This should be local to array, but we don't support local
1740   parametric methods in the language spec at all at the moment. *)
1741__arr1[\E, nat n\](w:__Proxy[\E\],x:N[\n\]):Array1[\E,0,n\] =
1742    array1[\E,n\]()
1743__arr2[\E, nat n, nat m\](w:__Proxy[\E\],x:N[\n\],y:N[\m\]):
1744    Array2[\E,0,n,0,m\] = array2[\E,n,m\]()
1745__arr3[\E, nat n, nat m, nat p\](w:__Proxy[\E\],x:N[\n\],y:N[\m\],z:N[\p\]):
1746    Array3[\E,0,n,0,m,0,p\] = array3[\E,n,m,p\]()
1747
1748(** Factory for immutable arrays that returns an empty 0-indexed array
1749    of a given run-time-determined size. **)
1750immutableArray[\E\](x:ZZ32):ImmutableArray[\E,ZZ32\] =
1751    __imm1(__Proxy[\E\],reflect(x))
1752(*
1753immutableArray[\E\](x:ZZ32,y:ZZ32):ImmutableArray[\E,(ZZ32,ZZ32)\] =
1754    __imm2(__Proxy[\E\],reflect(x), reflect(y))
1755immutableArray[\E\](x:ZZ32,y:ZZ32,z:ZZ32):ImmutableArray[\E,(ZZ32,ZZ32,ZZ32)\] =
1756    __imm3(__Proxy[\E\],reflect(x), reflect(y), reflect(z))
1757*)
1758
1759(* This should be local to immutableArray, but we don't support local
1760   parametric methods in the language spec at all at the moment. *)
1761__imm1[\E, nat n\](w:__Proxy[\E\],x:N[\n\]):ImmutableArray1[\E,0,n\] =
1762   immutableArray1[\E,n\]()
1763(*
1764__imm2[\E, nat n, nat m\](w:__Proxy[\E\],x:N[\n\],y:N[\m\]):
1765    ImmutableArray2[\E,0,n,0,m\] = immutableArray2[\E,n,m\]()
1766__imm3[\E, nat n, nat m, nat p\](w:__Proxy[\E\],x:N[\n\],y:N[\m\],z:N[\p\]):
1767    ImmutableArray3[\E,0,n,0,m,0,p\] = immutableArray3[\E,n,m,p\]()
1768*)
1769
1770primitiveArray[\E\](x:ZZ32):Array[\E,ZZ32\] = __parr(__Proxy[\E\],reflect(x))
1771__parr[\E, nat n\](w:__Proxy[\E\],x:N[\n\]):PrimitiveArray[\E,n\] =
1772    PrimitiveArray[\E,n\]()
1773
1774primitiveImmutableArray[\E\](x:ZZ32):ImmutableArray[\E,ZZ32\] =
1775    __piarr(__Proxy[\E\],reflect(x))
1776__piarr[\E, nat n\](w:__Proxy[\E\],x:N[\n\]):PrimImmutableArray[\E,n\] =
1777    PrimImmutableArray[\E,n\]()
1778
1779(** NOTE: StandardImmutableArrayType is a parent of
1780    StandardMutableArrayType.  It therefore doesn't extend
1781    ImmutableArray as you might expect.  Other types that extend
1782    it should also extend ImmutableArray explicitly. **)
1783trait StandardImmutableArrayType[\T extends StandardImmutableArrayType[\T,E,I\],E,I\]
1784        extends { ReadableArray[\E,I\] }
1785    fill(f:I->E):T = do
1786        for i <- zeroIndices() do init0(i,f(toIndex(i))) end
1787        self
1788      end
1789    fill(v:E):T = do
1790        for i <- zeroIndices() do init0(i,v) end
1791        self
1792      end
1793
1794    copy():T
1795end
1796
1797
1798trait StandardMutableArrayType[\T extends StandardMutableArrayType[\T,E,I\],E,I\]
1799        extends { StandardImmutableArrayType[\T,E,I\], Array[\E,I\] }
1800    assign(v:T):T = do
1801        for i <- zeroIndices() do put(i,v.get(i)) end
1802        self
1803      end
1804    assign(f:I->E):T = do
1805        for i <- zeroIndices() do put(i,f(toIndex(i))) end
1806        self
1807      end
1808end
1809
1810(* Canonical partitioning of a positive number x into two pieces.  If
1811     (a,b) = partition(n)
1812   and n > 0 then 0 < a <= b,  n = a + b.
1813   As it turns out we choose a to be the largest power of 2 < n.
1814*)
1815partition(x:ZZ32):(ZZ32,ZZ32) = do
1816    m = partitionL(x)
1817    (m,x-m)
1818  end
1819
1820(** A ReadableArray1[\T,b0,s0\] is an arbitrary 1-dimensional array
1821    whose s0 elements are of type T, and whose lowest index is b0.
1822
1823    The natural order of all generators is from b0 to b0+s0-1. **)
1824trait ReadableArray1[\T, nat b0, nat s0\]
1825        extends { Indexed1[\s0\], Rank1, ReadableArray[\T,ZZ32\] }
1826        comprises { ImmutableArray1[\T,b0,s0\], Array1[\T,b0,s0\] }
1827    getter size():ZZ32 = s0
1828    getter bounds():ScalarRange[\ZZ32,true\] = ParRange[\ZZ32,true\](b0,s0)
1829    getter mutability():String
1830    getter toString() = do
1831        r = "[" b0 "#" s0 "]" mutability() " = ["
1832        if s0=0 then
1833            r "]"
1834        else
1835            f(i:ZZ32,t:T):String = " " t
1836            j(a:String,b:String):String = a b
1837            r indexValuePairs().mapReduce[\String\](f,j,"") " ]"
1838        end
1839      end
1840
1841    opr |self| : ZZ32 = s0
1842
1843    subarray[\nat b, nat s, nat o\]():ReadableArray1[\T, b, s\]
1844
1845    (* Offset converts from b0 indexing to 0 indexing,
1846       bounds checking en route *)
1847    offset(i:ZZ32):ZZ32 = do
1848        r = i - b0
1849        if NOT (0 <= r < s0) then oops(1, b0, s0, i) end
1850        r
1851    end
1852    toIndex(i:ZZ32):ZZ32 = i + b0
1853
1854    zeroIndices(): ScalarRange[\ZZ32,true\] = ParRange[\ZZ32,true\](0,s0)
1855end
1856
1857trait ImmutableArray1[\T, nat b0, nat s0\]
1858    extends { StandardImmutableArrayType[\ImmutableArray1[\T,b0,s0\],T,ZZ32\],
1859              ImmutableArray[\T,ZZ32\], ReadableArray1[\T,b0,s0\] }
1860    getter mutability():String = "(immutable)"
1861    shift(o:ZZ32): ImmutableArray[\T,ZZ32\] =
1862        if o=0 then
1863            self
1864        else
1865            __subarrayI(self,reflect(o),N[\s0\],N[\b0\])
1866        end
1867
1868    opr[r: Range[\ZZ32\]] : ImmutableArray[\T,ZZ32\] = do
1869        r' = (bounds())[r]
1870        z = N[\0\]
1871        s = reflect( |r'| )
1872        l = reflect(r'.lower())
1873        __subarrayI(self,z,s,l)
1874      end
1875    opr[_:OpenRange[\ZZ32\]] : ImmutableArray1[\T,0,s0\] =
1876        subarray[\0,s0,0\]()
1877    opr[_:OpenRange[\Any\]] : ImmutableArray1[\T,0,s0\] =
1878        subarray[\0,s0,0\]()
1879
1880    (** subarray selects a subarray of this array based on static parameters.
1881        b#s are the new bounds of the array; o is
1882        the index of the subarray within the current array. **)
1883    subarray[\nat b, nat s, nat o\]():ImmutableArray1[\T, b, s\] = do
1884        boundsCheck = (bounds())[o#s]
1885        __ImmutableSubArray1[\T,b,s,b0,s0\](self,o-b0,1)
1886    end
1887
1888    (* the replica method returns a replica of the array (similar layout
1889       etc.) but with a different element type. *)
1890    replica[\U\]():ImmutableArray1[\U,b0,s0\] = __immutableFactory1[\U,b0,s0\]()
1891
1892    copy():ImmutableArray1[\T,b0,s0\] =
1893        replica[\T\]().fill(fn (i:ZZ32):T => get(i-b0))
1894
1895    thaw():Array1[\T,b0,s0\] =
1896        __builtinFactory1[\T,b0,s0\]().fill(fn (i:ZZ32):T => get(i-b0))
1897
1898    map[\R\](f:T->R): ImmutableArray1[\R,b0,s0\] =
1899        replica[\R\]().fill(fn (i:ZZ32):R => f(get(i-b0)))
1900    ivmap[\R\](f:(ZZ32,T)->R): ImmutableArray1[\R,b0,s0\] =
1901        replica[\R\]().fill(fn (i:ZZ32):R => f(i,get(i-b0)))
1902end
1903
1904(** Array1[\T,b0,s0\] is a 1-dimension array whose s0 elements are of
1905    type T, and whose lowest index is b0. **)
1906trait Array1[\T, nat b0, nat s0\]
1907    extends { ReadableArray1[\T,b0,s0\],
1908              StandardMutableArrayType[\Array1[\T,b0,s0\],T,ZZ32\] }
1909    excludes {Number, String}
1910
1911    getter mutability():String = ""
1912
1913    shift(o:ZZ32): Array[\T,ZZ32\] =
1914        if o=0 then
1915            self
1916        else
1917            __subarray(self,reflect(o),N[\s0\],N[\b0\])
1918        end
1919
1920    opr[r: Range[\ZZ32\]] : Array[\T,ZZ32\] = do
1921        r' = (bounds())[r]
1922        z = N[\0\]
1923        s = reflect( |r'| )
1924        l = reflect(r'.lower())
1925        __subarray(self,z,s,l)
1926      end
1927    opr[_:OpenRange[\ZZ32\]] : Array1[\T,0,s0\] =
1928        subarray[\0,s0,0\]()
1929    opr[_:OpenRange[\Any\]] : Array1[\T,0,s0\] =
1930        subarray[\0,s0,0\]()
1931
1932    (** subarray selects a subarray of this array based on static parameters.
1933        b#s are the new bounds of the array; o is
1934        the index of the subarray within the current array. **)
1935    subarray[\nat b, nat s, nat o\]():Array1[\T, b, s\] = do
1936      boundsCheck = (bounds())[o#s]
1937      __SimpleSubArray1[\T,b,s,b0,s0\](self,o-b0,1)
1938    end
1939
1940    (* the replica method returns a replica of the array (similar layout
1941       etc.) but with a different element type. *)
1942    replica[\U\]():Array1[\U,b0,s0\] = __builtinFactory1[\U,b0,s0\]()
1943
1944    copy():Array1[\T,b0,s0\] =
1945        replica[\T\]().fill(fn (i:ZZ32):T => get(i-b0))
1946
1947    freeze():ImmutableArray1[\T,b0,s0\] =
1948        __immutableFactory1[\T,b0,s0\]().fill(fn (i:ZZ32):T => get(i-b0))
1949
1950    map[\R\](f:T->R): Array1[\R,b0,s0\] =
1951        replica[\R\]().fill(fn (i:ZZ32):R => f(get(i-b0)))
1952    ivmap[\R\](f:(ZZ32,T)->R): Array1[\R,b0,s0\] =
1953        replica[\R\]().fill(fn (i:ZZ32):R => f(i,get(i-b0)))
1954end
1955
1956(* WORK AROUND absence of type inference in method calls. *)
1957__subarray[\T, nat b0, nat s0, nat b, nat s, nat o\]
1958          (it:Array1[\T,b0,s0\],
1959           _:N[\b\],_:N[\s\],_:N[\o\]):Array1[\T,b,s\] =
1960    it.subarray[\b,s,o\]()
1961
1962__subarrayI[\T, nat b0, nat s0, nat b, nat s, nat o\]
1963          (it:ImmutableArray1[\T,b0,s0\],
1964           _:N[\b\],_:N[\s\],_:N[\o\]):ImmutableArray1[\T,b,s\] =
1965    it.subarray[\b,s,o\]()
1966
1967
1968(** A 1-D subarray of an Array1.
1969    b_a#s_a is the underlying array's bounds; b0#s0 is the
1970    result bounds.  o0 is the starting offset in the underlying array,
1971    defined in 0-indexed space.  m0 the stride within that array.
1972    Invariant: (s0-1) m0 + o0 - b_a) < s_a *)
1973object __SimpleSubArray1[\T, nat b0, nat s0, nat b_a, nat s_a\]
1974       (arr:Array1[\T,b_a,s_a\], o0:ZZ32, m0:ZZ32)
1975       extends Array1[\T, b0, s0\]
1976    index(i:ZZ32):T = i m0 + o0
1977    get(i:ZZ32):T = arr.get(index(i))
1978    put(i:ZZ32,v:T): () = arr.put(index(i),v)
1979    init0(i:ZZ32,v:T): () = arr.init0(index(i),v)
1980    subarray[\nat b, nat s, nat o\]():Array1[\T, b, s\] = do
1981        boundsCheck = (bounds())[o#s]
1982        o_n : ZZ32 = o - b0
1983        __SimpleSubArray1[\T, b, s, b_a, s_a\](arr, index(o_n), m0)
1984      end
1985end
1986
1987(** The same as above, but immutable. **)
1988object __ImmutableSubArray1[\T, nat b0, nat s0, nat b_a, nat s_a\]
1989       (arr:ImmutableArray1[\T,b_a,s_a\], o0:ZZ32, m0:ZZ32)
1990       extends ImmutableArray1[\T, b0, s0\]
1991    index(i:ZZ32):T = i m0 + o0
1992    get(i:ZZ32):T = arr.get(index(i))
1993    put(i:ZZ32,v:T): () = arr.put(index(i),v)
1994    init0(i:ZZ32,v:T): () = arr.init0(index(i),v)
1995    subarray[\nat b, nat s, nat o\]():ImmutableArray1[\T, b, s\] = do
1996        boundsCheck = (bounds())[o#s]
1997        o_n : ZZ32 = o - b0
1998        __ImmutableSubArray1[\T, b, s, b_a, s_a\](arr, index(o_n), m0)
1999      end
2000end
2001
2002trait AnyVector end
2003
2004trait Vector[\T extends Number, nat s0\]
2005        extends { AnyVector, Array1[\T,0,s0\], AdditiveGroup[\Vector[\T,s0\]\] }
2006        excludes { AnyMultiplicativeRing }
2007    opr +(self, v:Vector[\T,s0\]): Vector[\T,s0\] =
2008        ivmap[\T\](fn (i:ZZ32, e: T):T => e + v.get(i))
2009    opr -(self, v:Vector[\T,s0\]): Vector[\T,s0\] =
2010        ivmap[\T\](fn (i:ZZ32, e: T):T => e - v.get(i))
2011    opr -(self): Vector[\T,s0\] = map[\T\](fn (e: T):T => - e)
2012    scale(t: T): Vector[\T,s0\] = map[\T\](fn (v) => t v)
2013    pmul(v: Vector[\T,s0\]): Vector[\T,s0\] =
2014        ivmap[\T\](fn (i:ZZ32, e: T):T => e v.get(i))
2015    dot(v: Vector[\T,s0\]): T =
2016        SUM [(i,me_i)<-indexValuePairs()] me_i v.get(i)
2017end
2018
2019object __DefaultVector[\T, nat s0\]() extends Vector[\T,s0\]
2020  mem: PrimitiveArray[\T,s0\] = PrimitiveArray[\T,s0\]()
2021  get(i:ZZ32):T = mem.get(i)
2022  put(i:ZZ32, v:T) = mem.put(i,v)
2023  init0(i:ZZ32, v:T) = mem.init0(i,v)
2024  replica[\U\]() = array1[\U,s0\]()
2025end
2026
2027(* builtinFactory1 must be a non-overloaded 0-parameter factory for
2028   1-D arrays.  The type parameters are enshrined in LHSEvaluator.java
2029   and NonPrimitive.java; the factory name is enshrined in
2030   WellKnownNames.java.  There must be some factory, named in this
2031   file, with this type signature.  A similar thing is true for
2032   K-dimensional array types. *)
2033__builtinFactory1[\T, nat b0, nat s0\]():Array1[\T,b0,s0\] = do
2034    r = array1[\T,s0\]()
2035    typecase _ = N[\b0\] of
2036        N[\0\] => r
2037        else => r.subarray[\b0,s0,0\]()
2038    end
2039  end
2040
2041(* immutableFactory1 is a non-overloaded 0-parameter factory for
2042   0-indexed 1-D arrays.  It is also mentioned in WellKnownNames as it
2043   is used to allocate storage for varargs. *)
2044__immutableFactory1[\T, nat b0, nat s0\]():ReadableArray1[\T,b0,s0\] = do
2045    r = immutableArray1[\T,s0\]()
2046    typecase _ = N[\b0\] of
2047        N[\0\] => r
2048        else => r.subarray[\b0,s0,0\]()
2049    end
2050  end
2051
2052(* TODO: fix when Number is covariant. *)
2053array1[\T, nat s0\]():Array1[\T,0,s0\] =
2054    typecase _ = __Proxy[\T\] of
2055        __Proxy[\ZZ32\] => vector[\T,s0\]()
2056        __Proxy[\ZZ64\] => vector[\T,s0\]()
2057        __Proxy[\RR64\] => vector[\T,s0\]()
2058        __Proxy[\Number\] => vector[\T,s0\]()
2059        else => PrimitiveArray[\T,s0\]()
2060    end
2061array1[\T, nat s0\](v:T):Array1[\T,0,s0\] = array1[\T,s0\]().fill(v)
2062array1[\T, nat s0\](f:ZZ32->T):Array1[\T,0,s0\] = array1[\T,s0\]().fill(f)
2063
2064immutableArray1[\T, nat s0\](): ImmutableArray1[\T,0,s0\] =
2065    PrimImmutableArray[\T,s0\]()
2066
2067(* vector is the same as array1, but specialized to numeric type arguments *)
2068vector[\T extends Number, nat s0\]():Vector[\T,s0\] = __DefaultVector[\T,s0\]()
2069vector[\T extends Number, nat s0\](v:T):Vector[\T,s0\] =
2070    vector[\T,s0\]().fill(v)
2071vector[\T extends Number, nat s0\](f:ZZ32->T):Vector[\T,s0\] =
2072    vector[\T,s0\]().fill(f)
2073
2074pmul[\ T extends Number, nat k \]
2075    (a : Vector[\T,k\], b : Vector[\T,k\]):Vector[\T,k\] = a.pmul(b)
2076
2077opr DOT[\ T extends Number, nat n \]
2078       (me : Vector[\T,n\], other : Vector[\T,n\]):T = me.dot(other)
2079
2080opr juxtaposition[\ T extends Number, nat n \]
2081     (me : Vector[\T,n\], other : Vector[\T,n\]):T = me.dot(other)
2082
2083opr DOT[\ T extends Number, nat n \]
2084       (me : Vector[\T,n\], other : T) : Vector[\T,n\] = me.scale(other)
2085
2086opr juxtaposition[\ T extends Number, nat n \]
2087     (me : Vector[\T,n\], other : T) : Vector[\T,n\] = me.scale(other)
2088
2089opr DOT[\ T extends Number, nat n \]
2090        (other : T, me : Vector[\T,n\]) : Vector[\T,n\] = me.scale(other)
2091
2092opr juxtaposition[\ T extends Number, nat n \]
2093     (other : T, me : Vector[\T,n\]) : Vector[\T,n\] = me.scale(other)
2094
2095squaredNorm[\T extends Number, nat s0\](a:Vector[\T,s0\]):T = a.dot(a)
2096
2097opr ||[\ T extends Number, nat k \]me : Vector[\T,k\]|| : RR64 = SQRT squaredNorm(me)
2098
2099(** Array2[\T,b0,s0,b1,s1\] is the type of 2-dimensional arrays of
2100    element type T, with size s0 in the first dimension and s1 in the
2101    second dimension and lowest index (b0,b1).  Natural order for all
2102    generators in each dimension is from b to b+s-1; the overall order
2103    of elements need only be consistent with the cross product of
2104    these orderings (see Generator.cross()). **)
2105trait Array2[\T, nat b0, nat s0, nat b1, nat s1\]
2106    extends { Indexed1[\s0\], Indexed2[\s1\], Rank2,
2107              StandardMutableArrayType[\Array2[\T,b0,s0,b1,s1\],T,(ZZ32,ZZ32)\] }
2108    excludes { Number, String }
2109  getter size():ZZ32 = s0 s1
2110  getter bounds():Tuple2Range[\ZZ32,ZZ32,true\] = Tuple2Range[\ZZ32,ZZ32,true\](b0,b1,s0,s1)
2111  getter toString() = do
2112    r : String := "[" b0 "#" s0 "," b1 "#" s1 "] ="
2113    row(i) =
2114      for j <- seq(0#s1) do
2115         r := r " " get(i,j)
2116      end
2117    if s0 = 0 then
2118      r " []"
2119    else
2120      r := r "\n["
2121      row(0)
2122      for i <- seq(1#(s0-1)) do
2123        r := r "\n "
2124        row(i)
2125      end
2126      r " ]"
2127    end
2128  end
2129  opr |self| : ZZ32 = s0 s1
2130  (* Translate from b0,b1-indexing to 0-indexing, checking bounds. *)
2131  offset(t_1:(ZZ32,ZZ32)):(ZZ32,ZZ32) = do
2132    (a0,a1) = t_1
2133    c0 = a0 - b0
2134    c1 = a1 - b1
2135    if NOT (0 <= c0 < s0) then
2136        oops(1,b0,s0,a0)
2137    elif NOT (0 <= c1 < s1) then
2138        oops(2,b1,s1,a1)
2139    else
2140        (c0,c1)
2141    end
2142  end
2143  toIndex(t_1:(ZZ32,ZZ32)):(ZZ32,ZZ32) = do (a0,a1)=t_1; (a0+b0,a1+b1) end
2144  opr[x:ZZ32,y:ZZ32]:=(v:T):() = do self[ (x,y) ] := v end
2145  opr[r:Range[\(ZZ32,ZZ32)\]]: Array[\T,(ZZ32,ZZ32)\] = do
2146      r' = (bounds())[r]
2147      (z0,z1) = r'.extent()
2148      (l0,l1) = r'.lower()
2149      __subarray(self, N[\0\],reflect(z0), N[\0\], reflect(z1),
2150                 reflect(l0),reflect(l1))
2151    end
2152  opr[_:OpenRange[\ZZ32\]] : Array2[\T,0,s0,0,s1\] =
2153      subarray[\0,s0,0,s1,0,0\]()
2154  opr[_:OpenRange[\Any\]] : Array2[\T,0,s0,0,s1\] =
2155      subarray[\0,s0,0,s1,0,0\]()
2156  shift(t_1:(ZZ32,ZZ32)): Array[\T,(ZZ32,ZZ32)\] = do
2157      (o0,o1)=t_1
2158      if o0=0 AND o1=0 then
2159          self
2160      else
2161          __subarray(self,reflect(o0),N[\s0\], reflect(o1),N[\s1\], N[\b0\],N[\b1\])
2162      end
2163    end
2164
2165  (** 2-D subarray given static subarray parameters.
2166      (bo1,bo2)#(so1,so2) are output bounds.
2167      The result is the subarray starting at (o0,o1) in the original array.
2168   **)
2169  subarray[\nat bo0, nat so0, nat bo1, nat so1, nat o0, nat o1\]
2170          (): Array2[\T,bo0,so0,bo1,so1\] = do
2171      boundsCheck = (bounds())[ (o0,o1)#(so0,so1) ]
2172      SubArray2[\T,bo0,so0,bo1,so1,b0,s0,b1,s1\](self,1,o0,1,o1)
2173    end
2174
2175  zeroIndices():Tuple2Range[\ZZ32,ZZ32,true\] = Tuple2Range[\ZZ32,ZZ32,true\](0,0,s0,s1)
2176
2177  replica[\U\]():Array2[\U,b0,s0,b1,s1\] =
2178      __builtinFactory2[\U,b0,s0,b1,s1\]()
2179  copy():Array2[\T,b0,s0,b1,s1\] =
2180      self.replica[\T\]().fill(fn (i:ZZ32,j:ZZ32):T => get(i-b0,j-b1))
2181  put(t1:(ZZ32, ZZ32), v:T) : ()
2182  get(t1:(ZZ32, ZZ32)):T
2183  t():Array2[\T,b1,s1,b0,s0\] = TransposedArray2[\T,b1,s1,b0,s0\](self)
2184  (* Copied here for better return type information. *)
2185  map[\R\](f:T->R): Array2[\R,b0,s0,b1,s1\] =
2186      replica[\R\]().fill(fn (i:ZZ32,j:ZZ32):R => f(get(i-b0,j-b1)))
2187  ivmap[\R\](f:((ZZ32,ZZ32),T)->R): Array2[\R,b0,s0,b1,s1\] =
2188      replica[\R\]().fill(fn (i:ZZ32,j:ZZ32):R => f((i,j),get(i-b0,j-b1)))
2189
2190  freeze():ImmutableArray[\T,(ZZ32,ZZ32)\] = fail("Freeze not defined yet!")
2191end
2192
2193(** Hoisted out here to work around the lack of method type inference. **)
2194__subarray[\T, nat b0, nat s0, nat b1, nat s1,
2195           nat bo0, nat so0, nat bo1, nat so1, nat o0, nat o1\]
2196        (this:Array2[\T,b0,s0,b1,s1\],
2197         _:N[\bo0\],_:N[\so0\],_:N[\bo1\],_:N[\so1\],
2198         _:N[\o0\],_:N[\o1\]): Array2[\T,bo0,so0,bo1,so1\] = do
2199(*
2200    println("__subarray[\\" b0 "," s0 "," b1 "," s1 ", "
2201            bo0 "," so0 "," bo1 "," so1 ", " o0 "," o1 "\\]()")
2202*)
2203    this.subarray[\bo0,so0,bo1,so1,o0,o1\]()
2204  end
2205
2206(** Default array is column-major, but we could switch it. **)
2207object __DefaultArray2[\T, nat b0, nat s0, nat b1, nat s1\]()
2208        extends Array2[\T, b0, s0, b1, s1\]
2209    mem:PrimitiveArray[\T, (s0 s1) \] = PrimitiveArray[\T, (s0 s1) \]()
2210    init0(t_1:(ZZ32,ZZ32), v:T) : () = do (i,j)=t_1; mem.init0(i s1 + j, v) end
2211    put(t_1:(ZZ32,ZZ32), v:T) : () = do (i,j)=t_1; mem.put(i s1 + j, v) end
2212    get(t_1:(ZZ32,ZZ32)):T = do (i,j)=t_1; mem.get(i s1 + j) end
2213end
2214
2215(** Transposes the index of the underlying array mem, and transposes
2216    its natural order as well. **)
2217object TransposedArray2[\T, nat b0, nat s0, nat b1, nat s1\]
2218                       (mem:Array2[\T,b1,s1,b0,s0\])
2219    extends Array2[\T, b0, s0, b1, s1\]
2220  replica[\U\]():Array2[\U,b0,s0,b1,s1\] = mem.replica[\U\]().t()
2221
2222  init0(t_1:(ZZ32,ZZ32), v:T) : () = do (i,j)=t_1; mem.init0((j,i),v) end
2223  put(t_1:(ZZ32,ZZ32), v:T) : () = do (i,j)=t_1; mem.put((j,i),v) end
2224  get(t_1:(ZZ32,ZZ32)):T = do (i,j)=t_1; mem.get(j,i) end
2225  t() = mem
2226end
2227
2228(** Simple 2-D subarray, used when we have no other knowledge of the
2229    underlying structure.  If we're on top of a PrimitiveArray we can
2230    really do much better than this.
2231    (b0,b1)#(s0,s1) are the bounds of the subarray.
2232    (bu0,bu1)#(su0,su1) are the bounds of the underlying array.
2233    m_i, o_i are multiplier and offset (0-based) of dimension i.
2234**)
2235object SubArray2[\T, nat b0, nat s0, nat b1, nat s1,
2236                     nat bu0, nat su0, nat bu1, nat su1\]
2237                (mem: Array2[\T,bu0,su0,bu1,su1\],
2238                 m0:ZZ32, o0:ZZ32, m1:ZZ32, o1:ZZ32)
2239        extends Array2[\T,b0,s0,b1,s1\]
2240    index(a0:ZZ32, a1:ZZ32): (ZZ32,ZZ32) = (m0 a0 + o0, m1 a1 + o1)
2241    init0(t_1:(ZZ32,ZZ32), v:T): () = mem.init0(index(t_1),v)
2242    put(t_1:(ZZ32,ZZ32), v:T): () = mem.put(index(t_1),v)
2243    get(t_1:(ZZ32,ZZ32)): T = mem.get(index(t_1))
2244end
2245
2246trait AnyMatrix end
2247
2248trait Matrix[\T extends Number, nat s0, nat s1\]
2249        extends { AnyMatrix, Array2[\T, 0, s0, 0, s1\], AdditiveGroup[\Matrix[\T,s0,s1\]\] }
2250        excludes { AnyMultiplicativeRing }
2251    opr +(self, v:Matrix[\T,s0,s1\]): Matrix[\T,s0,s1\] =
2252        ivmap[\T\](fn (i:(ZZ32,ZZ32),e:T):T => e + v.get(i))
2253    opr -(self, v:Matrix[\T,s0,s1\]): Matrix[\T,s0,s1\] =
2254        ivmap[\T\](fn (i:(ZZ32,ZZ32),e:T):T => e - v.get(i))
2255    opr -(self): Matrix[\T,s0,s1\] = map[\T\](fn (e:T):T => - e)
2256    scale(t_1: T): Matrix[\T,s0,s1\] = map[\T\](fn (e:T):T => t_1 e)
2257    mul[\ nat s2 \](other: Matrix[\T,s1,s2\]): Matrix[\T,s0,s2\] = do
2258        res = matrix[\T,s0,s2\]()
2259        mma(a:ZZ32,i:ZZ32,b:ZZ32,j:ZZ32,c:ZZ32,k:ZZ32):() =
2260            if k>=i AND k>=j then
2261              if k=1 then
2262                pr : T = get(a,b) other.get(b,c)
2263                (* If this were atomic, we could parallelize j-partition. *)
2264                res.put((a,c), res.get(a,c) + pr)
2265              else
2266                (k0,k1) = partition(k)
2267                (mma(a,i,b,j,c,k0),mma(a,i,b,j,c+k0,k1))
2268              end
2269            elif j>=i then
2270                (j0,j1) = partition(j)
2271                mma(a,i,b,j0,c,k)
2272                mma(a,i,b+j0,j1,c,k)
2273            else
2274                (i0,i1) = partition(i)
2275                (mma(a,i0,b,j,c,k),mma(a+i0,i1,b,j,c,k))
2276            end
2277        mm(a:ZZ32,i:ZZ32,b:ZZ32,j:ZZ32,c:ZZ32,k:ZZ32):() =
2278            if k>=i AND k>=j then
2279              if k=1 then
2280                res.put((a,c), get(a,b) other.get(b,c))
2281              else
2282                (k0,k1) = partition(k)
2283                (mm(a,i,b,j,c,k0),mm(a,i,b,j,c+k0,k1))
2284              end
2285            elif j>=i then
2286                (j0,j1) = partition(j)
2287                mm(a,i,b,j0,c,k)
2288                mma(a,i,b+j0,j1,c,k)
2289            else
2290                (i0,i1) = partition(i)
2291                (mm(a,i0,b,j,c,k),mm(a+i0,i1,b,j,c,k))
2292            end
2293        if s0=0 OR s1=0 OR s2=0 then
2294          res
2295        else
2296          mm(0,s0,0,s1,0,s2)
2297          res
2298        end
2299      end
2300    rmul(v: Vector[\T,s1\]): Vector[\T,s0\] = do
2301        row(i:ZZ32):T =
2302            SUM[(j,v_j)<-v.indexValuePairs] get(i,j) v_j
2303        vector[\T,s0\]().fill(row)
2304      end
2305    lmul(v: Vector[\T,s0\]): Vector[\T,s1\] = do
2306        col(i:ZZ32):T =
2307            SUM[(j,v_j)<-v.indexValuePairs] v_j get(j,i)
2308        vector[\T,s1\]().fill(col)
2309      end
2310    t(): Matrix[\T,s1,s0\] = TransposedMatrix[\T,s1,s0\](self)
2311end
2312
2313(* Default matrix should match default array in column vs row-major. *)
2314object __DefaultMatrix[\T, nat s0, nat s1\]()
2315    extends Matrix[\T, s0, s1\]
2316  mem:PrimitiveArray[\T, (s0 s1) \] = PrimitiveArray[\T, (s0 s1) \]()
2317  init0(t_1:(ZZ32,ZZ32), v:T) : () = do (i,j)=t_1; mem.init0(i s1 + j, v) end
2318  put(t_1:(ZZ32,ZZ32), v:T) : () = do (i,j)=t_1; mem.put(i s1 + j, v) end
2319  get(t_1:(ZZ32,ZZ32)):T = do (i,j)=t_1; mem.get(i s1 + j) end
2320end
2321
2322object TransposedMatrix[\T, nat s0, nat s1\](mem:Matrix[\T,s1,s0\])
2323        extends Matrix[\T, s0, s1\]
2324    replica[\U\]():Array2[\U,0,s0,0,s1\] = mem.replica[\U\]().t()
2325
2326    init0(t_1:(ZZ32,ZZ32), v:T) : () = do (i,j)=t_1; mem.init0((j,i),v) end
2327    put(t_1:(ZZ32,ZZ32), v:T) : () = do (i,j)=t_1; mem.put((j,i),v) end
2328    get(t_1:(ZZ32,ZZ32)):T = do (i,j)=t_1; mem.get(j,i) end
2329    t(): Matrix[\T,s1,s0\] = mem
2330    add(v:TransposedMatrix[\T,s0,s1\]): Matrix[\T,s0,s1\] = mem.add(v.t()).t()
2331    subtract(v:Matrix[\T,s0,s1\]): Matrix[\T,s0,s1\] = mem.subtract(v.t()).t()
2332    negate(): Matrix[\T,s0,s1\] = mem.negate().t()
2333    scale(f: T): Matrix[\T,s0,s1\] = mem.scale(f).t()
2334    rmul(v: Vector[\T,s1\]): Vector[\T,s0\] = mem.lmul(v)
2335    lmul(v: Vector[\T,s0\]): Vector[\T,s1\] = mem.rmul(v)
2336(*  Can't overload generic methods yet, but this is preferable.
2337    mul[\nat s2\](v:TransposedMatrix[\T,s1,s2\]): Matrix[\T,s0,s2\] =
2338        v.t().mul(mem).t()
2339*)
2340end
2341
2342__builtinFactory2[\T,nat b0,nat s0,nat b1,nat s1\]():Array2[\T,b0,s0,b1,s1\] =
2343    if b0=0 AND b1=0 then
2344        array2[\T,s0,s1\]()
2345    else
2346        __DefaultArray2[\T,b0,s0,b1,s1\]()
2347    end
2348
2349(* array2 is a factory for 0-based 2-D arrays. *)
2350(* TODO: fix when Number is covariant. *)
2351array2[\T, nat s0, nat s1\]():Array2[\T,0,s0,0,s1\] =
2352    typecase _ = __Proxy[\T\] of
2353        __Proxy[\ZZ32\] => matrix[\T,s0,s1\]()
2354        __Proxy[\ZZ64\] => matrix[\T,s0,s1\]()
2355        __Proxy[\RR64\] => matrix[\T,s0,s1\]()
2356        __Proxy[\Number\] => matrix[\T,s0,s1\]()
2357        else => __DefaultArray2[\T,0,s0,0,s1\]()
2358    end
2359array2[\T, nat s0, nat s1\](v:T):Array2[\T,0,s0,0,s1\] =
2360  array2[\T,s0,s1\]().fill(v)
2361array2[\T, nat s0, nat s1\](f:(ZZ32,ZZ32)->T):Array2[\T,0,s0,0,s1\] =
2362  array2[\T,s0,s1\]().fill(f)
2363
2364(* matrix is the same as array1, but specialized to numeric type
2365   arguments, except that the default value (if given) is used to
2366   construct a multiple of the identity matrix. *)
2367matrix[\T extends Number, nat s0, nat s1\]():Matrix[\T,s0,s1\] =
2368  __DefaultMatrix[\T,s0,s1\]()
2369matrix[\T extends Number, nat s0, nat s1\](v:T):Matrix[\T,s0,s1\] =
2370  array2[\T,s0,s1\]().fill(fn (x:ZZ32,y:ZZ32):T => if x=y then v else 0 end)
2371
2372(* Matrix multiplication; used to use a cache-oblivious algorithm, but
2373   we ran into trouble due to lack of support for atomic increment of
2374   matrix elements. *)
2375opr DOT[\ T extends Number, nat n, nat m, nat p\]
2376       (me:Matrix[\T,n,m\], other:Matrix[\T,m,p\]): Matrix[\T,n,p\] =
2377        me.mul[\p\](other)
2378
2379opr juxtaposition[\ T extends Number, nat n, nat m, nat p\]
2380     (me:Matrix[\T,n,m\], other:Matrix[\T,m,p\]): Matrix[\T,n,p\] =
2381        me.mul[\p\](other)
2382
2383
2384(* matrix-vector multiplication *)
2385opr DOT[\ T extends Number, nat n, nat m \]
2386       (me:Matrix[\T,n,m\], v:Vector[\T,m\]):Vector[\T,n\] = me.rmul(v)
2387
2388opr juxtaposition[\ T extends Number, nat n, nat m \]
2389     (me:Matrix[\T,n,m\], v:Vector[\T,m\]):Vector[\T,n\] = me.rmul(v)
2390
2391(* vector-matrix multiplication *)
2392opr DOT[\ T extends Number, nat n, nat m \]
2393       (v:Vector[\T,n\], me:Matrix[\T,n,m\]):Vector[\T,m\] = me.lmul(v)
2394
2395opr juxtaposition[\ T extends Number, nat n, nat m \]
2396     (v:Vector[\T,n\], me:Matrix[\T,n,m\]):Vector[\T,m\] = me.lmul(v)
2397
2398opr DOT[\ T extends Number, nat n, nat m \]
2399       (me : Matrix[\T,n,m\], other : T) : Matrix[\T,n,m\] = me.scale(other)
2400
2401opr juxtaposition[\ T extends Number, nat n, nat m \]
2402     (me : Matrix[\T,n,m\], other : T) : Matrix[\T,n,m\] = me.scale(other)
2403
2404opr DOT[\ T extends Number, nat n, nat m \]
2405       (other : T, me : Matrix[\T,n,m\]) : Matrix[\T,n,m\] = me.scale(other)
2406
2407opr juxtaposition[\ T extends Number, nat n, nat m \]
2408     (other : T, me : Matrix[\T,n,m\]) : Matrix[\T,n,m\] = me.scale(other)
2409
2410(** Array3[\T,b0,s0,b1,s1,b2,s2\] is the type of 3-dimensional arrays
2411    of element type T, with size s_i in the i^th dimension and lowest
2412    index (b0,b1,b2).  Natural order for all generators in each
2413    dimension is from b to b+s-1; the overall order of elements need
2414    only be consistent with the cross product of these orderings (see
2415    Generator.cross()). **)
2416trait Array3[\T, nat b0, nat s0, nat b1, nat s1, nat b2, nat s2\]
2417    extends { Indexed1[\s0\], Indexed2[\s1\], Indexed3[\s2\], Rank3,
2418              StandardMutableArrayType[\Array3[\T,b0,s0,b1,s1,b2,s2\],T,
2419                                        (ZZ32,ZZ32,ZZ32)\] }
2420    excludes { Number, String }
2421
2422    getter size():ZZ32 = s0 s1 s2
2423    getter bounds():Tuple3Range[\ZZ32,ZZ32,ZZ32,true\] =
2424        Tuple3Range[\ZZ32,ZZ32,ZZ32,true\](b0,b1,b2,s0,s1,s2)
2425
2426    getter toString():String = do
2427      r : String := "[" b0 "#" s0 "," b1 "#" s1 "," b2 "#" s2 "] ="
2428      row(i,k) =
2429          for j <- seq(0#s1) do
2430            r := r " " self[b0+i,b1+j,b2+k]
2431          end
2432      plane(k) =
2433        if s1 > 0 then
2434          row(0,k)
2435          for i <- seq(1#(s0-1)) do
2436            r := r "\n "
2437            row(i,k)
2438          end
2439        end
2440      if s0=0 then
2441        r " []"
2442      else
2443        r := r "\n["
2444        plane(0)
2445        for k <- seq(1#(s2-1)) do
2446          r := r " ;;\n "
2447          plane(k)
2448        end
2449        r " ]"
2450      end
2451    end
2452
2453    opr |self| : ZZ32 = s0 s1 s2
2454
2455    (* Again, offset performs bounds checking and shifts to 0 indexing. *)
2456    offset(t:(ZZ32,ZZ32,ZZ32)):(ZZ32,ZZ32,ZZ32) = do
2457      (a0,a1,a2)=t
2458      c0 = a0 - b0; c1 = a1 - b1; c2 = a2 - b2
2459      if NOT (0 <= c0 < s0) then oops(1, b0, s0, a0); end
2460      if NOT (0 <= c1 < s1) then oops(2, b1, s1, a1); end
2461      if NOT (0 <= c2 < s2) then oops(3, b2, s2, a2); end
2462      (c0,c1,c2)
2463    end
2464    toIndex(t:(ZZ32,ZZ32,ZZ32)):(ZZ32,ZZ32,ZZ32) =
2465        do (a0,a1,a2) = t; (a0+b0,a1+b1,a2+b2) end
2466
2467    (* And get and put are 0-indexed without bounds checks. *)
2468    put(t:(ZZ32,ZZ32,ZZ32), v:T) : ()
2469    get(t:(ZZ32,ZZ32,ZZ32)):T
2470
2471    opr[i:ZZ32, j:ZZ32, k:ZZ32] := (v:T) = do self[ (i,j,k) ] := v end
2472    opr[r:Range[\(ZZ32,ZZ32,ZZ32)\]]: Array[\T,(ZZ32,ZZ32,ZZ32)\] = do
2473        r' = (bounds())[r]
2474        (z0,z1,z2) = r'.extent()
2475        (l0,l1,l2) = r'.lower()
2476        __subarray(self, N[\0\],reflect(z0), N[\0\],reflect(z1),
2477                   N[\0\],reflect(z2), reflect(l0),reflect(l1), reflect(l2))
2478      end
2479    opr[_:OpenRange[\ZZ32\]] : Array3[\T,0,s0,0,s1,0,s2\] =
2480        subarray[\0,s0,0,s1,0,s2,0,0,0\]()
2481    opr[_:OpenRange[\Any\]] : Array3[\T,0,s0,0,s1,0,s2\] =
2482        subarray[\0,s0,0,s1,0,s2,0,0,0\]()
2483    shift(t:(ZZ32,ZZ32,ZZ32)): Array[\T,(ZZ32,ZZ32)\] = do
2484        (o0,o1,o2)=t
2485        if o0=0 AND o1=0 AND o2=0 then
2486            self
2487        else
2488            __subarray(self,
2489                       reflect(o0),N[\s0\], reflect(o1),N[\s1\],
2490                       reflect(o2),N[\s2\], N[\b0\],N[\b1\],N[\b2\])
2491        end
2492      end
2493
2494    (** 3-D subarray given static subarray parameters.
2495        (bo1,bo2)#(so1,so2) are output bounds.
2496        The result is the subarray starting at (o0,o1) in the original array.
2497     **)
2498    subarray[\nat bo0, nat so0, nat bo1, nat so1, nat bo2, nat so2,
2499              nat o0, nat o1, nat o2\]
2500            (): Array3[\T,bo0,so0,bo1,so1,bo2,so2\] = do
2501        boundsCheck = (bounds())[ (o0,o1,o2)#(so0,so1,so2) ]
2502        SubArray3[\T,bo0,so0,bo1,so1,bo2,so2,b0,s0,b1,s1,b2,s2\](self,1,o0,1,o1,1,o2)
2503      end
2504
2505    zeroIndices():Tuple3Range[\ZZ32,ZZ32,ZZ32,true\] =
2506        Tuple3Range[\ZZ32,ZZ32,ZZ32,true\](0,0,0,s0,s1,s2)
2507
2508    replica[\U\]():Array3[\U,b0,s0,b1,s1,b2,s2\] =
2509        __DefaultArray3[\U,b0,s0,b1,s1,b2,s2\]()
2510    copy():Array3[\T,b0,s0,b1,s1,b2,s2\] =
2511        self.replica[\T\]().fill(fn (i:ZZ32,j:ZZ32,k:ZZ32):T =>
2512                                     get(i-b0,j-b1,k-b2))
2513    map[\R\](f:T->R): Array3[\R,b0,s0,b1,s1,b2,s2\] =
2514        replica[\R\]().fill(fn (i:ZZ32,j:ZZ32,k:ZZ32):R =>
2515                                f(get(i-b0,j-b1,k-b2)))
2516    ivmap[\R\](f:((ZZ32,ZZ32,ZZ32),T)->R): Array3[\R,b0,s0,b1,s1,b2,s2\] =
2517        replica[\R\]().fill(fn (i:ZZ32,j:ZZ32,k:ZZ32):R =>
2518                                f((i,j,k),get(i-b0,j-b1,k-b2)))
2519
2520    freeze():ImmutableArray[\T,(ZZ32,ZZ32,ZZ32)\] =
2521        fail("Freeze not defined yet!")
2522end
2523
2524(** hoisted out here to work around absence of type inference for methods. **)
2525__subarray[\T, nat b0, nat s0, nat b1, nat s1, nat b2, nat s2,
2526            nat bo0, nat so0, nat bo1, nat so1, nat bo2, nat so2,
2527            nat o0, nat o1, nat o2\]
2528      (this:Array3[\T,b0,s0,b1,s1,b2,s2\],
2529       _:N[\bo0\],_:N[\so0\],_:N[\bo1\],_:N[\so1\],_:N[\bo2\],_:N[\so2\],
2530       _:N[\o0\],_:N[\o1\],_:N[\o2\]): Array3[\T,bo0,so0,bo1,so1,bo2,so2\] =
2531    this.subarray[\bo0,so0,bo1,so1,bo2,so2,o0,o1,o2\]()
2532
2533object __DefaultArray3[\T, nat b0, nat s0, nat b1, nat s1, nat b2, nat s2\]() extends
2534                                        Array3[\T, b0, s0, b1, s1, b2, s2\]
2535  mem:PrimitiveArray[\T,(s0 (s1 s2))\] = PrimitiveArray[\T,(s0 (s1 s2))\]()
2536
2537  ofs(i:ZZ32,j:ZZ32,k:ZZ32):ZZ32 = (i s1 + j) s2 + k
2538
2539  init0(t:(ZZ32,ZZ32,ZZ32), v:T) : () = mem.init0(ofs(t),v)
2540  put(t:(ZZ32,ZZ32,ZZ32), v:T) : () = mem.put(ofs(t),v)
2541  get(t:(ZZ32,ZZ32,ZZ32)) : T = mem.get(ofs(t))
2542end
2543
2544(** Simple 3-D subarray, used when we have no other knowledge of the
2545    underlying structure.  If we're on top of a PrimitiveArray we can
2546    really do much better than this.
2547    (b0,b1,b2)#(s0,s1,s2) are the bounds of the subarray.
2548    (bu0,bu1,bu2)#(su0,su1,su2) are the bounds of the underlying array.
2549    m_i, o_i are multiplier and offset (0-based) of dimension i.
2550**)
2551object SubArray3[\T, nat b0, nat s0, nat b1, nat s1, nat b2, nat s2,
2552                     nat bu0, nat su0, nat bu1, nat su1, nat bu2, nat su2\]
2553                (mem: Array3[\T,bu0,su0,bu1,su1,bu2,su2\],
2554                 m0:ZZ32,o0:ZZ32, m1:ZZ32,o1:ZZ32, m2:ZZ32, o2:ZZ32)
2555        extends Array3[\T,b0,s0,b1,s1,b2,s2\]
2556    index(a0:ZZ32, a1:ZZ32, a2:ZZ32): (ZZ32,ZZ32,ZZ32) =
2557        (m0 a0 + o0, m1 a1 + o1, m2 a2 + o2)
2558    init0(t:(ZZ32,ZZ32,ZZ32), v:T): () = mem.init0(index(t),v)
2559    put(t:(ZZ32,ZZ32,ZZ32), v:T): () = mem.put(index(t),v)
2560    get(t:(ZZ32,ZZ32,ZZ32)): T = mem.get(index(t))
2561end
2562
2563__builtinFactory3[\T, nat b0, nat s0, nat b1, nat s1, nat b2, nat s2\]():
2564        Array3[\T,b0,s0,b1,s1,b2,s2\] =
2565  __DefaultArray3[\T,b0,s0,b1,s1,b2,s2\]()
2566
2567array3[\T,nat s0, nat s1, nat s2\]():Array3[\T,0,s0,0,s1,0,s2\] =
2568  __DefaultArray3[\T,0,s0,0,s1,0,s2\]()
2569
2570(*************
2571
2572trait Monoid[\ T, opr OPLUS \]
2573  where { T extends Monoid[\ T, OPLUS \] }
2574    zero() : T
2575    opr OPLUS(self, other:T):T
2576end
2577
2578*************)
2579
2580(************************************************************
2581* Reductions
2582************************************************************)
2583
2584trait Reduction[\L\]
2585    empty(): L
2586    join(a: L, b: L): L
2587end
2588
2589(** Invariants:
2590    join must be associative with identity empty
2591    unlift(lift(x)) = x
2592 **)
2593trait ActualReduction[\R,L\] extends Reduction[\L\]
2594    getter toString():String
2595    lift(r: Any): L
2596    unlift(l:L): R
2597    (** If this reduction left-distributes over r, return a pair of
2598        reductions with the same lift and unlift **)
2599    leftDistribute(r: Reduction[\R\]): SomeReductionPair[\R\] =
2600        distribute(r)
2601    (** If this reduction right-distributes over r, return a pair of
2602        reductions with the same lift and unlift **)
2603    rightDistribute(r: Reduction[\R\]): SomeReductionPair[\R\] =
2604        distribute(r)
2605    (** If this reduction distributes over r, return a pair of
2606        reductions with the same lift and unlift **)
2607    distribute[\K\](r: ActualReduction[\R,K\]): SomeReductionPair[\R\] =
2608        NoReductionPair[\R\]
2609end
2610
2611trait PossibleReductionPair[\R\] extends Condition[\SomeReductionPair[\R\]\]
2612    comprises { NoReductionPair[\R\], SomeReductionPair[\R\] }
2613end
2614
2615object NoReductionPair[\R\] extends PossibleReductionPair[\R\]
2616    getter holds(): Boolean = false
2617    getter cond[\G\](t:PossibleReductionPair[\R\]->G, e:()->G): G = e()
2618end
2619
2620trait SomeReductionPair[\R\] extends PossibleReductionPair[\R\]
2621    getter holds(): Boolean = true
2622    getter cond[\G\](t:PossibleReductionPair[\R\]->G, e:()->G): G = t(self)
2623    getter outer(): Reduction[\R\]
2624    getter inner(): Reduction[\R\]
2625end
2626
2627trait ReductionPair[\R,L\] extends SomeReductionPair[\R\]
2628    getter outer(): ActualReduction[\R,L\]
2629    getter inner(): ActualReduction[\R,L\]
2630end
2631
2632(** The usual lifting to Maybe for identity-less operators **)
2633trait AssociativeReduction[\R\] extends ActualReduction[\R,AnyMaybe\]
2634    empty(): Nothing[\R\] = Nothing[\R\]
2635    join(a: AnyMaybe, b: AnyMaybe): AnyMaybe =
2636        if av <- a then
2637            if bv <- b then
2638                Just(simpleJoin(av,bv))
2639            else
2640                a
2641            end
2642        else
2643            b
2644        end
2645    simpleJoin(a:Any, b:Any): Any
2646    lift(r:Any): AnyMaybe = Just(r)
2647    unlift(r:AnyMaybe): R = r.get
2648end
2649
2650trait CommutativeReduction[\R\] extends AssociativeReduction[\R\] end
2651
2652(** Monoids don't require a special lift and unlift operation. **)
2653trait MonoidReduction[\R\] extends ActualReduction[\R,R\]
2654    lift(r:Any): R = r
2655    unlift(r:R): R = r
2656end
2657
2658trait CommutativeMonoidReduction[\R\] extends MonoidReduction[\R\] end
2659
2660trait ReductionWithZeroes[\R,L\] extends ActualReduction[\R,L\]
2661    isLeftZero(l:L): Boolean = isZero(l)
2662    isRightZero(l:L): Boolean = isZero(l)
2663    isZero(l:L): Boolean = false
2664end
2665
2666trait BigOperator[\I,O,R,L\]
2667    getter reduction(): ActualReduction[\R,L\]
2668    getter body(): I->R
2669    getter unwrap(): R->O
2670end
2671
2672object BigReduction[\R,L\](r:ActualReduction[\R,L\]) extends BigOperator[\R,R,R,L\]
2673    getter reduction(): ActualReduction[\R,L\] = r
2674    getter body(): R->R = fn x => x
2675    getter unwrap(): R->R = fn x => x
2676end
2677
2678object Comprehension[\I,O,R,L\](u: R->O, r: ActualReduction[\R,L\], singleton:I->R)
2679        extends BigOperator[\I,O,R,L\]
2680    getter reduction(): ActualReduction[\R,L\] = r
2681    getter body(): I->R = singleton
2682    getter unwrap(): R->O = u
2683end
2684
2685(** VoidReduction is usually done for effect, so we pretend that
2686    the completion performs the effects.  This rules out things
2687    distributing over void (that would change the number of effects in
2688    our program) but not void distributing over other things. **)
2689object VoidReduction extends { CommutativeMonoidReduction[\()\] }
2690    getter toString() = "VoidReduction"
2691    empty(): () = ()
2692    join(a: (), b: ()): () = ()
2693end
2694
2695(* Hack to permit any Number to work non-parametrically. *)
2696object SumReduction extends CommutativeMonoidReduction[\Number\]
2697    getter toString() = "SumReduction"
2698    empty(): Number = 0
2699    join(a: Number, b: Number): Number = a+b
2700end
2701
2702opr SUM[\T extends Number\](): Comprehension[\T,Number,Number,Number\] =
2703    Comprehension[\T,Number,Number,Number\](fn x => x, SumReduction, cast[\Number\])
2704
2705object ProdReduction extends CommutativeMonoidReduction[\Number\]
2706    getter toString() = "ProdReduction"
2707    empty(): Number = 1
2708    join(a:Number, b:Number): Number = a b
2709end
2710
2711opr PROD[\T extends Number\](): Comprehension[\T,Number,Number,Number\] =
2712    Comprehension[\T,Number,Number,Number\](fn x => x, ProdReduction, cast[\Number\])
2713
2714object MinReduction[\T extends StandardMin[\T\]\] extends CommutativeReduction[\T\]
2715    getter toString() = "MinReduction"
2716    simpleJoin(a, b) = a MIN b
2717end
2718
2719opr BIG MIN[\T extends StandardMin[\T\]\](): BigReduction[\T,AnyMaybe\] =
2720    BigReduction[\T,AnyMaybe\](MinReduction[\T\])
2721
2722object MaxReduction[\T extends StandardMax[\T\]\] extends CommutativeReduction[\T\]
2723    getter toString() = "MaxReduction"
2724    simpleJoin(a, b) = a MAX b
2725end
2726
2727opr BIG MAX[\T extends StandardMax[\T\]\](): BigReduction[\T,AnyMaybe\] =
2728    BigReduction[\T,AnyMaybe\](MaxReduction[\T\])
2729
2730opr BIG MINNUM(): BigReduction[\RR64,RR64\] =
2731    BigReduction[\RR64,RR64\](
2732        MapReduceReduction[\RR64\](fn (a:RR64,b:RR64):RR64 => a MINNUM b, 0.0/0.0))
2733
2734opr BIG MAXNUM(): BigReduction[\RR64,RR64\] =
2735    BigReduction[\RR64,RR64\](
2736        MapReduceReduction[\RR64\](fn (a:RR64,b:RR64):RR64 => a MAXNUM b, 0.0/0.0))
2737
2738(** AndReduction and OrReduction take advantage of natural zeroes for early exit. **)
2739object AndReduction
2740        extends { CommutativeMonoidReduction[\Boolean\],
2741                  ReductionWithZeroes[\Boolean,Boolean\] }
2742    getter toString() = "AndReduction"
2743    empty(): Boolean = true
2744    join(a: Boolean, b: Boolean): Boolean = a AND b
2745    isZero(a:Boolean): Boolean = NOT a
2746end
2747
2748opr BIG AND[\T\](): BigReduction[\Boolean,Boolean\] =
2749    BigReduction[\Boolean,Boolean\](AndReduction)
2750
2751object OrReduction
2752        extends { CommutativeMonoidReduction[\Boolean\],
2753                  ReductionWithZeroes[\Boolean,Boolean\] }
2754    getter toString() = "OrReduction"
2755    empty(): Boolean = false
2756    join(a: Boolean, b: Boolean): Boolean = a OR b
2757    isZero(a:Boolean): Boolean = a
2758end
2759
2760opr BIG OR[\T\]():BigReduction[\Boolean, Boolean\] =
2761    BigReduction[\Boolean,Boolean\](OrReduction)
2762
2763(** A reduction performing String concatenation **)
2764object StringReduction extends MonoidReduction[\String\]
2765    getter toString() = "StringReduction"
2766    empty(): String = ""
2767    join(a:String, b:String): String = a || b
2768end
2769
2770(** A reduction performing String concatenation with a space **)
2771object SpaceReduction extends MonoidReduction[\String\]
2772    getter toString() = "StringReduction"
2773    empty(): String = ""
2774    join(a:String, b:String): String = a ||| b
2775end
2776
2777(** A reduction performing String concatenation with newline separation **)
2778object NewlineReduction extends AssociativeReduction[\String\]
2779    getter toString() = "NewlineReduction"
2780    simpleJoin(a, b) = a // b
2781end
2782
2783(** This operator performs string concatenation, first converting
2784    its inputs (of type Any) to String if necessary. **)
2785opr BIG ||(): Comprehension[\Any,String,String,String\] =
2786    Comprehension[\Any,String,String,String\](
2787        identity[\String\],StringReduction,fn (x:Any)=> "" x)
2788
2789(** This operator performs string concatenation, first converting
2790    its inputs (of type Any) to String if necessary, and separating
2791    non-empty components by a space. **)
2792opr BIG |||(): Comprehension[\Any,String,String,String\] =
2793    Comprehension[\Any,String,String,String\](
2794        identity[\String\],SpaceReduction,fn (x:Any)=> "" x)
2795
2796(** This operator performs string concatenation with newline
2797    separation, first converting its inputs (of type Any) to String if
2798    necessary. **)
2799opr BIG //(): Comprehension[\Any,String,String,AnyMaybe\] =
2800    Comprehension[\Any,String,String,AnyMaybe\](
2801        fn x => x,NewlineReduction,fn (x:Any)=> "" x)
2802
2803(** A %MapReduceReduction% takes an associative binary function %j% on
2804    arguments of type %R%, and the identity of that function %z%, and
2805    returns the corresponding reduction. **)
2806object MapReduceReduction[\R\](j:(R,R)->R, z:R) extends MonoidReduction[\R\]
2807    getter toString()="mapReduceReduction"
2808    empty(): R = z
2809    join(a:R, b:R): R = (j)(a,b)
2810end
2811
2812(** A %MIMapReduceReduction% takes an associative binary function %j% on
2813    arguments of type %R%, and the identity of that function %z%, and
2814    returns the corresponding reduction. **)
2815object MIMapReduceReduction[\R\](j:(Any,Any)->R, z:Any) extends MonoidReduction[\Any\]
2816    getter toString():String="MIMapReduceReduction from embiggen"
2817    empty(): R = z
2818    join(a:Any, b:Any): R = (j)(a,b)
2819end
2820
2821(** %embiggen% takes a type %T% and an operation (either an operator
2822    %OP% or binary function %f% on type %T%), along with the identity
2823    %z% of the operation, and returns a function suitable as the right-hand
2824    side of the definition of the corresponding BIG operator. **)
2825(*
2826embiggen[\T,opr OP\](z:Any, g:(Reduction[\Any\],T->Any) -> Any) : T =
2827    g(MIOprReduction[\T,OP\](z), fn (x) => x)
2828*)
2829embiggen[\T\](j:(Any,Any)->T, z:T) : Comprehension[\T,T,Any,Any\] =
2830    Comprehension[\T,T,Any,Any\](fn (x) => x, MIMapReduceReduction[\T\](j,z), fn (x) => x)
2831
2832(** Helpers for maps and cross products of generators.  These can be
2833    quite a bit more sophisticated (for example, we can hoist maps
2834    outwards if we think that'd be useful), but let's get this much
2835    working first. *)
2836trait SomeMappedGenerator[\F\] extends Generator[\F\] end
2837
2838trait MappedGenerator[\E,F\] extends SomeMappedGenerator[\F\]
2839    getter g(): Generator[\E\]
2840    getter f(): E -> F
2841    getter toString(): String = g() ".map(f)"
2842    generate[\R\](r: Reduction[\R\], m: F->R): R =
2843        g().generate[\R\](r, m COMPOSE f())
2844    reduce(r: Reduction[\F\]): F =
2845        g().generate[\F\](r, f())
2846    map[\G\](f': F->G): SimpleMappedGenerator[\E,G\] =
2847        SimpleMappedGenerator[\E,G\](g(), f' COMPOSE f())
2848    seq(self) = SimpleMappedSeqGenerator[\E,F\](seq(g()),f())
2849end
2850
2851object SimpleMappedGenerator[\E,F\](g0: Generator[\E\], f0: E->F)
2852        extends MappedGenerator[\E,F\]
2853    getter g() = g0
2854    getter f() = f0
2855end
2856
2857object SimpleMappedIndexed[\E,F,I\](g0: Indexed[\E,I\], f0: E->F)
2858        extends { MappedGenerator[\E,F\], Indexed[\F,I\] }
2859    getter size(): ZZ32 = |g()|
2860    getter g() = g0
2861    getter f() = f0
2862    getter bounds(): Range[\I\] = g().bounds
2863    getter indexValuePairs(): Indexed[\(I,F),I\] =
2864        g().indexValuePairs.map[\(I,F)\](fn (i:I, e:E): F => (i,(f())(e)))
2865    getter indices(): Indexed[\I,I\] = g().indices
2866    opr |self| : ZZ32 = |g()|
2867    opr[i:I] : F = (f())(g()[i])
2868    opr[r:Range[\I\]] : Indexed[\F,I\] =
2869        SimpleMappedIndexed[\E,F,I\](g()[r],f())
2870
2871    ivmap[\R\](ff:(I,F)->R): Indexed[\R,I\] =
2872        g0().ivmap[\R\](fn (i:I, e:E) => ff(i, (f())(e)))
2873    map[\G\](f': F->G): SimpleMappedIndexed[\E,G,I\] =
2874        SimpleMappedIndexed[\E,G,I\](g(), f' COMPOSE f())
2875end
2876
2877object SimpleMappedSeqGenerator[\E,F\](g0: SequentialGenerator[\E\], f0: E->F)
2878        extends { MappedGenerator[\E,F\], SequentialGenerator[\F\] }
2879    getter g() = g0
2880    getter f() = f0
2881    getter toString() = "seq(" g0 ".map(f))"
2882    seq(self): SimpleMappedSeqGenerator[\E,F\] = self
2883end
2884
2885trait FilterGenerator[\E\] extends Generator[\E\]
2886    getter g(): Generator[\E\]
2887    getter p(): E -> Condition[\()\]
2888    getter toString(): String = g() ".filter(p)"
2889    generate[\R\](r:Reduction[\R\], m: E->R): R =
2890        g().generate[\R\](r, fn(e:E):R => if (p())(e).holds then m(e) else r.empty() end)
2891    reduce(r: Reduction[\E\]): E =
2892        g().generate[\E\](r, fn(e:E):E => if (p())(e).holds then e else r.empty() end)
2893    filter(p': E -> Condition[\()\]): SimpleFilterGenerator[\E\] =
2894        SimpleFilterGenerator[\E\](g(), p() ANDCOND p')
2895    seq(self) = SimpleSeqFilterGenerator[\E\](seq(g()),p())
2896end
2897
2898object SimpleFilterGenerator[\E\](g0:Generator[\E\], p0: E->Condition[\()\])
2899        extends FilterGenerator[\E\]
2900    getter g(): Generator[\E\]       = g0
2901    getter p(): E -> Condition[\()\]  = p0
2902end
2903
2904object SimpleSeqFilterGenerator[\E\](g0: SequentialGenerator[\E\], p0: E->Condition[\()\])
2905        extends { FilterGenerator[\E\], SequentialGenerator[\E\] }
2906    getter g(): Generator[\E\]       = g0
2907    getter p(): E -> Condition[\()\]  = p0
2908    getter toString() = "seq(" g0 ".filter(p))"
2909    seq(self): SimpleSeqFilterGenerator[\E\] = self
2910end
2911
2912trait NestedGenerator[\E,F\] extends Generator[\F\]
2913    getter g(): Generator[\E\]
2914    getter f(): E -> Generator[\F\]
2915    getter toString(): String
2916    generate[\R\](r: Reduction[\R\], m: F->R): R =
2917        g().generate[\R\](r,fn (e:E):R => (f())(e).generate[\R\](r,m))
2918    mapReduce[\R\](body: F->R, join:(R,R)->R, id:R): R =
2919        g().mapReduce[\R\](
2920            fn (e:E): R => (f())(e).mapReduce[\R\](body,join,id),
2921            join, id)
2922    reduce(r: Reduction[\F\]): F =
2923        g().generate[\F\](r,fn (e:E):F => (f())(e).reduce(r))
2924    reduce(j:(F,F)->F, z:F):F =
2925        g().mapReduce[\F\](fn (e:E): F => (f())(e).reduce(j,z), j, z)
2926    loop(body:F->()): () =
2927        g().loop(fn (e:E) => (f())(e).loop(body))
2928    map[\G\](h:F->G): Generator[\G\] =
2929        g().nest[\G\](fn (e:E): Generator[\G\] => (f())(e).map[\G\](h))
2930    nest[\G\](h:F->Generator[\G\]): Generator[\G\] =
2931        g().nest[\G\](fn (e:E):Generator[\G\] => (f())(e).nest[\G\](h))
2932end
2933
2934object SimpleNestedGenerator[\E,F\](g0: Generator[\E\], f0: E->Generator[\F\])
2935        extends { NestedGenerator[\E,F\] }
2936    getter g() = g0
2937    getter f() = f0
2938    getter toString() = g() ".nest(f)"
2939    seq(self) =
2940        typecase ff = f() of
2941            (E -> SequentialGenerator[\F\]) =>
2942                SimpleNestedSeqGenerator[\E,F\](seq(g()),ff)
2943            else =>
2944                SimpleNestedSeqGenerator[\E,F\](seq(g()),
2945                     fn (e:E): SequentialGenerator[\F\] => seq(self.f()(e)))
2946        end
2947end
2948
2949object SimpleNestedSeqGenerator[\E,F\]
2950        (g0: SequentialGenerator[\E\], f0: E->SequentialGenerator[\F\])
2951        extends { NestedGenerator[\E,F\], SequentialGenerator[\F\] }
2952    getter g() = g0
2953    getter f() = f0
2954    getter toString() = "seq(" g() ".nest(f))"
2955end
2956
2957trait PairGenerator[\E,F\] extends Generator[\(E,F)\]
2958  comprises { SimplePairGenerator[\E,F\], SimplePairSeqGenerator[\E,F\] }
2959    getter e(): Generator[\E\]
2960    getter f(): Generator[\F\]
2961    getter toString(): String
2962    getter size():ZZ32 = |self|
2963    opr |self| : ZZ32 = |e()| |f()|
2964    generate[\R\](r: Reduction[\R\], m:(E,F)->R): R =
2965        e().generate[\R\](r, fn (a: E): R =>
2966                              f().generate[\R\](r, fn (b: F): R => m(a,b)))
2967end
2968
2969object SimplePairGenerator[\E,F\](e0: Generator[\E\], f0: Generator[\F\])
2970        extends PairGenerator[\E,F\]
2971    getter e() = e0
2972    getter f() = f0
2973    getter toString()=(e0 ".cross(" f0 ")" )
2974    seq(self) = SimplePairSeqGenerator[\E,F\](seq(e0),seq(f0))
2975end
2976
2977object SimplePairSeqGenerator[\E,F\](e0: Generator[\E\], f0: Generator[\F\])
2978        extends { PairGenerator[\E,F\], SequentialGenerator[\(E,F)\] }
2979    getter e() = e0
2980    getter f() = f0
2981    getter toString()=("seq(" e ".cross(" f "))" )
2982end
2983
2984(** Helper for serializing generators naively.  This code should make
2985 *  obvious that naive seq is *VERY INEFFICIENT*.  It
2986 *  constructs a function closure whose size is proportional to
2987 *  %|g|%, and then executes that closure.  This trick is old hat
2988 *  to lambda-calculus wonks, but pretty unfamiliar to the common man.
2989 *
2990 *  Basically each element takes in the accumulated value a from the element
2991 *  to its left.  This is joined with the result of mapping on the
2992 *  current element value, and that result is returned.  Join simply
2993 *  reverse-composes the functions for its subtrees, so the output of the left
2994 *  subtree is fed to the right subtree.
2995 *
2996 *  Note that a similar trick can be used to reverse and sequentialize
2997 *  a generator (use forward function composition rather than reverse
2998 *  composition, and flipping around the join at the leaves). *)
2999object NaiveSeqGenerator[\E\](g: Generator[\E\])
3000        extends SequentialGenerator[\E\]
3001    getter size() = |g|
3002    getter toString():String = "naive seq(" g.toString ")"
3003    opr |self| : ZZ32 = |g|
3004    generate[\R\](r: Reduction[\R\], m:E->R): R = do
3005      rcompose(f:R->R, f':R->R): R->R = fn (x:R):R => f'(f(x))
3006      id(x:R):R = x
3007      mp(x:E):R->R = fn (a:R):R => r.join(a,m(x))
3008      f : R -> R = g.mapReduce[\R->R\](mp,rcompose,id)
3009      mt : R = r.empty()
3010      f mt
3011    end
3012end
3013
3014(************************************************************
3015* Ranges
3016************************************************************)
3017
3018(** Ranges in general represent uses of the # and : operators.
3019    It's mostly subtypes of Range that are interesting.
3020
3021    The partial order on ranges describes containment:
3022      a < b iff all points in a are strictly contained in b.
3023 **)
3024trait Range[\T\]
3025    extends StandardPartialOrder[\Range[\T\]\]
3026    comprises { RangeWithLower[\T\], RangeWithUpper[\T\],
3027                RangeWithExtent[\T\], PartialRange[\T\] }
3028    excludes { Number }
3029    getter isEmpty(): Boolean = (|self| ≤ 0)
3030    opr[r:Range[\T\]]: Range[\T\] = fail("Unrecognized Range " r)
3031    opr[_:OpenRange[\Any\]] : Range[\T\] = self
3032    opr[other:LowerRange[\T\]] : Range[\T\]
3033    opr[other:UpperRange[\T\]] : Range[\T\]
3034    opr[other:ExtentRange[\T\]] : Range[\T\]
3035    opr[other:CompleteRange[\T\]] : CompleteRange[\T\]
3036    opr =(self,_:Range[\T\]): Boolean = false
3037end
3038
3039trait PartialRange[\T\] extends Range[\T\]
3040    comprises { OpenRange[\T\],
3041                LowerRange[\T\], UpperRange[\T\], ExtentRange[\T\] }
3042    excludes { CompleteRange[\T\] }
3043end
3044
3045object OpenRange[\T\] extends { Range[\T\], PartialRange[\T\] }
3046    toString():String = "#"
3047    opr[_:OpenRange[\T\]] : OpenRange[\T\] = self
3048
3049    opr[other:LowerRange[\T\]] : LowerRange[\T\] = other
3050    opr[other:UpperRange[\T\]] : UpperRange[\T\] = other
3051    opr[other:ExtentRange[\T\]] : ExtentRange[\T\] = other
3052    opr[other:CompleteRange[\T\]] : CompleteRange[\T\] = other
3053    opr =(self,_:OpenRange[\T\]): Boolean = true
3054    opr CMP(self,other:Range[\T\]): TotalComparison =
3055        typecase other of
3056            OpenRange[\T\] => EqualTo
3057            else => GreaterThan
3058        end
3059end
3060
3061opr PARTIAL_LEXICO(a:Comparison, b:Comparison) =
3062    typecase a of
3063        Unordered => Unordered
3064        EqualTo => b
3065        else =>
3066            typecase b of
3067                Unordered => Unordered
3068                else => a
3069            end
3070    end
3071
3072opr PARTIAL_LEXICO(a:Comparison, b:()->Comparison) =
3073    typecase a of
3074        Unordered => Unordered
3075        EqualTo => b()
3076        else =>
3077            typecase _ = b() of
3078                Unordered => Unordered
3079                else => a
3080            end
3081    end
3082
3083(** Non-traditional partial ordering on tuples, CMP ordering elsewhere. **)
3084opr PCMP[\A,B\](t1:(A,B), t2:(A,B)): Comparison = do
3085    (a1,b1)=t1
3086    (a2,b2)=t2
3087    (a1 CMP a2) PARTIAL_LEXICO: (b1 CMP b2)
3088  end
3089
3090opr PCMP[\A,B,C\](t1:(A,B,C), t2:(A,B,C)): Comparison = do
3091    (a1,b1,c1)=t1
3092    (a2,b2,c2)=t2
3093    (a1 CMP a2) PARTIAL_LEXICO: (b1 CMP b2) PARTIAL_LEXICO (c1 CMP c2)
3094  end
3095
3096opr PCMP(a:Number, b:Number): TotalComparison = a CMP b
3097
3098(** Non-traditional subtraction of bounds, elementwise on tuples **)
3099opr SUBTR[\A,B\](t1:(A,B), t2:(A,B)): (A,B) = do
3100    (a1,b1) = t1
3101    (a2,b2) = t2
3102    (a1 SUBTR a2, b1 SUBTR b2)
3103  end
3104
3105opr SUBTR[\A,B,C\](t1:(A,B,C), t2:(A,B,C)): (A,B,C) = do
3106    (a1,b1,c1) = t1
3107    (a2,b2,c2) = t2
3108    (a1 SUBTR a2, b1 SUBTR b2, c1 SUBTR c2)
3109  end
3110
3111opr SUBTR[\T extends MultiplicativeRing[\T\]\](a:T, b:T):T = a.one + a - b
3112
3113(** join upper and lower bounds comparisons (total or partial) to
3114    yield partial containment. **)
3115
3116trait RangeWithLower[\T\] extends Range[\T\]
3117        comprises { LowerRange[\T\], CompleteRange[\T\] }
3118    getter lower():T
3119end
3120
3121rangeBoundError[\T\](r1:Range[\T\], r2: Range[\T\]): Range[\T\] =
3122    fail(r1 "[" r2 "] does not contain bound of indexing range")
3123
3124object LowerRange[\T\](lo:T) extends { RangeWithLower[\T\], PartialRange[\T\] }
3125    getter lower():T = lo
3126    toString():String = lower() "#"
3127    opr[_:OpenRange[\T\]] : LowerRange[\T\] = self
3128    opr[other:LowerRange[\T\]] : LowerRange[\T\] =
3129        if other.lower >= self.lower then
3130            other
3131        else
3132            rangeBoundError[\T\](self,other)
3133        end
3134    opr[other:ExtentRange[\T\]] : FullRange[\T,true\] = self.lower # other.extent()
3135    opr[other:UpperRange[\T\]] : FullRange[\T,true\] =
3136        if other.upper >= self.lower then
3137            self.lower : other.upper
3138        else
3139            rangeBoundError[\T\](self,other)
3140        end
3141    opr[other:CompleteRange[\T\]] : CompleteRange[\T\] =
3142        if other.lower >= self.lower then
3143            other
3144        else
3145            rangeBoundError[\T\](self,other)
3146        end
3147    opr =(self, x:LowerRange[\T\]): Boolean = self.lower = x.lower
3148    opr CMP(self, other:Range[\T\]): Comparison =
3149        typecase other of
3150            OpenRange[\T\] => LessThan
3151            LowerRange[\T\] => other.lower PCMP self.lower
3152            CompleteRange[\T\] =>
3153                typecase c = other.lower PCMP self.lower of
3154                    EqualTo => GreaterThan
3155                    LessThan => Unordered
3156                    else => c
3157                end
3158            else => Unordered
3159        end
3160end
3161
3162trait RangeWithUpper[\T\] extends Range[\T\]
3163        comprises { UpperRange[\T\], CompleteRange[\T\] }
3164    getter upper():T
3165end
3166
3167object UpperRange[\T\](up:T) extends { RangeWithUpper[\T\], PartialRange[\T\] }
3168    getter upper():T = up
3169    toString():String = ":" upper()
3170    opr[_:OpenRange[\T\]] : UpperRange[\T\] = self
3171    opr[other:LowerRange[\T\]] : FullRange[\T,true\] = other.lower:self:upper
3172    opr[other:UpperRange[\T\]] : UpperRange[\T\] =
3173        if other.upper <= self.upper then
3174            other
3175        else
3176            rangeBoundError[\T\](self,other)
3177        end
3178    opr[other:ExtentRange[\T\]] : FullRange[\T,true\] =
3179        (self.upper SUBTR other.extent) # other.extent
3180    opr[other:CompleteRange[\T\]] : CompleteRange[\T\] =
3181        if other.upper <= self.upper then
3182            other
3183        else
3184            rangeBoundError[\T\](self,other)
3185        end
3186    opr =(self,x:UpperRange[\T\]): Boolean = upper() = x.upper()
3187    opr CMP(self, other:Range[\T\]): Comparison =
3188        typecase other of
3189            OpenRange[\T\]  => LessThan
3190            UpperRange[\T\] => self.upper PCMP other.upper
3191            CompleteRange[\T\]  =>
3192                typecase c = self.upper PCMP other.upper of
3193                    EqualTo => GreaterThan
3194                    LessThan => Unordered
3195                    else => c
3196                end
3197            else => Unordered
3198        end
3199end
3200
3201trait RangeWithExtent[\T\] extends Range[\T\]
3202        comprises { ExtentRange[\T\], CompleteRange[\T\] }
3203    getter extent():T
3204    toString():String = "#" self.extent
3205end
3206
3207object ExtentRange[\T\](ex:T) extends { RangeWithExtent[\T\], PartialRange[\T\] }
3208    getter extent():T = ex
3209    opr[_:OpenRange[\T\]] : ExtentRange[\T\] = self
3210    opr[other:LowerRange[\T\]] : FullRange[\T,true\] = other.lower # self.extent
3211    opr[other:UpperRange[\T\]] : FullRange[\T,true\] =
3212        (other.upper SUBTR self.extent) # self.extent
3213    opr[other:ExtentRange[\T\]] : ExtentRange[\T\] =
3214        if other.extent <= self.extent then
3215            other
3216        else
3217            rangeBoundError[\T\](self,other)
3218        end
3219    opr[other:CompleteRange[\T\]] : CompleteRange[\T\] =
3220        if other.extent <= self.extent then
3221            other
3222        else
3223            rangeBoundError[\T\](self,other)
3224        end
3225    opr =(self,x:ExtentRange[\T\]): Boolean = self.extent = x.extent
3226    opr CMP(self, other:Range[\T\]): Comparison =
3227        typecase other of
3228            OpenRange[\T\]   => LessThan
3229            ExtentRange[\T\] => self.extent PCMP other.extent
3230            else => Unordered
3231        end
3232end
3233
3234(** The type %CompleteRange[\T\]% is really just %FullRange[\T,flag\]% for
3235    either setting of %flag%.  We need it for stuff like %typecase%
3236    and %extends% clauses since we can't bind universally quantified
3237    variables in those settings.  Since essentially all the methods are
3238    independent of the setting of flag we include them here. **)
3239trait CompleteRange[\T\]
3240        extends { RangeWithLower[\T\], RangeWithUpper[\T\],
3241                  RangeWithExtent[\T\], Indexed[\T,T\] }
3242        comprises { FullRange[\T,true\], FullRange[\T,false\] }
3243    getter indices(): FullRange[\T,true\] = bounds()
3244    getter isBounded(): Boolean
3245    getter isSized(): Boolean
3246
3247    (** The following two methods are used in bounds checking code to
3248        permit ranges that are just outside the edge of the given
3249        range.   Because they're intended for internal use we ignore
3250        the setting of flag and return a CompleteRange. **)
3251    widenUpper(): CompleteRange[\T\]
3252    widenLower(): CompleteRange[\T\]
3253
3254    opr[r:Range[\T\]]: CompleteRange[\T\] = fail("Unrecognized Range " r)
3255    opr[_:OpenRange[\T\]]: CompleteRange[\T\] = self
3256    (** Square-bracket indexing on a FullRange restricts that range to
3257         the range provided.  Restriction should behave as follows:
3258            - Restriction to an OpenRange is the identity.
3259            - An UpperRange or ExtentRange restrict the upper bound and
3260              extent of the range.
3261            - A LowerRange restricts the lower bound and extent of the range.
3262        Note that this makes it compatible with the square-bracket
3263        indexing of the Indexed trait. **)
3264    opr[r:LowerRange[\T\]]: CompleteRange[\T\] =
3265        if r.lower = self.lower then
3266            (* Important, also handles empty range case. *)
3267            self
3268        elif r.lower IN widenUpper() then
3269            r.lower:self.upper
3270        else
3271            rangeBoundError[\T\](self,r)
3272        end
3273    opr[r:UpperRange[\T\]]: CompleteRange[\T\] =
3274        if r.upper = self.upper then
3275            (* Important, also handles empty range case. *)
3276            self
3277        elif r.upper IN widenLower() then
3278            self.lower:r.upper
3279        else
3280            rangeBoundError[\T\](self,r)
3281        end
3282    opr[r:ExtentRange[\T\]]: CompleteRange[\T\] =
3283        if r.extent <= self.extent then
3284            self.lower#r.extent
3285        else
3286            fail(self "[" r "] is not sufficiently large in some dimension")
3287        end
3288    opr[r:CompleteRange[\T\]]: CompleteRange[\T\] =
3289        if r.lower < self.lower then
3290            rangeBoundError[\T\](self,r)
3291        elif r.upper > self.upper then
3292            rangeBoundError[\T\](self,r)
3293        else
3294            r
3295        end
3296
3297    toString():String =
3298        if self.isBounded then
3299            self.lower ":" self.upper
3300        else
3301            self.lower "#" self.extent
3302        end
3303
3304    opr =(self, other:CompleteRange[\T\]): Boolean =
3305        self.isBounded=other.isBounded AND self.lower=other.lower AND
3306        self.extent = other.extent
3307    opr CMP(self, other:Range[\T\]): Comparison =
3308        typecase other of
3309            CompleteRange[\T\] =>
3310                a = self.lower PCMP other.lower
3311                b = self.upper PCMP other.upper
3312                typecase _ = (a,b) of
3313                    (Unordered,Comparison) => Unordered
3314                    (Comparison,Unordered) => Unordered
3315                    (LessThan,LessThan) => Unordered
3316                    (GreaterThan,GreaterThan) => Unordered
3317                    (EqualTo,EqualTo) =>
3318                        if self.isBounded = other.isBounded then
3319                            EqualTo
3320                        else
3321                            Unordered
3322                        end
3323                    (EqualTo,Comparison) => b
3324                    (GreaterThan,Comparison) => LessThan
3325                    else (* LessThan,Comparison *) => GreaterThan
3326                end
3327            else => INVERSE (other CMP self)
3328        end
3329end
3330
3331(** A %FullRange% is either bounded (generated from a lower and upper
3332    bound, as in %l:u%) or sized (generated from a lower bound and a
3333    size, as in %l#s%).  These two kinds of range behave identically
3334    in most settings; the only time they behave differently is when we
3335    construct a strided range: both %l:u:i% and %l#s:i% generate
3336    elements %l, l+i, l+2i, ...%, but the former is bounded and
3337    generates no element larger than %i% and the latter is sized and
3338    generates exactly %s% elements.
3339
3340    Data structure bounds are always bounded. **)
3341trait FullRange[\T, bool bounded\] extends CompleteRange[\T\]
3342        comprises { ScalarRange[\T,bounded\], TupleRange[\T,bounded\] }
3343    getter isBounded(): Boolean = bounded
3344    getter isSized(): Boolean = NOT bounded
3345end
3346
3347rangeIndexFailure[\T\](r:CompleteRange[\T\],i:T): () =
3348    fail(r "[" i "] out of range.")
3349
3350(** ParRanges and SeqRanges, the simplest and most basic of all
3351    generators.  They generate |self| numbers, incrementing by 1,
3352    starting with lower() (that's the canonical ordering). *)
3353trait ScalarRange[\N extends Integral[\N\], bool bounded\]
3354        extends { FullRange[\N, bounded\] }
3355        comprises { ParRange[\N, bounded\], SeqRange[\N, bounded\] }
3356    getter bounds():FullRange[\N,true\] = ParRange[\N,true\](0,extent())
3357    getter upper():N = lower() + extent() - 1
3358    getter size():ZZ32 = |self|
3359    widenUpper(): ScalarRange[\N,false\] = lower()#(extent()+1)
3360    widenLower(): ScalarRange[\N,false\] = (lower()-1)#(extent()+1)
3361    opr |self| : ZZ32 = narrow(0 MAX extent())
3362    opr[i:N]: N =
3363        if 0 <= i < extent() then
3364            i + lower()
3365        else
3366            rangeIndexFailure[\N\](self,i)
3367        end
3368    opr IN(a:N, self): Boolean = do
3369        t = a - lower()
3370        0 <= t < extent()
3371      end
3372end
3373
3374value object ParRange[\N extends Integral[\N\], bool bounded\](lo:N, ex:N)
3375        extends ScalarRange[\N,bounded\]
3376    getter extent() = ex
3377    getter lower() = lo
3378    getter indexValuePairs() =
3379        ParRange[\N,bounded\](0,ex).map[\(N,N)\](fn (n:N):(N,N) => (n,n+lo))
3380
3381    seq(self) = SeqRange[\N,bounded\](lo,ex)
3382    generate[\R\](r: Reduction[\R\], m: N->R): R =
3383        if ex < 1 then
3384            r.empty()
3385        else
3386            gen(l,s) = if s>=2 then
3387                           (s1,s2) = partition(s)
3388                           r.join(gen(l,s1),gen(l+s1,s2))
3389                       else
3390                           m(l)
3391                       end
3392            gen(lo,ex)
3393        end
3394    mapReduce[\R\](m: N->R, j:(R,R)->R, z:R): R =
3395        if ex < 1 then
3396            z
3397        else
3398            gen(l,s) = if s>=2 then
3399                           (s1,s2) = partition(s)
3400                           j(gen(l,s1),gen(l+s1,s2))
3401                       else
3402                           m(l)
3403                       end
3404            gen(lo,ex)
3405        end
3406    reduce(j:(N,N)->N, z:N):N =
3407        if ex < 1 then
3408            z
3409        else
3410            gen(l,s) = if s>=2 then
3411                           (s1,s2) = partition(s)
3412                           j(gen(l,s1),gen(l+s1,s2))
3413                       else
3414                           l
3415                       end
3416            gen(lo,ex)
3417        end
3418    reduce(r: Reduction[\N\]):N =
3419        if ex < 1 then
3420            r.empty()
3421        else
3422            gen(l,s) = if s>=2 then
3423                           (s1,s2) = partition(s)
3424                           r.join(gen(l,s1),gen(l+s1,s2))
3425                       else
3426                           l
3427                       end
3428            gen(lo,ex)
3429        end
3430    loop(f:N->()): () =
3431        if ex < 1 then
3432            ()
3433        else
3434            gen(l,s) = if s>=2 then
3435                           (s1,s2) = partition(s)
3436                           (gen(l,s1),gen(l+s1,s2))
3437                           ()
3438                       else
3439                           f(l)
3440                       end
3441            gen(lo,ex)
3442        end
3443end
3444value object SeqRange[\N extends Integral[\N\], bool bounded\](lo:N, ex:N)
3445        extends { ScalarRange[\N,bounded\], SequentialGenerator[\N\] }
3446    getter extent() = ex
3447    getter lower() = lo
3448    getter toString() =
3449        ("seq(" lo (if bounded then ":" upper() else "#" ex ")"))
3450    getter indexValuePairs() =
3451        SeqRange[\N,bounded\](0,ex).map[\(N,N)\](fn (n:N):(N,N) => (n,n+lo))
3452    generate[\R\](r: Reduction[\R\], m: N->R): R = do
3453        h = lo + ex
3454        l : N := lo
3455        acc : R = r.empty()
3456        (* DON'T DEFINE THIS USING RECURSION!!! *)
3457        while l < h do
3458            b = m(l)
3459            acc := r.join(acc, b)
3460            l += 1
3461        end
3462        acc
3463      end
3464    loop(f: N->()): () = do
3465        h = lo + ex
3466        l : N := lo
3467        (* DON'T DEFINE THIS USING RECURSION!!! *)
3468        while l < h do
3469            f(l)
3470            l += 1
3471        end
3472      end
3473end
3474
3475trait TupleRange[\T, bool bounded\] extends FullRange[\T,bounded\]
3476end
3477
3478object Tuple2Range[\N extends Integral[\N\], M extends Integral[\M\], bool bounded\]
3479                  (l1:N,l2:M,x1:N,x2:M)
3480        extends { TupleRange[\(N,M),bounded\], DelegatedIndexed[\(N,M),(N,M)\] }
3481    getter bounds():Tuple2Range[\N,M,true\] = Tuple2Range[\N,M,true\](0,0,x1,x2)
3482    getter extent():(N,M) = (x1,x2)
3483    getter lower():(N,M) = (l1,l2)
3484    getter upper():(N,M) = (l1+x1-1, l2+x2-1)
3485    getter size():(N,M) = |self|
3486    getter generator():Generator[\(N,M)\] =
3487        ParRange[\N,bounded\](l1,x1).cross[\M\](ParRange[\M,bounded\](l2,x2))
3488    getter toString(): String =
3489        ("(" l1 "," l2
3490         (if bounded then
3491             (u1,u2) = upper()
3492             "):(" u1 "," u2 ")"
3493         else
3494             ")#(" x1 "," x2 ")"
3495         end))
3496    getter indexValuePairs() =
3497        bounds().map[\((N,M),(N,M))\](
3498            fn (n:N,m:M):((N,M),(N,M)) => ((n,m),(n+l1,m+l2)))
3499    widenUpper(): Tuple2Range[\N,M,true\] = Tuple2Range[\N,M,true\](l1,l2,x1+1,x2+1)
3500    widenLower(): Tuple2Range[\N,M,true\] = Tuple2Range[\N,M,true\](l1-1,l2-1,x1+1,x2+1)
3501    opr |self| : ZZ32 = narrow((0 MAX x1) (0 MAX x2))
3502    opr[i:(N,M)]: (N,M) = do
3503        (i1,i2) = i
3504        if 0 <= i1 < x1 AND 0 <= i2 < x2 then
3505            (i1+l1,i2+l2)
3506        else
3507            rangeIndexFailure[\(N,M)\](self,i)
3508        end
3509      end
3510    opr IN(t:(N,M), self): Boolean = do
3511        (v1,v2) = t
3512        0 <= v1-l1 < x1 AND 0 <= v2-l2 < x2
3513      end
3514    opr =(self,r:Tuple2Range[\N,M,bounded\]): Boolean =
3515        l1=r.l1 AND l2=r.l2 AND x1=r.x1 AND x2=r.x2
3516end
3517
3518object Tuple3Range[\N1 extends Integral[\N1\], N2 extends Integral[\N2\], N3 extends Integral[\N3\],
3519                   bool bounded\]
3520                  (l1:N1,l2:N2,l3:N3,x1:N1,x2:N2,x3:N3)
3521        extends { TupleRange[\(N1,N2,N3),bounded\],
3522                  DelegatedIndexed[\(N1,N2,N3),(N1,N2,N3)\] }
3523    getter bounds():Tuple3Range[\N1,N2,N3,true\] =
3524        Tuple3Range[\N1,N2,N3,true\]((0,0,0),(x1,x2,x3))
3525    getter extent():(N1,N2,N3) = (x1,x2,x3)
3526    getter lower():(N1,N2,N3) = (l1,l2,l3)
3527    getter upper():(N1,N2,N3) = (l1+x1-1,l2+x2-1,l3+x3-1)
3528    getter size():(N1,N2,N3) = |self|
3529    getter generator():Generator[\(N1,N2,N3)\] =
3530        ParRange[\N1,bounded\](l1,x1).cross[\N2\](ParRange[\N2,bounded\](l2,x2)).cross[\N3\](
3531            ParRange[\N3,bounded\](l3,x3)).map[\(N1,N2,N3)\](
3532                fn (t:(N1,N2),n3:N3):(N1,N2,N3) => do (n1,n2)=t; (n1,n2,n3) end)
3533    getter toString(): String =
3534        ("(" l1 "," l2 "," l3
3535         (if bounded then
3536             (u1,u2,u3) = upper()
3537             "):(" u1 "," u2 "," u3 ")"
3538         else
3539             ")#(" x1 "," x2 "," x3 ")"
3540         end))
3541    getter indexValuePairs() =
3542        (0#x1).cross(0#x2).cross(0#x3).map[\((N1,N2,N3),(N1,N2,N3))\](
3543            fn (t:(N1,N2),n3:N3):((N1,N2,N3),(N1,N2,N3)) =>
3544                do (n1,n2)=t; ((n1,n2,n3),(n1+l1,n2+l2,n3+l3)) end)
3545    widenUpper(): Tuple3Range[\N1,N2,N3,true\] =
3546        Tuple3Range[\N1,N2,N3,true\](l1,l2,l3,x1+1,x2+1,x3+1)
3547    widenLower(): Tuple3Range[\N1,N2,N3,true\] =
3548        Tuple3Range[\N1,N2,N3,true\](l1-1,l2-1,l3-1,x1+1,x2+1,x3+1)
3549    opr |self| : (N1,N2,N3) = narrow((0 MAX x1) (0 MAX x2) (0 MAX x3))
3550    opr[i:(N1,N2,N3)]: (N1,N2,N3) = do
3551        (i1,i2,i3) = i
3552        if 0 <= i1 < x1 AND 0 <= i2 < x2 AND 0 <= i3 < x3 then
3553            (i1+l1,i2+l2,i3+l3)
3554        else
3555            rangeIndexFailure[\(N1,N2,N3)\](self,i)
3556        end
3557      end
3558    opr IN(t:(N1,N2,N3), self): Boolean = do
3559        (v1,v2,v3) = t
3560        0 <= v1-l1 < x1 AND 0 <= v2-l2 < x2 AND 0 <= v3-l3 < x3
3561      end
3562    opr =(self,r:Tuple3Range[\N1,N2,N3,bounded\]): Boolean =
3563        l1=r.l1 AND l2=r.l2 AND x1=r.x1 AND x2=r.x2 AND l3=r.l3 AND x3=r.x3
3564end
3565
3566(** Helpers for # to get the type instantiation "right".  We pass in bogus ZZ32's to
3567    ensure that the result type is at least ZZ32. **)
3568sizedRange[\I extends AnyIntegral\](_:I,lo:I,ex:I): ParRange[\I,false\] = ParRange[\I,false\](lo,ex)
3569sized2Range[\I extends AnyIntegral, J extends AnyIntegral\]
3570           (_:I,_:J,l1:I,l2:J,ex1:I,ex2:J): Tuple2Range[\I,J,false\] =
3571    Tuple2Range[\I,J,false\](l1,l2,ex1,ex2)
3572sized3Range[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\]
3573     (_:I,_:J,_:K,l1:I,l2:J,l3:K,ex1:I,ex2:J,ex3:K): Tuple3Range[\I,J,K,false\] =
3574    Tuple3Range[\I,J,K,false\](l1,l2,l3,ex1,ex2,ex3)
3575
3576(** The # and : operators serve as factories for parallel ranges. **)
3577opr #[\I extends AnyIntegral\](lo:I, ex:I): ParRange[\I,false\] = sizedRange(0 asif ZZ32,lo,ex)
3578(*
3579opr #(lo:IntLiteral, ex:IntLiteral): ParRange[\ZZ32\] = ParRange[\ZZ32,false\](lo,ex)
3580*)
3581opr #[\I extends AnyIntegral, J extends AnyIntegral\]
3582     (lo:(I,J), ex:(I,J)): Tuple2Range[\I,J,false\] =
3583    do (l1,l2)=lo; (x1,x2)=ex; sized2Range(0 asif ZZ32,0 asif ZZ32,l1,l2,x1,x2) end
3584opr #[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\]
3585     (lo:(I,J,K), ex:(I,J,K)): Tuple3Range[\I,J,K,false\] =
3586    do (l1,l2,l3)=lo; (x1,x2,x3)=ex
3587       sized3Range(0 asif ZZ32,0 asif ZZ32,0 asif ZZ32,l1,l2,l3,x1,x2,x3)
3588    end
3589
3590(** Helpers for : to get the type instantiation "right".  We pass in bogus ZZ32's to
3591    ensure that the result type is at least ZZ32.  **)
3592boundedRange[\I extends AnyIntegral\](_:I,lo:I,ex:I): ParRange[\I,true\] = ParRange[\I,true\](lo,ex)
3593bounded2Range[\I extends AnyIntegral, J extends AnyIntegral\]
3594           (_:I,_:J,l1:I,l2:J,ex1:I,ex2:J): Tuple2Range[\I,J,true\] =
3595    Tuple2Range[\I,J,true\](l1,l2,ex1,ex2)
3596bounded3Range[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\]
3597     (_:I,_:J,_:K,l1:I,l2:J,l3:K,ex1:I,ex2:J,ex3:K): Tuple3Range[\I,J,K,true\] =
3598    Tuple3Range[\I,J,K,true\](l1,l2,l3,ex1,ex2,ex3)
3599
3600opr :[\I extends AnyIntegral\](lo:I, hi:I): ParRange[\I,true\] =
3601        boundedRange(0 asif ZZ32,lo,hi-lo+1)
3602(*
3603opr :(lo:IntLiteral, hi:IntLiteral): ParRange[\ZZ32,true\] =
3604        ParRange[\ZZ32,true\](lo,hi-lo+1)
3605*)
3606opr :[\I extends AnyIntegral, J extends AnyIntegral\]
3607     (lo:(I,J), hi:(I,J)): Tuple2Range[\I,J,true\] =
3608    do (l1,l2)=lo; (h1,h2)=hi; bounded2Range(0 asif ZZ32,0 asif ZZ32,l1,l2,h1-l1+1,h2-l2+1) end
3609opr :[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\]
3610     (lo:(I,J,K), hi:(I,J,K)): Tuple3Range[\I,J,K,true\] = do
3611    (l1,l2,l3)=lo; (h1,h2,h3)=hi
3612    bounded3Range(0 asif ZZ32,0 asif ZZ32,0 asif ZZ32,l1,l2,l3,h1-l1+1,h2-l2+1,h3-l3+1)
3613  end
3614
3615lowerRange[\I extends AnyIntegral\](_:I,x:I):LowerRange[\I\] = LowerRange[\I\](x)
3616lower2Range[\I extends AnyIntegral, J extends AnyIntegral\](_:I,_:J,x:I,y:J):
3617    LowerRange[\(I,J)\] = LowerRange[\(I,J)\](x,y)
3618lower3Range[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\]
3619           (_:I,_:J,_:K,x:I,y:J,z:K): LowerRange[\(I,J,K)\] =
3620    LowerRange[\(I,J,K)\](x,y,z)
3621
3622extentRange[\I extends AnyIntegral\](_:I,x:I):ExtentRange[\I\] = ExtentRange[\I\](x)
3623extent2Range[\I extends AnyIntegral, J extends AnyIntegral\](_:I,_:J,x:I,y:J):
3624    ExtentRange[\(I,J)\] = ExtentRange[\(I,J)\](x,y)
3625extent3Range[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\]
3626            (_:I,_:J,_:K,x:I,y:J,z:K): ExtentRange[\(I,J,K)\] =
3627    ExtentRange[\(I,J,K)\](x,y,z)
3628
3629upperRange[\I extends AnyIntegral\](_:I,x:I):UpperRange[\I\] = UpperRange[\I\](x)
3630upper2Range[\I extends AnyIntegral, J extends AnyIntegral\](_:I,_:J,x:I,y:J):
3631    UpperRange[\(I,J)\] = UpperRange[\(I,J)\](x,y)
3632upper3Range[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\]
3633           (_:I,_:J,_:K,x:I,y:J,z:K): UpperRange[\(I,J,K)\] =
3634    UpperRange[\(I,J,K)\](x,y,z)
3635
3636(** Factories for incomplete ranges **)
3637opr (x:I)#[\I extends AnyIntegral\] : LowerRange[\I\] = lowerRange(0 asif ZZ32, x)
3638opr (x:I,y:J)#[\I extends AnyIntegral, J extends AnyIntegral\] : LowerRange[\(I,J)\] =
3639    lower2Range(0 asif ZZ32,0 asif ZZ32, x,y)
3640opr (x:I,y:J,z:K)#[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\] :
3641         LowerRange[\(I,J,K)\] = lower3Range(0 asif ZZ32,0 asif ZZ32,0 asif ZZ32, x,y,z)
3642opr (x:I):[\I\] : LowerRange[\I\] = x#
3643opr #[\I extends AnyIntegral\](x:I) : ExtentRange[\I\] = extentRange(0 asif ZZ32, x)
3644opr #[\I extends AnyIntegral, J extends AnyIntegral\](xy:(I,J)) : ExtentRange[\(I,J)\] =
3645    do (x,y) = xy; extent2Range(0 asif ZZ32,0 asif ZZ32, x,y) end
3646opr #[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\](xyz:(I,J,K)) :
3647         ExtentRange[\(I,J,K)\] =
3648    do (x,y,z) = xyz; extent3Range(0 asif ZZ32,0 asif ZZ32,0 asif ZZ32, x,y,z) end
3649opr :[\I extends AnyIntegral\](x:I) : UpperRange[\I\] = upperRange(0 asif ZZ32, x)
3650opr :[\I extends AnyIntegral, J extends AnyIntegral\](xy:(I,J)) : UpperRange[\(I,J)\] =
3651    do (x,y) = xy; upper2Range(0 asif ZZ32,0 asif ZZ32, x,y) end
3652opr :[\I extends AnyIntegral, J extends AnyIntegral, K extends AnyIntegral\](xyz:(I,J,K)) :
3653         UpperRange[\(I,J,K)\] =
3654    do (x,y,z) = xyz; upper3Range(0 asif ZZ32,0 asif ZZ32,0 asif ZZ32, x,y,z) end
3655(*
3656opr (x:I)#[\I\] : LowerRange[\I\] = LowerRange[\I\](x)
3657opr (x:I):[\I\] : LowerRange[\I\] = LowerRange[\I\](x)
3658opr #[\I\](x:I) : ExtentRange[\I\] = ExtentRange[\I\](x)
3659opr :[\I\](x:I) : UpperRange[\I\] = UpperRange[\I\](x)
3660*)
3661opr #() : OpenRange[\Any\] = OpenRange[\Any\]
3662opr :() : OpenRange[\Any\] = OpenRange[\Any\]
3663
3664trait String extends { StandardTotalOrder[\String\], ZeroIndexed[\Char\], DelegatedIndexed[\Char,ZZ32\] }
3665             excludes {Number, Char, AnyMultiplicativeRing, AnyList}
3666    getter size() : ZZ32
3667    getter toString() : String = self
3668    getter indices() : FullRange[\ZZ32,true\] = self.bounds
3669    (* This is the "dumb" generator.  It always works, but can be "Big O" inefficient, e.g., for
3670       CatString trees.  Sub-traits should override it with equivalent but more efficeint code. *)
3671    getter generator() : Generator[\Char\] =
3672        indices().map[\Char\](fn (i:ZZ32):Char => self[i])       
3673    getter depth() = 0
3674   
3675    showStructure() = showStructure(0)
3676     
3677    opr |self| : ZZ32 = self.size
3678    opr CASE_INSENSITIVE_CMP(self, other:String): TotalComparison
3679    (** As a convenience, we permit LowerRange indexing to go 1 past the bounds
3680        of the String, returning the empty String, in order to permit some convenient
3681        String-trimming idioms. **)
3682    opr [i:ZZ32]: Char =
3683        if 0 <= i < |self|
3684        then self.get(i)
3685        else
3686            (* println "Index " i " not in bounds " self.bounds *)
3687            throw IndexOutOfBounds(0,(|self|)-1,i)
3688        end
3689
3690    opr[r0:Range[\ZZ32\]] : String =  do
3691        r1 = self.bounds[r0]     (* This will complete r0 if it is incomplete, and throw a bounds exception when necessary *)
3692        self.uncheckedSubstring(r1)
3693      end
3694
3695    (** The operator %||% with at least one String argument converts to String and
3696        appends **)
3697    opr ||(self, b:String):String
3698    opr ||(self, b:Number):String = self || b.toString
3699    opr ||(self, c:Char):String
3700    opr ||(self, b:()):String = self || "()"
3701    opr ||(self, b:(Any,Any)):String = do (i,j) = b; self || "(" || i || "," j || ")" end
3702    opr ||(self, b:(Any,Any,Any)):String =
3703        do (i,j,k) = b; self || "(" || i || "," j || "," k || ")" end
3704    opr ||(self, b:(Any,Any,Any,Any)):String =
3705        do (i,j,k,l) = b; self || "(" || i || "," j || "," k || "," l || ")" end
3706    opr ||(self, b:(Any,Any,Any,Any,Any)):String =
3707        do (i,j,k,l,m) = b; self || "(" || i || "," j || "," k || "," l || "," m || ")" end
3708    opr ||(self, b:(Any,Any,Any,Any,Any,Any)):String =
3709        do (i,j,k,l,m,n) = b; self || "(" || i || "," j || "," k || "," l || "," m || "," n || ")" end
3710    opr ||(a:Any, self):String = a.toString || self
3711    opr ||(self, b:Any):String = self || b.toString
3712
3713    (** The operator %|||% with at least one String argument converts to string,
3714        then appends with a whitespace separator unless one of the two arguments is
3715        empty.  If there is an empty argument, the other argument is returned. **)
3716    opr |||(self, b:String): String =
3717        if |self| = 0 then b
3718        elif |b| = 0 then self
3719        else self || " " || b
3720        end
3721    opr |||(self, b:Any): String = self ||| (""||b)
3722    opr |||(a:Any, self): String = (""||a) ||| self
3723
3724    (** Right now for backward compatibility juxtaposition works like %||% **)
3725    opr juxtaposition(a:Any, self):String = (""||a) || self
3726    opr juxtaposition(self, b:String):String = self || b
3727    opr juxtaposition(self, b:Any):String = self || b
3728
3729    (** opr %//% appends with a single newline separator.  Note that as
3730        with %||% and %|||% at least one argument must be a String.
3731        There is a postfix version in FortressLibrary that performs
3732        string conversion, but the prefix version must occur before a
3733        String. **)
3734    opr //(self) : String = "\n"||self
3735    opr //(self, a:String): String = self||"\n"||a
3736    opr //(self, a:Any): String    = self||"\n"||a
3737    opr //(a:Any, self): String    = a||"\n"||self
3738
3739    (** opr %///% appends with a double newline separator.  Note that, as
3740        with %||% and %|||%, at least one argument must be a String.
3741        There is a postfix version in FortressLibrary that performs
3742        string conversion, but the prefix version must occur before a
3743        String. **)
3744    opr ///(self) : String = "\n\n"||self
3745    opr ///(self, a:String): String = self||"\n\n"||a
3746    opr ///(self, a:Any): String    = self||"\n\n"||a
3747    opr ///(a:Any, self): String    = a||"\n\n"||self
3748
3749  end
3750
3751(***********************************************************
3752* Numeric primitives
3753************************************************************)
3754
3755nanoTime():ZZ64 = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Long$NanoTime")
3756printTaskTrace():() = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$PrintTaskTrace")
3757
3758__globalTimeInformation: ZZ64 := 0
3759recordTime(dummy: Any): () = do __globalTimeInformation := nanoTime() end
3760printTime(dummy: Any): () = do
3761    r = nanoTime()
3762    e = r - __globalTimeInformation
3763    __globalTimeInformation := r
3764    secs: ZZ64 = (e+500000) DIV 1000000
3765    println("Operation took " secs "ms")
3766  end
3767
3768fromRawBits(a:ZZ64):RR64 = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$FromRawBits")
3769
3770random(a:Number):RR64 = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Float$Random")
3771
3772char(a:ZZ32):Char = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.Char$Chr")
3773
3774
3775print(a:Any):() = print("" a)
3776println(a:Any):() = println("" a)
3777(* 0-argument versions handle passing of () to single-argument versions. *)
3778print():() = print("")
3779println():() = println("")
3780print(a: JavaString): () =
3781        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$Print")
3782println(a: JavaString): () =
3783        builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$Println")
3784
3785
3786forDigit(x:ZZ32, radix:ZZ32): Maybe[\Char\] =
3787    if (radix<2 OR radix>16 OR x<0 OR x>=radix) then
3788        Nothing[\Char\]
3789    elif (radix <= 12) then
3790        forDigit(x, "0123456789xe")
3791    else
3792        forDigit(x, "0123456789abcdef")
3793    end
3794
3795forDigit(x:ZZ32, radixString:String): Maybe[\Char\] =
3796    if( 0 <= x < |radixString| ) then
3797        Just[\Char\](radixString[x])
3798    else
3799        Nothing[\Char\]
3800    end
3801
3802
3803(** Convert string to arbitrary integral type.  String may contain
3804    leading - or +.  Valid radixes are 2,8,10,12, and 16.  No spaces
3805    may occur in the string, and it must have at least one digit.
3806
3807    Right now we're oblivious to overflow!  This ought to be fixed.
3808
3809    This ought to support arbitrary integer types, but right now
3810    there's no clean way to convert all the arithmetic to use a
3811    provided type without having an instance of that type in hand.
3812    Unsigned types in particular are a bit sticky.
3813 **)
3814strToInt(s: String, radix: ZZ32): ZZ32 = do
3815    (i0, neg) =
3816        if s[0] = '-' then (1, true)
3817        elif s[0] = '+' then (1, false)
3818        else (0,false) end
3819    n = |s| - 1
3820    r = SUM[ i <- i0:n] if d <- digit(s[i], radix) then
3821                          d radix^(n-i)
3822                      else
3823                          fail("strToInt(" s.toString "," radix "): non-digit " s[i].toString)
3824                      end
3825    if neg then -r else r end
3826  end
3827
3828(** Radix-10 digit conversion.  All caveats of the flexible-radix conversion above apply. *)
3829strToInt(s: String): ZZ32 = strToInt(s,10)
3830
3831match(regex:String,some:String):Boolean = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$Match")
3832
3833(** postfix %//% appends a single newline separator.  The postfix version
3834    performs implicit conversion to String, which is why it's a
3835    standalone top-level function.  Infix and prefix versions are defined by String. **)
3836opr (x:Any)// : String = x||"\n"
3837
3838(** postfix %///% appends a double newline separator.  The postfix version
3839    performs implicit conversion to String, which is why it's a
3840    standalone top-level function.  Infix and prefix versions are defined by String. **)
3841opr (x:Any)/// : String = x||"\n\n"
3842
3843(* A way to get environment information from inside of fortress *)
3844getEnvironment(name:String, defaultValue:String):String = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$GetEnvironment")
3845
3846(* These are useful temporary hacks for debugging multi-threaded programs *)
3847printThreadInfo(a:String):() = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$PrintThreadInfo")
3848printThreadInfo(a:Number):() = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$PrintThreadInfo")
3849throwError(a:String):() = builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$ThrowError")
3850
3851opr SEQV(a:Any, b:Any):Boolean =
3852    builtinPrimitive("com.sun.fortress.interpreter.glue.prim.AnyPrim$SEquiv")
3853
3854opr  XOR(a:Boolean, b:Boolean):Boolean = if a then NOT b else b end
3855opr  OR(a:Boolean, b:Boolean):Boolean = if a then true else b end
3856opr AND(a:Boolean, b:Boolean):Boolean = if a then b else false end
3857opr  OR(a:Boolean, b:()->Boolean):Boolean = if a then true else b() end
3858opr AND(a:Boolean, b:()->Boolean):Boolean = if a then b() else false end
3859opr NOT(a:Boolean):Boolean = if a then false else true end
3860opr ->(a: Boolean, b:Boolean):Boolean = if a then b else true end
3861opr ->(a: Boolean, b:()->Boolean):Boolean = if a then b() else true end
3862opr <->(a: Boolean, b:Boolean):Boolean = a=b
3863
3864true : Boolean = () SEQV ()
3865false : Boolean = true SEQV ()
3866
3867opr +[\T extends Number\](x:T):T = x
3868
3869(* Shouldn't these operators have to extend something? A,B,C? *)
3870
3871opr =[\A,B\](t1:(A,B), t2:(A,B)): Boolean = do
3872    (a1,b1) = t1
3873    (a2,b2) = t2
3874    (a1=a2) AND: (b1=b2)
3875  end
3876
3877opr <[\A,B\](t1:(A,B), t2:(A,B)): Boolean = do
3878    (a1,b1) = t1
3879    (a2,b2) = t2
3880    typecase _ = a1 CMP a2 of
3881        LessThan => true
3882        EqualTo => b1 < b2
3883        GreaterThan => false
3884    end
3885  end
3886
3887opr <=[\A,B\](t1:(A,B), t2:(A,B)): Boolean = do
3888    (a1,b1) = t1
3889    (a2,b2) = t2
3890    typecase _ = a1 CMP a2 of
3891        LessThan => true
3892        EqualTo => b1 <= b2
3893        GreaterThan => false
3894    end
3895  end
3896
3897opr >[\A,B\](t1:(A,B), t2:(A,B)): Boolean = do
3898    (a1,b1) = t1
3899    (a2,b2) = t2
3900    typecase _ = a1 CMP a2 of
3901        LessThan => false
3902        EqualTo => b1 > b2
3903        GreaterThan => true
3904    end
3905  end
3906
3907opr >=[\A,B\](t1:(A,B), t2:(A,B)): Boolean = do
3908    (a1,b1) = t1
3909    (a2,b2) = t2
3910    typecase _ = a1 CMP a2 of
3911        LessThan => false
3912        EqualTo => b1 >= b2
3913        GreaterThan => true
3914    end
3915  end
3916
3917opr CMP[\A,B\](t1:(A,B), t2:(A,B)): Comparison = do
3918    (a1,b1) = t1
3919    (a2,b2) = t2
3920    (a1 CMP a2) LEXICO: (b1 CMP b2)
3921  end
3922
3923opr =[\A,B,C\](t1:(A,B,C), t2:(A,B,C)): Boolean = do
3924    (a1,b1,c1) = t1
3925    (a2,b2,c2) = t2
3926    (a1=a2) AND: (b1=b2) AND: (c1=c2)
3927  end
3928
3929opr <[\A,B,C\](t1:(A,B,C), t2:(A,B,C)): Boolean = do
3930    (a1,b1,c1) = t1
3931    (a2,b2,c2) = t2
3932    typecase _ = (a1 CMP a2) LEXICO: (b1 CMP b2) of
3933        LessThan => true
3934        EqualTo => c1 < c2
3935        GreaterThan => false
3936    end
3937  end
3938
3939opr <=[\A,B,C\](t1:(A,B,C), t2:(A,B,C)): Boolean = do
3940    (a1,b1,c1) = t1
3941    (a2,b2,c2) = t2
3942    typecase _ = (a1 CMP a2) LEXICO: (b1 CMP b2) of
3943        LessThan => true
3944        EqualTo => c1 <= c2
3945        GreaterThan => false
3946    end
3947  end
3948
3949opr >[\A,B,C\](t1:(A,B,C), t2:(A,B,C)): Boolean = do
3950    (a1,b1,c1) = t1
3951    (a2,b2,c2) = t2
3952    typecase _ = (a1 CMP a2) LEXICO: (b1 CMP b2) of
3953        LessThan => false
3954        EqualTo => c1 > c2
3955        GreaterThan => true
3956    end
3957  end
3958
3959opr >=[\A,B,C\](t1:(A,B,C), t2:(A,B,C)): Boolean = do
3960    (a1,b1,c1) = t1
3961    (a2,b2,c2) = t2
3962    typecase _ = (a1 CMP a2) LEXICO: (b1 CMP b2) of
3963        LessThan => false
3964        EqualTo => c1 >= c2
3965        GreaterThan => true
3966    end
3967  end
3968
3969opr CMP[\A,B,C\](t1:(A,B,C), t2:(A,B,C)): Comparison = do
3970    (a1,b1,c1) = t1
3971    (a2,b2,c2) = t2
3972    (a1 CMP a2) LEXICO: (b1 CMP b2) LEXICO: (c1 CMP c2)
3973  end
3974
3975object Box[\T\](var val : T)
3976end
3977
3978end
Note: See TracBrowser for help on using the browser.