From d5ffb4f7627907d283eb5e84800350e3c88d2ecb Mon Sep 17 00:00:00 2001 From: humzashahid Date: Thu, 15 Feb 2024 12:30:48 +0000 Subject: [PATCH] progress rewriting rope.sml --- .DS_Store | Bin 6148 -> 6148 bytes .rope.sml.swp | Bin 0 -> 20480 bytes mlton | 1 + rope.sml | 613 ++++++++++++++++++++------------------------------ utils.sml | 28 ++- 5 files changed, 263 insertions(+), 379 deletions(-) create mode 100644 .rope.sml.swp create mode 160000 mlton diff --git a/.DS_Store b/.DS_Store index 6308708d133b54f75f97bbd24c133a93ffed3a48..13aadb5b59c834312f4dcb5531971feabbe86a87 100644 GIT binary patch delta 51 zcmV-30L=e{FoZCWPXPG?S|bT(N+> J0ka1P{SUR{5m*2K delta 427 zcmZoMXfc@J&nUDpU^g?P&}1H#neLJdi43I-B@FotxeTccMGWacG9HLi7&3vP@jzSz zRFMo6DQ3_E(!~sAo;mr+NjdpR3=9kc3=E7vftYXdES5xhc7_6=>U@SQpvn}6QZ#k4 zli#q|ha#&fWk^9&12l_4?>`s-Squ!E3_%R842}#g48A~G4@kP8>R?I-+pfTxZ7Tw_ zyAM^n$Qh4VFRnZqZlZBfM(g JGdss$egHabURwYF diff --git a/.rope.sml.swp b/.rope.sml.swp new file mode 100644 index 0000000000000000000000000000000000000000..38d7d9319cfb857b6d262a35246952fc0524d7f5 GIT binary patch literal 20480 zcmeI2S&S4#7{^OI@WKP5hN!W`gI(maMDVT^F4&1;Ro9Dl9qTI>`z_+uYgy; zE8rFI3U~#)0$u^HfLFjP;1%!+j6#8cMf$mWDz(D|Zf5=8egA*Ew^AG7ZFmB1hb3?| zTn4k@XqXBI!36kqFQqoYd+;u-ho|9ASP6?@Hk<)Rz%HT`Gw9*0%19D3m_=!8RINBDKTQXj)QxCJUO z7c~5|3-yKduo`ZFYv2-C06lOd{IauBAHtjP6s(2AKV2R*cg7uL?@_TXc_(Gv;P}w2rgpswrhXM@gDXlXkaBN-8QA=cc*DTqJ4b!c|9W zsfCT;7O6cyn@V)eU;5{WzMG>_8Oorq$ILrENu^$9KBq}d-PK12-7I9Bmm zsXt7e$?!@z=km{*h_&dk8%I*h-Qq~ttnesC9Bo_9TB|Lr?U2*jJmOut)0XL|dlDKq zC*k5v8a;^#r_8N-6Z2%|pOap^$&hA%B~yyE6>l2nMsOEt7nOT*ZHB$A59?#p9Dk`b znj53uS8=yi@_BK!7%iS*I-EH3rr&hH)VXV2Z#og!wUBJdb#6Y&X!Em2H?&034E07B z=>>44CP+PndFQgPaL(-9Th+F{6}oiRF>4MSO7c24f<+IxAX(qy<2Vf;s1S{(Nilj+KKCr#U%qjx2ZJ+<+~BM#9eCDN8M)fJH_*>GDiiuF_)SpJIu z=3cy=&6uCmFU?3T3gRGMO1E}m$@l+he21?E`Tlq7@4xXqzZrgjPv8xB8DuWt0k{=p zJ|Kb%;B3gi6xa)7KHwMf{2tzix8Mbka-IQycm=!yUIDLwSHLUa74Qmp1-t@Y0k42p zU@HnR0pO-T<|R{Hg-TQiVqL1qgp{4^Fw;UcS&@s)B!FIUsrx{d`DR(VNFtacvtPr* zCS2;%2b9U-ij`}dYfvcYl9GV5WVw{mB`PglepHo2ndvEIKjdZogJ}`|8dpIY@=jL! zWct$1%t;0vObeWNB3ULgn#l|V@#H#eYNR2r2iefD=Hz@sENd;Q$y9oB5t!2M@!&umS?ezU-*&r`mf=2cmh^H0B6EP z*u%U;TkAIFU*0Na3Fledi@4?1s;TzFdvSCNwA4Eds)X{4L8C9khT2ja5#L= zTK$*s8pxXdLvRl)hs&W0Cct8jl`#`!&}(NP#@9c4!Z;)gQnl{@;}=aC5zjQWH66J!j=jsO4v literal 0 HcmV?d00001 diff --git a/mlton b/mlton new file mode 160000 index 0000000..fd6d870 --- /dev/null +++ b/mlton @@ -0,0 +1 @@ +Subproject commit fd6d8705780ea6e223c91a6b33553be1633c4eab diff --git a/rope.sml b/rope.sml index 218c9eb..fec75bb 100644 --- a/rope.sml +++ b/rope.sml @@ -1,398 +1,277 @@ -datatype rope = - N0 of string - | N1 of rope - | N2 of rope * int * int * rope - | L2 of string * string - | N3 of rope * rope * rope +signature ROPE = sig + type t + val empty : t + val of_string : string -> t + val size : t -> int + val insert : int * string * t -> t +end -val target_length = 1024 -val empty = N0 "" -fun of_string string = N0 string +structure Rope :> ROPE = struct + datatype t + = N0 of string + | N1 of t + | N2 of t * int * t + | L2 of string * string + | N3 of t * t * t -exception Size -exception Ins -exception Substring -exception Delete -exception To_string + datatype balance + = AddedNode + | DeletedNode + | NoAction -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 Size + val target_length = 1024 + val empty = N0 "" + fun of_string string = N0 string -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 is_less_than_target(str1, str2) = + String.size str1 + String.size str2 <= target_length -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, N1 t3) - end - | t => N1 t + exception AuxConstructor -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) + local + fun help_size(acc, rope) = + case rope of + N0 s => + acc + String.size s + | N1 t => + help_size(acc, t) + | N2(_, lm, r) => + help_size(acc + lm, r) + | _ => raise AuxConstructor + in + fun size rope = help_size(0, rope) + end -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 - | (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 - | (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 => + fun ins_root rope = + case rope of + L2(s1, s2) => + N2(N0 s1, String.size s1, N0 s2) + | N3(t1, t2, t3) => let - val t = ins cur_index string t + val t1_size = size t1 + val left = N2(t1, t1_size, t2) + val t2_size = size t2 in - n1 t + N2(left, t1_size + t2_size, N1 t3) 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 + | t => + N1 t + + fun del_root rope = + case rope of + N1 t => t + | t => t + + fun ins_n1 rope = + case rope of + L2 (s1, s2) => + N2(N0 s1, String.size s1, N0 s2) + | N3(t1, t2, t3) => let - val next_index = cur_index - lm - val r = ins next_index string r + val left = N2(t1, size t1, t2) in - ins_n2_right l r + N2(left, size left, t2) end - | _ => raise Ins + | t => + N1 t -fun insert index string rope = - let - val rope = ins index string rope - in - root rope - end + 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 left = N2(t1, t1_size, t2) + val t3_size = size t3 + val right = N2(t3, t3_size, t4) + val t2_size = size t2 + val left_size = t1_size + t2_size + in + N2(left, left_size, right) + end + | (N3(t1, t2, t3), t4) => + let + val left = N2(t1, size t2, t2) + in + N3(left, N1 t3, t4) + end + | (l, r) => + N2(l, size l, r) -fun sub start_idx end_idx acc rope = - case rope of - N0 str => - let - val str_size = String.size str - val before_start = start_idx <= 0 - val after_start = start_idx >= 0 - val after_end = end_idx >= str_size - val before_end = end_idx <= str_size - in - if before_start andalso after_end then - (str :: acc) - else if after_start andalso before_start then - let - val len = end_idx - start_idx - val str = String.substring(str, start_idx, len) - in - (str :: acc) - end - else if after_start andalso after_end then - let - val len = str_size - start_idx - val str = String.substring(str, start_idx, len) - in - (str :: acc) - end + fun del_n2_left(left, right) = + case (left, right) of + (N1 t1, N1 t2) => + N1(N2(t1, size t1, t2)) + | (N1 (N1 t1), N2(N1 t2, _, (t3 as N2 _))) => + let + val left = N2(t1, size t1, t2) + val inner = N2(left, size left, t3) + in + N1 (inner) + end + | (N1 (N1 t1), N2(N2(t2, _, t3), _, N1 t4)) => + let + val left = N2(t1, size t1, t2) + val right = N2(t3, size t3, t4) + val inner = N2(left, size left, right) + in + N1 inner + end + | (N1 (t1 as N1 _), N2((t2 as N2 _), _, (t3 as N2 _))) => + let + val left = N2(t1, size t1, t2) + val right = N1 t3 + in + N2(left, size left, right) + end + | (l, r) => + N2(l, size l, 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 left = N2(t1, size t1, t2) + val t3_size = size t3 + val right = N2(t3, t3_size, t4) + in + N2(left, size left, right) + end + | (t1, N3(t2, t3, t4)) => + let + val right = N2(t3, size t3, t4) + in + N3(t1, N1 t2, right) + end + | (l, r) => + N2(l, size l, r) + + fun del_n2_right(left, right) = + case (left, right) of + (N2(N1 t1, _, N2(t2, _, t3)), N1 t4) => + let + val left = N2(t1, size t1, t2) + val right = N2(t3, size t3, t4) + val inner = N2(left, size left, right) + in + N1 inner + end + | (N2((t1 as N2 _), lm, N1 t2), N1 (N1 t3)) => + let + val right = N2(t2, size t2, t3) + val inner = N2(t1, lm, right) + in + N1 inner + end + | (N2( (t1 as N2 _), _, (t2 as N2 _)), N1 (N1 t3)) => + let + val left_size = size t1 + val left = N1 t1 + val right = N2(t2, size t2, t3) + in + N2(left, left_size, right) + end + | (l, r) => + N2(l, size l, r) + + local + fun ins_leaf(cur_index, new_str, rope, old_str) = + if cur_index <= 0 then + if is_less_than_target(old_str, new_str) then + (N0(new_str ^ old_str), NoAction) else - let - val str = String.substring(str, 0, end_idx) - in - (str::acc) - end - end - | N1 t => - sub start_idx end_idx acc t - | N2(l, lm, _, r) => + (L2(new_str, old_str), AddedNode) + else if cur_index >= String.size old_str then + if is_less_than_target(old_str, new_str) then + (N0(old_str ^ new_str), NoAction) + else + (L2(old_str, new_str), AddedNode) + else + (* Need to split in middle of string. *) let - val starts_before = lm > start_idx - val ends_before = lm > end_idx - val starts_after = lm < start_idx - val ends_after = lm < end_idx + val sub1 = String.substring(old_str, 0, cur_index) + val sub2_len = String.size old_str - cur_index + val sub2 = String.substring(old_str, cur_index, sub2_len) in - if starts_before andalso ends_before then - sub start_idx end_idx acc l - else if starts_after andalso ends_after then - let - val next_start = start_idx - lm - val next_end = end_idx - lm - in - sub next_start next_end acc r - end + if is_less_than_target(old_str, new_str) then + (N0(sub1 ^ new_str ^ sub2), NoAction) + else if cur_index + String.size new_str <= target_length then + (L2(sub1 ^ new_str, sub2), AddedNode) + else if (String.size old_str - cur_index) + String.size new_str <= target_length then + (L2(sub1, new_str ^ sub2), AddedNode) else - let - val next_start = start_idx - lm - val next_end = end_idx - lm - val sub_acc = sub next_start next_end acc r - in - sub start_idx end_idx sub_acc l - end + (N3(N0 sub1, N0 new_str, N0 sub2), AddedNode) end - | _ => raise Substring - -fun substring start length rope = - let - val finish = start + length - val lst = sub start finish [] rope - in - String.concat lst - end - -fun del start_idx end_idx rope = - case rope of - N0 str => - let - val str_size = String.size str - val before_start = start_idx <= 0 - val after_end = end_idx >= str_size - val after_start = start_idx >= 0 - val before_end = end_idx <= str_size - in - if before_start andalso after_end then - (N0 "", false) - else if after_start andalso before_end then - let - val str1 = String.substring(str, 0, start_idx) - val del_len = str_size - end_idx - val str2 = String.substring(str, start_idx, del_len) - val new_len = str_size - del_len - in - if new_len <= target_length then - (N0(str1 ^ str2), false) - else - (L2(str1, str2), true) - end - else if after_start andalso after_end then - let - val str = String.substring(str, 0, start_idx) - in - (N0 str, false) - end - else + fun ins(cur_index, new_str, rope) = + case rope of + N2(l, lm, r) => + if cur_index < lm then let - val len = str_size - end_idx - val str = String.substring(str, end_idx, len) + val (l, action) = ins(cur_index, new_str, l) in - (N0 str, false) - end - end - | N1 t => - let - val (t, did_ins) = del start_idx end_idx t - val t = if did_ins then n1 t else t - in - (t, did_ins) - end - | N2(l, lm, rm, r) => - let - val start_is_less = lm > start_idx - val end_is_less = lm > end_idx - val start_is_more = lm < start_idx - val end_is_more = lm < end_idx - in - if start_is_less andalso end_is_less then - let - val (l, did_ins) = del start_idx end_idx l - in - case did_ins of - false => - (N2(l, size l, rm, r), false) - | true => - (ins_n2_left l r, true) - end - else if start_is_more andalso end_is_more then - let - val next_start = start_idx - lm - val next_end = end_idx - lm - val (r, did_ins) = del next_start next_end r - in - case did_ins of - false => - (N2(l, lm, size r, r), false) - | true => - (ins_n2_right l r, true) + (case action of + NoAction => + (case (l, r) of + (N0 s1, N0 s2) => + if is_less_than_target(s1, s2) then + (N0 (s1 ^ s2), DeletedNode) + else + (N2(l, lm + String.size new_str, r), action) + | _ => + (N2(l, lm + String.size new_str, r), action)) + | AddedNode => + (ins_n2_left(l, r), action) + | DeletedNode => + (del_n2_left(l, r), action)) end else let - val (l, did_ins_l) = del start_idx end_idx l - val r_start = start_idx - lm - val r_end = end_idx - lm - val (r, did_ins_r) = del r_start r_end r + val (r, action) = ins(cur_index - lm, new_str, r) in - if did_ins_l then - (ins_n2_left l r, true) - else if did_ins_r then - (ins_n2_right l r, true) - else - (N2(l, size l, size r, r), false) + (case action of + NoAction => + (case (l, r) of + (N0 s1, N0 s2) => + if is_less_than_target(s1, s2) then + (N0 (s1 ^ s2), DeletedNode) + else + (N2(l, lm, r), action) + | _ => + (N2(l, lm, r), action)) + | AddedNode => + (ins_n2_right(l, r), action) + | DeletedNode => + (del_n2_right(l, r), action)) end - end - | _ => raise Delete - -fun delete start length rope = - let - val finish = start + length - val (t, did_ins) = del start finish rope - val t = if did_ins then root rope else rope - in - t - end - -fun to_str acc rope = - case rope of - N0 str => - (str::acc) - | N1 t => - to_str acc t - | N2 (l, _, _, r) => + | N1 t => + let + val (t, action) = ins(cur_index, new_str, t) + in + (case action of + AddedNode => + (ins_n1 t, action) + | _ => + (N1 t, action)) + end + | N0 old_str => + ins_leaf(cur_index, new_str, rope, old_str) + | _ => + raise AuxConstructor + in + fun insert (index, str, rope) = let - val acc = to_str acc r + val (rope, action) = ins(index, str, rope) in - to_str acc l + (case action of + NoAction => + rope + | AddedNode => + ins_root rope + | DeletedNode => + del_root rope) end - | _ => raise To_string - -fun to_string rope = - let - val lst = to_str [] rope - in - String.concat lst end +end diff --git a/utils.sml b/utils.sml index 726869b..a1cf381 100644 --- a/utils.sml +++ b/utils.sml @@ -50,9 +50,15 @@ fun run_to_string_time title rope = time_func title f end -fun run_txns_1000_times counter arr acc = +fun run_txns_1000_times (counter, arr, total) = if counter = 1000 then - acc + let + val divisor = Int.toLarge 1000 + val total = total div divisor + val str = LargeInt.toString total + in + print str + end else let val start_time = Time.now() @@ -63,9 +69,10 @@ fun run_txns_1000_times counter arr acc = val end_time = Time.now() val end_time = Time.toMilliseconds end_time val time_diff = end_time - start_time - val time_diff = LargeInt.toString time_diff + val counter = counter + 1 + val total = time_diff + total in - run_txns_1000_times (counter + 1) arr (time_diff::acc) + run_txns_1000_times (counter, arr, total) end fun write_file filename acc = @@ -80,17 +87,14 @@ fun write_file filename acc = val _ = let - val svelte = run_txns_1000_times 0 svelte_arr [] - val _ = write_file "svelte_edit_traces.csv" svelte + val start_time = LargeInt.fromInt 0 + val svelte = run_txns_1000_times (999 ,svelte_arr, start_time ) - val rust = run_txns_1000_times 0 rust_arr [] - val _ = write_file "rust_edit_traces.csv" rust + val rust = run_txns_1000_times (999 ,rust_arr, start_time ) - val seph = run_txns_1000_times 0 seph_arr [] - val _ = write_file "seph_edit_traces.csv" seph + val seph = run_txns_1000_times (999, seph_arr, start_time) - val automerge = run_txns_1000_times 0 automerge_arr [] - val _ = write_file "automerge_edit_traces.csv" automerge + val automerge = run_txns_1000_times (999, automerge_arr , start_time) in () end