1 type String @abstract = 2 let mut display = StringBuilder.new 3 let mut staging = StringBuilder.new 4 var is_constant = false 5 let mut is_deferred = false 6 var is_invoking_callbacks = false 7 let callbacks = StdList<StdString * StdString -> Unit>.new 8 9 def as_string = display.as_string 10 def length = display.length 11 def has_callbacks = callbacks.is_not_empty 12 def is_empty = length == 0 13 def is_not_empty = length <> 0 14 15 def subscribe (f : StdString * StdString -> Unit) = 16 assert not is_invoking_callbacks 17 callbacks.add f 18 19 Token { assert not is_invoking_callbacks 20 callbacks.remove f } 21 22 fun destruct = 23 assert callbacks.is_empty 24 25 type MutString @[mut_of String] = 26 inherit String 27 28 let invoke_callbacks () = 29 assert not is_invoking_callbacks 30 is_invoking_callbacks = true 31 let s = display.as_string 32 let prev_s = staging.as_string 33 34 for f in callbacks do 35 f prev_s s 36 37 is_invoking_callbacks = false 38 39 let commit () = 40 if is_deferred then 41 return 42 43 assert not is_constant 44 let s = display 45 display = staging 46 staging = s 47 invoke_callbacks 48 staging.clear 49 staging.append display.as_string 50 51 def as_readonly = self as String 52 53 def set (s : StdString) = 54 if s <> display.as_string then 55 staging.clear 56 staging.append s 57 commit 58 59 def make_constant = 60 assert not is_constant 61 is_constant = true 62 63 def defer_commits = 64 assert not is_deferred 65 is_deferred = true 66 67 def resume_commits = 68 assert is_deferred 69 is_deferred = false 70 if display.as_string <> staging.as_string then 71 commit 72 73 def insert (index : u32) (c : Char) = 74 staging.insert index c 75 commit 76 77 def insert (index : u32) (s : StdString) = 78 staging.insert index s 79 commit 80 81 def replace (start : u32 82 end : u32 83 s : StdString) = 84 staging.replace_range start end s 85 commit 86 87 def append (s : StdString) = 88 staging.append s 89 commit 90 91 def remove_at (index : u32) = 92 staging.remove_at index 93 commit 94 95 def remove_range (index : u32) (count : u32) = 96 staging.remove_range index (index + count) 97 commit 98 99 def clear = 100 staging.clear 101 commit 102 103 object String = 104 def from_str (s : StdString) = 105 let string = String.new 106 string.set s 107 108 string 109