Changeset 2739
- Timestamp:
- 08/25/08 07:23:17 (15 months ago)
- Location:
- trunk
- Files:
-
- 7 modified
-
Library/CordedString.fsi (modified) (1 diff)
-
Library/CordedString.fss (modified) (7 diffs)
-
Library/FortressLibrary.fsi (modified) (6 diffs)
-
Library/FortressLibrary.fss (modified) (11 diffs)
-
Library/JavaString.fss (modified) (4 diffs)
-
ProjectFortress/not_passing_yet/CordedStringTests.fss (modified) (5 diffs)
-
ProjectFortress/tests/RangeTest.fss (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Library/CordedString.fsi
r2708 r2739 24 24 end 25 25 26 trait SubString extends String 27 comprises {...} 28 end 29 26 30 margin(prefix: String, indent: ZZ32) 27 31 -
trunk/Library/CordedString.fss
r2708 r2739 17 17 18 18 component CordedString 19 import List.{...} 19 20 export CordedString 20 21 21 22 (* I believe that these should eventually go with the range code. *) 22 23 23 (*Intersection of two ranges *) 24 opr ∩ (r0: Range[\ZZ32\], r1: Range[\ZZ32\]) = (r0.lower MAX r1.lower) : (r0.upper MIN r1.upper) 24 opr ∩ (r0: Range⟦ZZ32⟧, r1: Range⟦ZZ32⟧) = (r0.lower MAX r1.lower) : (r0.upper MIN r1.upper) 25 26 test rangeIntersect() = do 27 assert((0:5) ∩ (0:3), 0:3) 28 assert((0:5) ∩ (3:7), 3:5) 29 assert((0:5) ∩ (7:10), 7:5) 30 assert((5:3).size, 0, "The size of 5:3 is not zero!") 31 assert((9:8).size, 0, "The size of 9:8 is not zero!") 32 assert( (5:3).isEmpty, "5:3 is not empty!") 33 assert( (9:8).isEmpty, "9:8 is not empty!") 34 assert( ((0:5) ∩ (7:10)).isEmpty, "0:5 has a non-empty intersection with 7:10 !") 35 assert( (7:9)≪7, (0#3), "7:9≪7 isn't 0#3" ) 36 end 37 25 38 (* Shift a range left by the specified amount. *) 26 opr ↙(r: Range[\ZZ32\], leftShift: ZZ32) = (r.lower - leftShift)#r.extent 27 39 opr ≪(r: Range⟦ZZ32⟧, leftShift: ZZ32) = (r.lower - leftShift)#r.extent 40 (* Shift a range right by the specified amount. *) 41 opr ≫(r: Range⟦ZZ32⟧, rightShift: ZZ32) = (r.lower + rightShift)#r.extent 42 43 test testShiftLeft(): () = do 44 assert( (10:12) ≪ 9, 1:3) 45 end 46 47 test testShiftRight(): () = do 48 assert( (2:3) ≫ 5, 7:8) 49 end 50 51 test testRangeContainment = do 52 assert( (2:3) ≤ (2:3), "(2:3) not less than or equal to (2:3)") 53 (* println "(2#2) CMP (2:3) = " ((2#2) CMP (2:3)) *) 54 assert( (2#2) ≤ (2:3), "(2#2) not less than or equal to (2:3)") 55 end 56 (* 57 ==== Shared Traits ==== 58 *) 59 60 trait Concatenable extends String 61 opr || (self, other:String): String = 62 if |other| = 0 then self else CatString(self, other) end 63 opr || (self, _:EmptyString): String = self 64 opr || (self, other:Char) = CatString(self, other.toString) 65 end 28 66 (* 29 67 ==== CatString ==== 30 68 *) 31 69 32 object CatString(left: String, right:String) extends String70 object CatString(left: String, right:String) extends {String, Concatenable} 33 71 size = left.size + right.size 34 72 depthField = 1 + (left.depth MAX right.depth) … … 49 87 if i ∈ left.indices then left[i] else right[i - |left|] end 50 88 51 opr[r0:Range [\ZZ32\]] : String = do89 opr[r0:Range⟦ZZ32⟧] : String = do 52 90 r1 = self.bounds[r0] (* This will complete r0 if it is incomplete, and throw a bounds exception when necessary *) 53 self.uncheckedSubstring(r1) 91 if r1.isEmpty then 92 EmptyString 93 else 94 self.uncheckedSubstring(r1) 95 end 54 96 end 55 97 … … 65 107 right.showStructure(indent+8) 66 108 end 67 68 uncheckedSubstring(r0: Range⟦ZZ32⟧) = do 69 r1 = (r0 ↙ left.size) 109 110 (* without SubString nodes: 111 112 uncheckedSubstring(r0: Range⟦ZZ32⟧) = do 113 r1 = (r0 ≪ left.size) 70 114 left.uncheckedSubstring(r0 ∩ left.bounds) || right.uncheckedSubstring(r1 ∩ right.bounds) 71 115 end 72 73 74 (* Here is the three-way version: this framework is better once we have subString nodes 75 76 uncheckedSubstring(r0: Range[\ZZ32\]) = do 116 *) 117 118 uncheckedSubstring(r0: Range⟦ZZ32⟧) = do 77 119 leftBounds' = r0 ∩ left.bounds 78 r1 = (r0 ↙left.size)120 r1 = (r0 ≪ left.size) 79 121 rightBounds' = r1 ∩ right.bounds 80 if leftBounds.isEmpty then right.uncheckedSubstring(rightBounds') 81 else if rightBounds.isEmpty then left.uncheckedSubstring(leftBounds') 82 else left.uncheckedSubstring(leftBounds') || right.uncheckedSubstring(rightBounds') 83 end 84 *) 85 86 87 opr || (self, other:String): String = 88 if |other| = 0 then self else CatString(self, other) end 89 opr || (self, _:EmptyString) = self 90 opr || (self, other:Char) = CatString(self, other.toString) 91 122 (* atomic do 123 println "uncheckedSubstring " r0 " of " 124 self.showStructure() 125 println "===============" 126 println "leftBounds' = " leftBounds' ( if leftBounds'.isEmpty then "(empty)" else "(non-empty)" end ) 127 println "rightBounds' = " rightBounds' ( if rightBounds'.isEmpty then "(empty)" else "(non-empty)" end ) 128 println "===============" 129 end *) 130 if leftBounds'.isEmpty then 131 right.uncheckedSubstring(rightBounds') 132 elif rightBounds'.isEmpty then 133 left.uncheckedSubstring(leftBounds') 134 else 135 SubString'(self, r0) 136 end 137 end 138 92 139 println(self): () = do print(left) ; println(right) end 93 140 print(self): () = do print(left) ; print(right) end 94 95 end 96 97 object ConcatGenerator[\T\](first:Generator[\T\], second:Generator[\T\]) 98 extends Generator[\T\] 99 generate[\R\](r: Reduction[\R\], body:T->R):R = 100 r.join(first.generate[\R\](r, body), second.generate[\R\](r, body)) 141 142 subdivide(): Maybe⟦Generator⟦(ZZ32, String)⟧⟧ = Just ⟨ (0, left), (|left|, right) ⟩ 143 144 end 145 146 object ConcatGenerator⟦T⟧(first:Generator⟦T⟧, second:Generator⟦T⟧) 147 extends Generator⟦T⟧ 148 generate⟦R⟧(r: Reduction⟦R⟧, body:T->R):R = 149 r.join(first.generate⟦R⟧(r, body), second.generate⟦R⟧(r, body)) 101 150 end 102 151 … … 105 154 *) 106 155 107 value object EmptyString extends String156 value object EmptyString extends {String, Concatenable} 108 157 getter size() = 0 109 158 getter bounds() = 0#0 110 159 getter isEmpty() = true 111 getter generator() = Nothing [\Char\]160 getter generator() = Nothing⟦Char⟧ 112 161 opr CMP(self, other: String) = 113 162 |self| CMP |other| … … 116 165 get(i): Char = fail("Can't get characters from an empty string") 117 166 118 opr[r: Range [\ZZ32\]] : String = do167 opr[r: Range⟦ZZ32⟧] : String = do 119 168 rr = self.indices[r] (* to raise a bounds error *) 120 169 EmptyString … … 137 186 138 187 opr || (self, other:String): String = other 139 (* opr || (other: String, self): String = other *) (* this optimizes the case with EmptyString on the right*)140 opr || (self, _: EmptyString): String = self141 188 opr || (self, other:Char) = other.toString 142 189 … … 145 192 146 193 end 147 148 run(args: String...): () = do println "Finished" end 149 150 test rangeIntersect() = do 151 assert((0:5) ∩ (0:3), 0:3) 152 assert((0:5) ∩ (3:7), 3:5) 153 assert((0:5) ∩ (7:10), 7:5) 154 deny(5:3, 9:8) (* I hoped that that this would be an assert! *) 155 assert((5:3).size, 0, "The size of 5:3 is not zero!") 156 assert((9:8).size, 0, "The size of 9:8 is not zero!") 157 assert( (5:3).isEmpty, "5:3 is not empty!") 158 assert( (9:8).isEmpty, "9:8 is not empty!") 159 assert( ((0:5) ∩ (7:10)).isEmpty, "0:5 has a non-empty intersection with 7:10 !") 194 195 subdivide() = Nothing⟦Generator⟦(ZZ32, String)⟧⟧ 196 197 (* 198 ==== SubString ==== 199 *) 200 trait SubString extends {String, Concatenable} 201 comprises {SubString'} 202 end 203 204 object SubString'(parent: String, range: Range⟦ZZ32⟧) extends SubString 205 getter size() = range.size 206 getter depth() = parent.depth (* Why not one more than the parent? Would this break the balancing invariant? *) 207 getter isEmpty() = false 208 209 opr CMP(self, other: String) = do 210 (* if pgen ← parent.subdivide() then 211 BIG LEXICO [(start, str) ← pgen] self.uncheckedSubstring((start#|str|) ∩ self.bounds) CMP str 212 else 213 *) 214 (BIG LEXICO [i ← 0#(|self| MIN |other|)] self.get(i) CMP other.get(i)) LEXICO (|self| CMP |other|) 215 (* end 216 *) 217 end 218 219 220 verify() = do 221 parent.verify() 222 deny(range.isEmpty, "SubString (" range ") has empty range") 223 assert(range < parent.bounds, "SubString (" range ") has range equal to or greater than that of parent (" parent.bounds ")") 224 end 225 showStructure(indent) = do 226 margin(indent) 227 println "S" |self| "=[" range "]" 228 parent.showStructure(indent + 8) 229 end 230 231 get(i:ZZ32) = do 232 assert(i < range.size, "getting char " i " from a substring of size " |range|) 233 parent.get(range.lower+i) 234 end 235 236 uncheckedSubstring(r0: Range⟦ZZ32⟧) = do 237 assert((r0≫range.lower) ≤ range, "asking for substring [" r0 "] of S" self.size) 238 if r0.isEmpty then EmptyString 239 elif r0 = self.bounds then println "trivial substring"; self 240 else SubString'(parent, r0≫range.lower) 241 end 242 end 243 244 println(self): () = do print(self) ; println() end 245 print(self): () = for ch ← seq(self) do print ch end 246 247 subdivide(): Maybe⟦Generator⟦(ZZ32, String)⟧⟧ = do 248 (* The pairs (start, str) that are generated are such that start[0] = 0 and start[i] = | str[0] || ... || str[i-1] | 249 and str[0] || str [1] || ... || str[n] = self 250 *) 251 pieces = parent.subdivide() 252 offset = range.lower 253 if pgen ← pieces then 254 <| if (start#piece.size) ≤ range then 255 (start-offset, piece) 256 else 257 range' = range ∩ (start#piece.size) 258 (range'.lower-offset, SubString'(piece, range'≪start)) 259 end | (start, piece) ← pgen, (range ∩ (start#piece.size)).nonEmpty |> 260 else 261 Nothing⟦Generator⟦(ZZ32,String)⟧⟧ 262 end 263 end 160 264 end 161 265 -
trunk/Library/FortressLibrary.fsi
r2726 r2739 99 99 isLeftZero(_:Comparison): Boolean 100 100 end 101 102 opr BIG LEXICO(): BigReduction[\TotalComparison, TotalComparison\] 101 103 102 104 trait Comparison … … 701 703 trait Condition[\E\] extends SequentialGenerator[\E\] 702 704 getter isEmpty(): Boolean 705 getter nonEmpty(): Boolean 703 706 getter holds(): Boolean 704 707 getter size(): ZZ32 … … 973 976 defined as %|self| = 0%. *) 974 977 getter isEmpty(): Boolean 978 getter nonEmpty(): Boolean 975 979 (** %size()% is depracted; use %|self|% instead. *) 976 980 abstract getter size(): ZZ32 … … 1802 1806 RangeWithExtent[\T\], PartialRange[\T\] } 1803 1807 excludes { Number } 1804 1805 getter isEmpty(): Boolean 1808 1806 1809 opr =(self,_:Range[\T\]): Boolean 1807 1810 end … … 1969 1972 opr |self| : ZZ32 1970 1973 opr CASE_INSENSITIVE_CMP(self, other:String): TotalComparison 1974 1971 1975 opr [i:ZZ32]: Char 1972 1976 (** As a convenience, we permit LowerRange indexing to go 1 past the bounds … … 1978 1982 should be in a "friends" interface *) 1979 1983 uncheckedSubstring(r0: Range[\ZZ32\]) : String 1984 1985 subdivide(): Maybe[\Generator[\(ZZ32, String)\]\] 1980 1986 1981 1987 (** The operator %||% with at least one String argument converts to string and -
trunk/Library/FortressLibrary.fss
r2715 r2739 135 135 isLeftZero(_:Comparison): Boolean = true 136 136 end 137 138 opr BIG LEXICO(): BigReduction[\TotalComparison, TotalComparison\] = 139 BigReduction[\TotalComparison,TotalComparison\](LexicographicReduction) 140 137 141 138 142 trait Comparison … … 1100 1104 trait Condition[\E\] extends { ZeroIndexed[\E\], SequentialGenerator[\E\] } 1101 1105 getter isEmpty(): Boolean = NOT holds() 1106 getter nonEmpty(): Boolean = NOT isEmpty() 1102 1107 getter holds(): Boolean = cond[\Boolean\](fn (_:E):Boolean => true, fn () => false) 1103 1108 getter size(): ZZ32 = if holds() then 1 else 0 end … … 1453 1458 defined as size=0 *) 1454 1459 getter isEmpty(): Boolean = |self| = 0 1455 (** %size()% is depracated; use %|self|%. *) 1460 getter nonEmpty(): Boolean = NOT self.isEmpty 1461 (** %self.size% is equivalent to %|self|%. *) 1456 1462 getter size(): ZZ32 1457 1463 (** bounds() yields a range of indices that are valid for the … … 3027 3033 RangeWithExtent[\T\], PartialRange[\T\] } 3028 3034 excludes { Number } 3029 getter isEmpty(): Boolean = (|self| ≤ 0)3035 3030 3036 opr[r:Range[\T\]]: Range[\T\] = fail("Unrecognized Range " r) 3031 3037 opr[_:OpenRange[\Any\]] : Range[\T\] = self … … 3284 3290 self.lower#r.extent 3285 3291 else 3286 fail(self "[" r "] is not sufficiently largein some dimension")3292 fail(self "[" r "] is too small in some dimension") 3287 3293 end 3288 3294 opr[r:CompleteRange[\T\]]: CompleteRange[\T\] = … … 3303 3309 3304 3310 opr =(self, other:CompleteRange[\T\]): Boolean = 3305 self.isBounded=other.isBounded AND self.lower=other.lower AND 3306 self.extent = other.extent 3311 (* isBounded()=other.isBounded() AND 3312 APB 2008.08.20: this seems bogus: isBounded tells us only whether we were created 3313 using an extent or an upper bound, and should not effect the comparison *) 3314 lower()=other.lower() AND extent() = other.extent() 3315 3307 3316 opr CMP(self, other:Range[\T\]): Comparison = 3308 3317 typecase other of … … 3315 3324 (LessThan,LessThan) => Unordered 3316 3325 (GreaterThan,GreaterThan) => Unordered 3317 (EqualTo,EqualTo) => 3326 (* This case seems unncessary; the (EqualTo,Comparison) case will cover us --- APB 2008.08.20 3327 (EqualTo,EqualTo) => EqualTo 3318 3328 if self.isBounded = other.isBounded then 3319 3329 EqualTo … … 3321 3331 Unordered 3322 3332 end 3333 *) 3323 3334 (EqualTo,Comparison) => b 3324 3335 (GreaterThan,Comparison) => LessThan … … 3676 3687 3677 3688 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 3689 3690 opr CASE_INSENSITIVE_CMP(self, other:String): TotalComparison = 3691 ((BIG LEXICO[i <- 0#(|self| MIN |other|) ] self.get(i) CASE_INSENSITIVE_CMP other.get(i)) LEXICO (|self| CMP |other|)) 3692 3693 opr CMP(self, other:String): TotalComparison = 3694 ((BIG LEXICO[i <- 0#(|self| MIN |other|) ] self.get(i) CMP other.get(i)) LEXICO (|self| CMP |other|)) 3695 3696 opr [i:ZZ32]: Char = 3697 (** As a convenience, we permit LowerRange indexing to go 1 past the bounds 3680 3698 of the String, returning the empty String, in order to permit some convenient 3681 3699 String-trimming idioms. **) 3682 opr [i:ZZ32]: Char =3683 3700 if 0 <= i < |self| 3684 3701 then self.get(i) … … 3773 3790 3774 3791 3775 print(a:Any):() = print( "" a)3776 println(a:Any):() = println( "" a)3792 print(a:Any):() = print(a.toString) 3793 println(a:Any):() = println(a.toString) 3777 3794 (* 0-argument versions handle passing of () to single-argument versions. *) 3778 3795 print():() = print("") … … 3782 3799 println(a: JavaString): () = 3783 3800 builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$Println") 3784 3785 3801 3786 3802 forDigit(x:ZZ32, radix:ZZ32): Maybe[\Char\] = -
trunk/Library/JavaString.fss
r2708 r2739 33 33 opr |self| : ZZ32 = 34 34 builtinPrimitive("com.sun.fortress.interpreter.glue.prim.JavaString$Size") 35 35 36 uncheckedSubstring(r1: Range[\ZZ32\]) : String = 37 (* We could build a subString node here, but not until everything is working, because that will intorduce 38 SubString objects into code that may still expect JavaStrings *) 36 39 if r1.isEmpty then "" 37 40 else self.javaSubstr(r1.lower, r1.upper + 1) (* Java substr's endIndex is one past the last character *) 38 41 end 42 39 43 opr =(self, other:String): Boolean = 40 44 builtinPrimitive("com.sun.fortress.interpreter.glue.prim.JavaString$Eq") … … 66 70 67 71 (* The following are curently dead code; see lines 3765 ish in FortressLibrary.fss *) 72 (* 68 73 javaPrint(a: JavaString): () = 69 74 builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$Print") 70 75 javaPrintln(a: JavaString): () = 71 76 builtinPrimitive("com.sun.fortress.interpreter.glue.prim.StringPrim$Println") 77 *) 72 78 73 79 indexOf(c:Char): Maybe[\ZZ32\] = do … … 101 107 102 108 opr ||(self, b:String):String = 103 CatString(self, b) 104 (* This makes the overloading resolution go beserk ... 105 opr ||(self, b:EmptyString):String = self 106 *) 109 (* It would be good to do something more sophisticated when b is short, such as copying 110 self and b into a StringBuffer and then turning the whole thing into a JavaString *) 111 if self.isEmpty then b else CatString(self, b) end 112 113 107 114 opr ||(self, b:Char): String = 108 115 if |self| ≥ flatStringInfo.maxSize then … … 111 118 javaAppend(self, b) 112 119 end 120 121 subdivide() = Nothing[\Generator[\(ZZ32, String)\]\] 113 122 114 123 end -
trunk/ProjectFortress/not_passing_yet/CordedStringTests.fss
r2708 r2739 18 18 component CordedStringTests 19 19 import CordedString.{...} 20 import JavaString.{...} 20 21 import Set.{...} 21 22 import List.{...} … … 45 46 end 46 47 end 47 48 48 49 test subString(): () = do 49 50 words = ⟨"The", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog."⟩ … … 56 57 assert(testString[i:j], referenceString[i:j]) 57 58 end 58 59 59 end 60 60 61 test subStringSimplification():() = do 62 testString = catStringFrom("The", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog.") 63 testString.verify() 64 sub1 = testString[34:36] 65 typecase sub1 of 66 JavaString => assert(true) 67 String => do sub1.showStructure() 68 assert(false, "sub1=" sub1 " is not a JavaString") end 69 end 70 end 71 72 (* test *) validateSubdivision(subject: String, division: Maybe⟦Generator⟦(ZZ32, String)⟧⟧): () = do 73 var len: ZZ32 = 0 74 var accum: String = "" 75 if gen ← division then 76 for (start, str) ← seq(gen) do 77 assert(start, len, str) 78 len := len + |str| 79 accum := accum || str 80 end 81 assert(len, |subject|) 82 assert(accum, subject) 83 end 84 end 85 86 test testSubdivide():() = do 87 subject = CatString("abcd", "efgh") 88 substr1 = subject[2:6] 89 var len: ZZ32 = 0 90 var accum: String = "" 91 for (start, str) ← seq(substr1.subdivide()) do 92 assert(start, len, str) 93 len := len + |str| 94 accum := accum || str 95 end 96 assert(len, |substr1|) 97 accum.verify() 98 accum.showStructure() 99 assert(accum, substr1) 100 101 substr2 = subject[4:6] 102 assert(substr2.subdivide(), Nothing⟦Generator⟦(ZZ32,String)⟧⟧) 103 104 substr3 = subject[0:5] 105 for p ← seq(substr1.subdivide()) do 106 println ("found tuple" || p) (* This should (did?) work prefix string too *) 107 end 108 109 end 110 111 (* 112 test comparison():() = do 113 smaller = catStringFrom("The", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog.") 114 bigger = catStringFrom("The", "quick", "brown", "jumped", "fox", "over", "the", "lazy", "doggie.") 115 smaller.verify 116 bigger.verify 117 smaller.showStructure 118 bigger.showStructure 119 assert(smaller < bigger) 120 assert(smaller[10:] < bigger[10:]) 121 a = smaller[30:36] 122 b = bigger[30:36] 123 a.verify 124 b.verify 125 a.showStructure 126 b.showStructure 127 assert(smaller[30:36] = bigger[30:36], smaller[30:36] " is not = to " bigger[30:36]) 128 end 129 *) 130 object CatStringReduction extends MonoidReduction[\String\] 131 getter toString() = "CatStringReduction" 132 empty(): String = EmptyString 133 join(a:String, b:String):String = CatString(a, b) 134 end 135 136 test catStringFrom(args: String...): String = 137 seq(args).generate⟦String⟧(CatStringReduction, fn(x) => x) 138 139 61 140 test testNonEmptyConcat(): () = do 62 141 stuff = "Hello " … … 66 145 assert(hw, "Hello World") 67 146 assert(hw, CatString("Hell", "o World")) 68 assert(hw[2:7], "llo Wo")69 assert(hw[0:3], "Hell")70 assert(hw[5:2], "")71 147 end 72 148 … … 106 182 for i ← result.bounds do assert(result[i] , chars[i]) end 107 183 end 108 184 109 185 run(args:String...):() = do 110 186 println "Tests complete" -
trunk/ProjectFortress/tests/RangeTest.fss
r2196 r2739 131 131 chkOrder(mm,i,LessThan), i <- <|lm,lh',lh,mh|> 132 132 chkOrder(mm,hh,Unordered) 133 chkOrder(lh,lh', Unordered)134 chkOrder(lh',lh, Unordered)133 chkOrder(lh,lh',EqualTo) (* APB 2008.08.20 Changed this from Unordered. Also changed the code *) 134 chkOrder(lh',lh,EqualTo) (* APB 2008.08.20 Changed this from Unordered. Also changed the code *) 135 135 end 136 136

