datatype rope = N0 of string | N1 of rope | N2 of rope * int * int * rope | L2 of string * string | N3 of rope * rope * rope val target_length = 1024 val empty = N0 "" fun of_string string = N0 string fun size rope = case rope of N0 s => String.size s | N1 t => size t | N2(_, lm, rm, _) => lm + rm | N3(t1, t2, t3) => let val t1_size = size t1 val t2_size = size t2 val t3_size = size t3 in t1_size + t2_size + t3_size end | _ => raise Empty fun root rope = case rope of L2(s1, s2) => N2(N0 s1, String.size s1, String.size s2, N0 s2) | N3(t1, t2, t3) => let val t1_size = size t1 val t2_size = size t2 val left = N2(t1, t1_size, t2_size, t2) val left_size = t1_size + t2_size val t3_size = size t3 in N2(left, left_size, t3_size, N1 t3) end | t => t fun n1 rope = case rope of L2(s1, s2) => N2(N0 s1, String.size s1, String.size s2, N0 s2) | N3(t1, t2, t3) => let val t1_size = size t1 val t2_size = size t2 val left = N2(t1, t1_size, t2_size, t2) val left_size = t1_size + t2_size val t3_size = size t3 in N2(left, left_size, t3_size, t3) end | t => N1 t fun ins_n2_left left right = case (left, right) of (L2(s1, s2), t3) => N3(N0 s1, N0 s2, t3) | (N3(t1, t2, t3), N1 t4) => let val t1_size = size t1 val t2_size = size t2 val left = N2(t1, t1_size, t2_size, t2) val left_size = t1_size + t2_size val t3_size = size t3 val t4_size = size t4 val right = N2(t3, t3_size, t4_size, t4) val right_size = t3_size + t4_size in N2(left, left_size, right_size, right) end | (N3(t1, t2, t3), t4 as N2 _) => let val left = N2(t1, size t1, size t2, t2) in N3(left, N1 t3, t4) end | (N3(t1, t2, t3), t4) => let val t1_size = size t1 val t2_size = size t2 val left = N2(t1, t1_size, t2_size, t2) val t3_size = size t3 val t4_size = size t4 val right = N2(t3, t3_size, t4_size, t4) val left_size = t1_size + t2_size val right_size = t3_size + t4_size in N2(left, left_size, right_size, right) end | (l, r) => N2(l, size l, size r, r) fun ins_n2_right left right = case (left, right) of (t1, L2(s1, s2)) => N3(t1, N0 s1, N0 s2) | (N1 t1, N3(t2, t3, t4)) => let val t1_size = size t1 val t2_size = size t2 val left = N2(t1, t1_size, t2_size, t2) val t3_size = size t3 val t4_size = size t4 val right = N2(t3, t3_size, t4_size, t4) val right_size = t3_size + t4_size val left_size = t1_size + t2_size in N2(left, left_size, right_size, right) end | (t1 as N2 _, N3(t2, t3, t4)) => let val right = N2(t3, size t3, size t4, t4) in N3(t1, N1 t2, right) end | (l, r) => N2(l, size l, size r, r) fun ins cur_index string rope = case rope of N0 str => let val old_str_size = String.size str val ins_str_size = String.size string val total_str_size = old_str_size + ins_str_size val left_size = ins_str_size + cur_index val prefer_left = left_size <= target_length val right_size = ins_str_size - cur_index val prefer_right = right_size <= target_length in if cur_index <= 0 then if total_str_size <= target_length then N0(string ^ str) else L2(string, str) else if cur_index >= old_str_size then if total_str_size <= target_length then N0(str ^ string) else L2(str, string) else if total_str_size <= target_length then let val str1 = String.substring(str, 0, cur_index) val str3 = String.substring(str, cur_index, old_str_size - cur_index) in N0(String.concat [str1, string, str3]) end else let val str1 = String.substring(str, 0, cur_index) val str3 = String.substring(str, cur_index, old_str_size - cur_index) in if prefer_left then L2(str1 ^ string, str3) else if prefer_right then L2(str1, string ^ str3) else N3(N0 str1, N0 string, N0 str3) end end | N1 t => let val t = ins cur_index string t in n1 t end | N2(l, lm, _, r) => if cur_index < lm then let val l = ins cur_index string l in ins_n2_left l r end else let val next_index = cur_index - lm val r = ins next_index string r in ins_n2_right l r end | _ => raise Empty