functorise character folders to reduce repetitive boilerplate code (but have not functorised yet)

This commit is contained in:
2025-08-03 16:21:36 +01:00
parent 9662540889
commit 473ea8e35d

View File

@@ -21,8 +21,11 @@ struct
(* strIdx is in tl *)
(case stl of
stlhd :: stltl =>
let val strIdx = strIdx - String.size shd
in M.fStart (strIdx, cursorIdx, stlhd, stltl, M.startState, count)
let
val strIdx = strIdx - String.size shd
in
M.fStart
(strIdx, cursorIdx, stlhd, stltl, M.startState, count)
end
| _ => cursorIdx)
| [] => cursorIdx
@@ -77,7 +80,13 @@ struct
val leftStrings = shd :: leftStrings
in
M.fStart
(strIdx, cursorIdx, stlhd, leftStrings, M.startState, count)
( strIdx
, cursorIdx
, stlhd
, leftStrings
, M.startState
, count
)
end
| [] => cursorIdx)
| [] => cursorIdx
@@ -95,7 +104,8 @@ struct
if strIdx < 0 then
case leftStrings of
lhd :: ltl =>
M.fStart (String.size lhd - 1, absIdx, lhd, ltl, M.startState, count)
M.fStart
(String.size lhd - 1, absIdx, lhd, ltl, M.startState, count)
| [] => 0
else
case #rightStrings lineGap of
@@ -104,3 +114,76 @@ struct
| [] => Int.max (0, cursorIdx - 2)
end
end
signature MAKE_CHAR_FOLDER =
sig
val startState: Word8.word
val tables: Word8.word vector vector
val isFinal: Word8.word -> bool
val finish: int -> int
end
functor MakeCharFolderNext(Fn: MAKE_CHAR_FOLDER) =
struct
fun nextState (currentState, currentChar) =
let
val currentState = Word8.toInt currentState
val currentTable = Vector.sub (Fn.tables, currentState)
val charIdx = Char.ord currentChar
in
Vector.sub (currentTable, charIdx)
end
fun foldNext (idx, absIdx, str, tl, currentState, counter) =
if idx = String.size str then
case tl of
str :: tl => foldNext (0, absIdx, str, tl, currentState, counter)
| [] => Int.max (absIdx - 2, 0)
else
let
val chr = String.sub (str, idx)
val newState = nextState (currentState, chr)
in
if Fn.isFinal newState then
if counter - 1 = 0 then
Fn.finish absIdx
else
(* new loop, so reset to start state and proceed *)
foldNext (idx + 1, absIdx + 1, str, tl, Fn.startState, counter - 1)
else
foldNext (idx + 1, absIdx + 1, str, tl, newState, counter)
end
end
functor MakeCharFolderPrev(Fn: MAKE_CHAR_FOLDER) =
struct
fun nextState (currentState, currentChar) =
let
val currentState = Word8.toInt currentState
val currentTable = Vector.sub (Fn.tables, currentState)
val charIdx = Char.ord currentChar
in
Vector.sub (currentTable, charIdx)
end
fun foldPrev (idx, absIdx, str, tl, currentState, counter) =
if idx < 0 then
case tl of
str :: tl =>
foldPrev (String.size str - 1, absIdx, str, tl, currentState, counter)
| [] => 0
else
let
val chr = String.sub (str, idx)
val newState = nextState (currentState, chr)
in
if Fn.isFinal newState then
if counter - 1 = 0 then
Fn.finish absIdx
else
foldPrev (idx - 1, absIdx - 1, str, tl, Fn.startState, counter - 1)
else
foldPrev (idx - 1, absIdx - 1, str, tl, newState, counter)
end
end