root/trunk/Library/CordedString.fss @ 2708

Revision 2708, 5.6 KB (checked in by black, 15 months ago)

Next iteration of CordedStrings?, with subrange and subscripting working, depth, and a diagnostic showStructure.

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 CordedString
19export CordedString
20
21(* I believe that these should eventually go with the range code. *)
22
23    (*Intersection of two ranges *)
24    opr ∩ (r0: Range[\ZZ32\], r1: Range[\ZZ32\]) = (r0.lower MAX r1.lower) : (r0.upper MIN r1.upper)
25    (* Shift a range left by the specified amount.  *)
26    opr ↙(r: Range[\ZZ32\], leftShift: ZZ32) = (r.lower - leftShift)#r.extent
27
28(*
29==== CatString ====
30*)
31
32  object CatString(left: String, right:String)  extends String
33    size = left.size + right.size
34    depthField = 1 + (left.depth MAX right.depth)
35    getter depth() = depthField
36    getter bounds() = 0#size
37    getter generator() = ConcatGenerator(left.generator, right.generator)
38    opr CMP(self, other: String) =
39        if |left| ≥ |other|
40        then
41            left CMP other
42        else
43            (left CMP other[0#|left|]) LEXICO: (right CMP other[(|left|):])
44        end
45    opr CASE_INSENSITIVE_CMP(self, other:String): TotalComparison = EqualTo
46
47    get(i): Char =
48    (* get is, and should be, without bounds checks.  [ ] does the bounds checks,a and then delegates to get *)   
49        if i ∈ left.indices then left[i] else right[i - |left|] end
50
51    opr[r0:Range[\ZZ32\]] : String =  do
52        r1 = self.bounds[r0]     (* This will complete r0 if it is incomplete, and throw a bounds exception when necessary *)
53        self.uncheckedSubstring(r1)
54      end
55     
56    verify() = do
57        assert(self.depth, (left.depth MAX right.depth) + 1, self)
58        assert(self.size(), |left| + |right|, self)
59    end
60       
61    showStructure(indent: ZZ32) = do
62        margin(indent)
63        println  ("C" || |self| "/" self.depth || ":" )
64        left.showStructure(indent+8)
65        right.showStructure(indent+8)
66    end
67     
68    uncheckedSubstring(r0: Range⟦ZZ32⟧) = do
69        r1 = (r0 ↙ left.size)
70        left.uncheckedSubstring(r0 ∩ left.bounds) || right.uncheckedSubstring(r1 ∩ right.bounds)           
71      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
77        leftBounds' = r0 ∩ left.bounds
78        r1 = (r0 ↙ left.size)
79        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   
92    println(self): () = do print(left) ; println(right) end 
93    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))
101  end
102
103(*
104==== EmptyString ====
105*)
106
107  value object EmptyString extends String
108    getter size() = 0
109    getter bounds() = 0#0
110    getter isEmpty() = true
111    getter generator() = Nothing[\Char\]
112    opr CMP(self, other: String) =
113        |self| CMP |other|
114    opr CASE_INSENSITIVE_CMP(self, other:String): TotalComparison =  |self| CMP |other|
115
116    get(i): Char = fail("Can't get characters from an empty string")
117
118    opr[r: Range[\ZZ32\]] : String = do
119        rr = self.indices[r]     (* to raise a bounds error *)
120        EmptyString
121    end
122   
123    verify() = do
124        assert(self.depth, 0, self)
125        assert(self.size, 0, self)
126    end
127         
128    showStructure(indent) = do
129        margin(indent)
130        println "E" |self| "/" self.depth
131    end
132   
133    uncheckedSubstring(r0: Range⟦ZZ32⟧) = do
134        assert r0.isEmpty
135        self
136    end
137
138    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 = self
141    opr || (self, other:Char) = other.toString
142     
143    print(self): () = do end
144    println(self): () = println("")
145 
146  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 !")
160  end
161 
162  margin(indent) = do
163      for i ← 0#indent do print " " end
164  end
165 
166end
Note: See TracBrowser for help on using the browser.