Started refactor

This commit is contained in:
Florian Schroedl
2022-08-09 22:07:30 +02:00
parent 9b0ad40f55
commit 892eec10d5
10 changed files with 1048 additions and 0 deletions

37
src_v2/utils/fp.nim Normal file
View File

@@ -0,0 +1,37 @@
import std/sugar
import fp/maybe
import results
func last*[T](xs: seq[T]): Maybe[T] =
if xs.len == 0:
nothing(T)
else:
just(xs[^1])
template isSome*(self: Result): bool = self.isOk()
template isNone*(self: Result): bool = self.isErr()
proc findMaybe*[T](xs: seq[T], fn: T -> bool): Maybe[T] =
for x in xs:
if fn(x):
return Just(x)
return Nothing[T]()
proc findMaybeFn*[T, B](fns: seq[T {.nimcall.} -> Maybe[B]], val: T): Maybe[B] =
for fn in fns:
let res = fn(val)
if res.isDefined():
return res
return Nothing[B]()
proc notNegative*[int](x: Maybe[int]): Maybe[int] =
## Maps nil object to nothing
x.filter(i => i >= 0)
when isMainModule:
echo @[
(x: int) => (if x == 2: Just("foo") else: Nothing[string]()),
].findMaybeFn(2)
assert last(@[1,2,3]) == just(3)
assert last[int](@[]) == nothing(int)

View File

@@ -0,0 +1,15 @@
import sequtils
import std/sugar
import microparsec
import results
echo toSeq(1..1000000)
# let headlineParser = manyTill(ch '*', space)
# .flatMap((stars: seq[char]) => pure(stars))
# # .flatMap((stars) => manyTill(anyChar, endOfLine)
# # .flatMap(headline => pure(stars, headline))
# # )
# echo headlineParser.parse("*** Headline")
# echo headlineParser.parse("* Headline")

28
src_v2/utils/parser.nim Normal file
View File

@@ -0,0 +1,28 @@
import std/parseutils
proc fastSubstr(s: string; token: var string; start, length: int) =
token.setLen length
for i in 0 ..< length: token[i] = s[i+start]
proc parseUntilBackwards*(s: string, token: var string, until: string,
start = 0): int {.inline.} =
## Parses a token and stores it in ``token``. Returns
## the number of the parsed characters or 0 in case of an error. A token
## consists of any character that comes before the `until` token.
runnableExamples:
var myToken: string
doAssert parseUntil("Hello World", myToken, "Wor") == 6
doAssert myToken == "Hello "
doAssert parseUntil("Hello World", myToken, "Wor", 2) == 4
doAssert myToken == "llo "
var i = s.len
while i > 0:
if until.len > 0 and s[i] == until[until.len - 1]:
var u = 1
while i+u < s.len and u < until.len and s[i+u] == until[u]:
inc u
if u >= until.len: break
dec(i)
result = i-start
fastSubstr(s, token, start, result)
#token = substr(s, start, i-1)

44
src_v2/utils/printers.nim Normal file
View File

@@ -0,0 +1,44 @@
import std/[
options,
sequtils,
strformat,
strutils,
sugar,
]
const INDENT_SIZE* = 2;
func stringifyFields*(
xs: seq[tuple[
field: string,
value: string,
print: bool
]],
indent = 0,
): string =
xs
.filter(x => x.print)
.map(x => x.field & ": " & $x.value)
.join(",\n")
func stringifyBlock*(blockName: string, indent = 0, xs: varargs[string]): string =
let fieldIndent = indent + INDENT_SIZE
concat(
@[&"{blockName}("],
@xs.mapIt(it.indent(fieldIndent)),
@[")"],
)
.join("\n")
func stringifySeq*[T](xs: seq[T], stringifyFn: (T) -> string, indent = 0): string =
let fieldIndent = indent + INDENT_SIZE
@[
"@[",
xs
.mapIt(it.stringifyFn())
.join(",\n")
.indent(fieldIndent),
"]",
]
.join("\n")

60
src_v2/utils/str.nim Normal file
View File

@@ -0,0 +1,60 @@
import std/[
strutils,
math,
]
import fusion/matching
{.experimental: "caseStmtMacros".}
func prettyExpectedSet*(x: set[char]): string =
## Pretty print value for a set `x` of characters
case x:
of AllChars:
"AllChars {'\x00'..'\xFF'}"
of Digits:
"Digits {'0'..'9'}"
of HexDigits:
"HexDigits {'0'..'9', 'A'..'F', 'a'..'f'}"
of Letters:
"Letters {'A'..'Z', 'a'..'z'}"
of Newlines:
"Newlines {'\r', '\n'}"
of Whitespace:
"Whitespace {' ', '\t', '\v', '\r', '\n', '\f'}"
else:
$x
func indentAfterNewline*(str: string, count: int): string =
## Indent lines following the first line of `str` by `count`.
## Useful for indenting nested keys of stringify functions.
var strDup = str.indent(count)
strDup.delete(0..count - 1)
strDup
proc safeDelete*(str: string, slice: Slice[int]): string =
## Deletes the items `str[slice]`, ignoring elements out of range.
if slice.a > str.len - 1:
str
else:
let fromIndex = clamp(slice.a, 0..str.len)
let toIndex = clamp(slice.b, 0..str.len - 1)
var strDup = str
strDup.delete(fromIndex..toIndex)
strDup
func findAndDelete*(str: string, chars: set[char], start = 0, last = str.len - 1): string =
## Find the next instance of `chars` from `start`.
## When found delete characters until `last`.
# Prevent passing negative numbers (e.g.: initial parser)
if start >= 0 and last >= 0:
let startChar = str.find(chars, start, last)
if startChar == -1:
str
else:
str.safeDelete(startChar..last)
else: str
func deleteAfterNewline*(str: string, start = 0): string =
## Delete string after next Newline from `start`.
findAndDelete(str, Newlines, start)