add higher order functions to fold through Rope and TinyRope
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
# Brolib-sml
|
||||
|
||||
## Introduction
|
||||
|
||||
Standard ML port of [this](https://github.com/hummy123/brolib) rope implementation.
|
||||
|
||||
## Usage
|
||||
|
||||
91
rope.sml
91
rope.sml
@@ -22,7 +22,24 @@ sig
|
||||
* because then line metadata will become invalid. *)
|
||||
val delete: int * int * t -> t
|
||||
|
||||
(* This below function verifies that line metadata is as expected,
|
||||
(* Folds over the characters in the rope starting from the index
|
||||
* in the second parameter. *)
|
||||
val foldFromIdx: (char * 'a -> 'a) * int * t * 'a -> 'a
|
||||
|
||||
(* Like the foldFromIdx function, but accepts a predicate as the second
|
||||
* argument.
|
||||
* If the predicate returns true, terminates and returns the result;
|
||||
* else, continues folding until predicate returns true or until remaining
|
||||
* characters have been traversed. *)
|
||||
val foldFromIdxTerm: (char * 'a -> 'a) * ('a -> bool) * int * t * 'a -> 'a
|
||||
|
||||
(* This function folds over the characters in the rope,
|
||||
* starting from a given line number.
|
||||
* The second argument is a predicate indicating when to stop folding. *)
|
||||
val foldLines: (char * 'a -> 'a) * ('a -> bool) * int * t * 'a -> 'a
|
||||
|
||||
(* This below function is just for testing.
|
||||
* It verifies that line metadata is as expected,
|
||||
* raising an exception if it is different,
|
||||
* and returning true if it is the same. *)
|
||||
val verifyLines: t -> bool
|
||||
@@ -666,6 +683,78 @@ struct
|
||||
in if didIns then insRoot rope else rope
|
||||
end
|
||||
|
||||
fun foldStringChars (apply, term, pos, str, strSize, acc) =
|
||||
if pos < strSize then
|
||||
if term acc then
|
||||
acc
|
||||
else
|
||||
let
|
||||
val chr = String.sub (str, pos)
|
||||
val acc = apply (chr, acc)
|
||||
in
|
||||
foldStringChars (apply, term, pos + 1, str, strSize, acc)
|
||||
end
|
||||
else
|
||||
acc
|
||||
|
||||
fun foldFromIdxTerm (apply, term, idx, rope, acc) =
|
||||
case rope of
|
||||
N2 (l, lm, _, r) =>
|
||||
if idx < lm then
|
||||
let
|
||||
val acc = foldFromIdxTerm (apply, term, idx, l, acc)
|
||||
in
|
||||
if term acc then acc
|
||||
else foldFromIdxTerm (apply, term, idx - lm, r, acc)
|
||||
end
|
||||
else
|
||||
foldFromIdxTerm (apply, term, idx - lm, r, acc)
|
||||
| N1 t => foldFromIdxTerm (apply, term, idx, t, acc)
|
||||
| N0 (str, _) =>
|
||||
foldStringChars (apply, term, idx, str, String.size str, acc)
|
||||
| _ => raise AuxConstructor
|
||||
|
||||
fun noTerm _ = false
|
||||
|
||||
fun foldFromIdx (apply, idx, rope, acc) =
|
||||
foldFromIdxTerm (apply, noTerm, idx, rope, acc)
|
||||
|
||||
fun foldLineCharsTerm (apply, term, pos, str, strSize, acc) =
|
||||
if pos < strSize then
|
||||
case term acc of
|
||||
false =>
|
||||
let
|
||||
val chr = String.sub (str, pos)
|
||||
val acc = apply (chr, acc)
|
||||
in
|
||||
foldLineCharsTerm (apply, term, pos, str, strSize, acc)
|
||||
end
|
||||
| true => acc
|
||||
else
|
||||
acc
|
||||
|
||||
fun foldLines (apply, term, lineNum, rope, acc) =
|
||||
case rope of
|
||||
N2 (l, _, lmv, r) =>
|
||||
if lineNum < lmv then
|
||||
let
|
||||
val acc = foldLines (apply, term, lineNum, rope, acc)
|
||||
in
|
||||
if term acc then acc
|
||||
else foldLines (apply, term, lineNum - lmv, r, acc)
|
||||
end
|
||||
else
|
||||
foldLines (apply, term, lineNum - lmv, r, acc)
|
||||
| N1 t => foldLines (apply, term, lineNum, t, acc)
|
||||
| N0 (str, vec) =>
|
||||
let
|
||||
val idx =
|
||||
if Vector.length vec > 0 then Vector.sub (vec, lineNum) else 0
|
||||
in
|
||||
foldLineCharsTerm (apply, term, idx, str, String.size str, acc)
|
||||
end
|
||||
| _ => raise AuxConstructor
|
||||
|
||||
fun verifyLines rope =
|
||||
foldr
|
||||
( (fn (_, str, vec) =>
|
||||
|
||||
@@ -8,6 +8,8 @@ sig
|
||||
val append: string * t -> t
|
||||
val delete: int * int * t -> t
|
||||
val toString: t -> string
|
||||
val foldFromIdxTerm: (char * 'a -> 'a) * ('a -> bool) * int * t * 'a -> 'a
|
||||
val foldFromIdx: (char * 'a -> 'a) * int * t * 'a -> 'a
|
||||
end
|
||||
|
||||
structure TinyRope :> TINY_ROPE =
|
||||
@@ -21,8 +23,6 @@ struct
|
||||
|
||||
exception AuxConstructor
|
||||
|
||||
exception Substring of int
|
||||
|
||||
fun foldr (f, state, rope) =
|
||||
case rope of
|
||||
N2 (l, _, r) =>
|
||||
@@ -350,4 +350,39 @@ struct
|
||||
let val (rope, didAdd) = del (start, start + length, rope)
|
||||
in if didAdd then insRoot rope else delRoot rope
|
||||
end
|
||||
|
||||
fun foldStringChars (apply, term, pos, str, strSize, acc) =
|
||||
if pos < strSize then
|
||||
case term acc of
|
||||
false =>
|
||||
let
|
||||
val chr = String.sub (str, pos)
|
||||
val acc = apply (chr, acc)
|
||||
in
|
||||
foldStringChars (apply, term, pos + 1, str, strSize, acc)
|
||||
end
|
||||
| true => acc
|
||||
else
|
||||
acc
|
||||
|
||||
fun foldFromIdxTerm (apply, term, idx, rope, acc) =
|
||||
case rope of
|
||||
N2 (l, lm, r) =>
|
||||
if idx < lm then
|
||||
let
|
||||
val acc = foldFromIdxTerm (apply, term, idx, l, acc)
|
||||
in
|
||||
if term acc then acc
|
||||
else foldFromIdxTerm (apply, term, idx - lm, r, acc)
|
||||
end
|
||||
else
|
||||
foldFromIdxTerm (apply, term, idx - lm, r, acc)
|
||||
| N1 t => foldFromIdxTerm (apply, term, idx, t, acc)
|
||||
| N0 str => foldStringChars (apply, term, idx, str, String.size str, acc)
|
||||
| _ => raise AuxConstructor
|
||||
|
||||
fun noTerm _ = false
|
||||
|
||||
fun foldFromIdx (apply, idx, rope, acc) =
|
||||
foldFromIdxTerm (apply, noTerm, idx, rope, acc)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user