diff --git a/README.md b/README.md index fc2fe65..4dcaf68 100644 --- a/README.md +++ b/README.md @@ -1 +1,6 @@ -# strings \ No newline at end of file +# A Python FFI provider for purescript-strings +Providing FFI files for https://github.com/purescript/purescript-strings + +Available mirrors: + +https://github.com/purescript-python/purescript-python-ffi-index diff --git a/python-ffi/Data/String/CodePoints.py b/python-ffi/Data/String/CodePoints.py new file mode 100644 index 0000000..3148580 --- /dev/null +++ b/python-ffi/Data/String/CodePoints.py @@ -0,0 +1,73 @@ +def _unsafeCodePointAt0(fallback): + def ap(s): + return ord(s[0]) + + return ap + + +def _codePointAtImpl(fallback, just, nothing, unsafeCodePointAt0, index, s): + length = len(s) + if index < 0 or index >= length: + return nothing + else: + return just(unsafeCodePointAt0(s[index])) + + +def _codePointAt(fallback): + return lambda just: lambda nothing: lambda unsafeCodePointAt0: lambda index: lambda s: _codePointAtImpl( + fallback, just, nothing, unsafeCodePointAt0, index, s + ) + + +def _codePrefixImpl(fallback, unsafeCodePointAt0, pred, s): + cpCount = 0 + for x in s: + cp = unsafeCodePointAt0(x) + if not pred(cp): + return cpCount + else: + cpCount += 1 + return cpCount + + +def _fromCodePointArray(singleton): + def ap(cps): + return "".join(map(_singleton, cps)) + + return ap + + +def _singleton(fallback): + return chr + + +def _take(fallback): + def ap(n): + return lambda s: s[:n] + + return ap + + +def _toCodePointArray(fallback): + def ap(unsafeCodePointAt0): + return lambda s: list(map(unsafeCodePointAt0, s)) + + return ap + + +def _countPrefix(fallback): + def unsafeCodePointAt0_(unsafeCodePointAt0): + def pred_(pred): + def str_(s): + count = 0 + for x in s: + if not pred(x): + return count + else: + count += 1 + + return str_ + + return pred_ + + return unsafeCodePointAt0_ diff --git a/python-ffi/Data/String/CodeUnits.py b/python-ffi/Data/String/CodeUnits.py new file mode 100644 index 0000000..328c749 --- /dev/null +++ b/python-ffi/Data/String/CodeUnits.py @@ -0,0 +1,121 @@ +def fromCharArray(a): + return "".join(a) + + +def toCharArray(s): + return list(s) + + +def singleton(c): + return c + + +def _charAt(just): + def nothing_(nothing): + def i_(i): + def s_(s): + if i >= 0 and i < len(s): + return just(s[i]) + else: + return nothing + + return s_ + + return i_ + + return nothing_ + + +def _toChar(just): + return lambda nothing: lambda s: just(s) if len(s) == 1 else nothing + + +length = len + + +def countPrefix(p): + def ap(s): + i = 0 + while i < len(s) and p(s[i]): + i += 1 + return i + + return ap + + +def _indexOfImpl(just, nothing, x, s): + i = s.find(x) + return nothing if i == -1 else just(i) + + +def _indexOf(just): + return lambda nothing: lambda x: lambda s: _indexOfImpl(just, nothing, x, s) + + +def _indexOfPImpl(just, nothing, x, startAt, s: str): + i = s.find(x, startAt) + return nothing if i == -1 else just(i) + + +def _indexOfStartingAtImpl(just, nothing, x, startAt, s): + if startAt < 0 or startAt > len(s): + return nothing + i = s.find(x, startAt) + return nothing if i == -1 else just(i) + + +globals()[ + "_indexOf'" +] = lambda just: lambda nothing: lambda x: lambda startAt: lambda s: _indexOfStartingAtImpl( + just, nothing, x, startAt, s +) + + +def _lastIndexOfImpl(just, nothing, x, s: str): + i = s.rfind(x) + return nothing if i == -1 else just(i) + + +def _lastIndexOfPImpl(just, nothing, x, startAt, s: str): + i = s.rfind(x, startAt) + return nothing if i == -1 else just(i) + + +def _lastIndexOf(just): + return lambda nothing: lambda x: lambda s: _lastIndexOfImpl(just, nothing, x, s) + + +def _lastIndexOfStartAtImpl(just, nothing, x, startAt, s): + if startAt < 0 or startAt > len(s): + return nothing + i = s.rfind(x, 0, startAt + len(x)) + return nothing if i == -1 else just(i) + + +globals()[ + "_lastIndexOf'" +] = lambda just: lambda nothing: lambda x: lambda startAt: lambda s: _lastIndexOfStartAtImpl( + just, nothing, x, startAt, s +) + + +def _lastIndexOfStartingAt(just): + return lambda nothing: lambda x: lambda startAt: lambda s: _lastIndexOfStartAtImpl( + just, nothing, x, startAt, s + ) + + +def take(n: int): + return lambda s: s[: max(n, 0)] + + +def drop(n: int): + return lambda s: s[max(n, 0) :] + + +def _slice(b): + return lambda e: lambda s: s[b:e] + + +def splitAt(i): + return lambda s: {"before": s[: max(i, 0)], "after": s[max(i, 0) :]} diff --git a/python-ffi/Data/String/Common.py b/python-ffi/Data/String/Common.py new file mode 100644 index 0000000..d760078 --- /dev/null +++ b/python-ffi/Data/String/Common.py @@ -0,0 +1,48 @@ +def _localeCompareImpl(lt, eq, gt, s1, s2): + # TODO: write correct localeCompare + + # var result = s1.localeCompare(s2); + # return result < 0 ? lt : result > 0 ? gt : eq; + if s1 == s2: + return eq + if s1 < s2: + return lt + if s1 > s2: + return gt + + +def _localeCompare(lt): + return lambda eq: lambda gt: lambda s1: lambda s2: _localeCompareImpl( + lt, eq, gt, s1, s2 + ) + + +def replace(s1): + return lambda s2: lambda s3: s3.replace(s1, s2, 1) + + +def replaceAll(s1): + return lambda s2: lambda s3: s3.replace(s1, s2) + + +def split(sep): + if len(sep) == 0: + return lambda s: list(s) + else: + return lambda s: s.split(sep) + + +def toLower(s): + return s.lower() + + +def toUpper(s): + return s.upper() + + +def trim(s): + return s.strip() + + +def joinWith(s): + return lambda xs: s.join(xs) diff --git a/python-ffi/Data/String/Regex.py b/python-ffi/Data/String/Regex.py new file mode 100644 index 0000000..4646046 --- /dev/null +++ b/python-ffi/Data/String/Regex.py @@ -0,0 +1,110 @@ +import re + + +def showRegexImpl(r): + return "" + r + + +globals()["showRegex'"] = showRegexImpl + + +def regexImpl(left): + raise NotImplementedError("FFI Not implemented. Data.String.Regex.regexImpl") + + +# return function (right) { +# return function (s1) { +# return function (s2) { +# try { +# return right(new RegExp(s1, s2)); +# } catch (e) { +# return left(e.message); +# } + +globals()["regex'"] = regexImpl + + +def source(r): + return r["source"] + + +def flagsImpl(r): + return { + "multiline": r["multiline"], + "ignoreCase": r["ignoreCase"], + "global": r["global"], + "sticky": bool(r["sticky"]), + "unicode": bool(r["unicode"]), + } + + +globals()["flags'"] = regexImpl + + +def test(r): + raise NotImplementedError("FFI Not implemented. Data.String.Regex.test") + + +# return function (s) { +# var lastIndex = r.lastIndex; +# var result = r.test(s); +# r.lastIndex = lastIndex; +# return result; + + +def _matchImpl(just, nothing, r, s): + m = re.match(r, s) + if m is None: + return nothing + else: + return just(m) + + +_match = lambda j: lambda n: lambda r: lambda s: _matchImpl(j, n, r, s) + + +# return function (nothing) { +# return function (r) { +# return function (s) { +# var m = s.match(r); +# if (m == null || m.length === 0) { +# return nothing; +# } else { +# for (var i = 0; i < m.length; i++) { +# m[i] = m[i] == null ? nothing : just(m[i]); +# } +# return just(m); +# } + + +def replace(r): + return lambda s1: lambda s2: s2.replace(s1, 1) + + +def replaceBy(r): + raise NotImplementedError("FFI Not implemented. Data.String.Regex.replaceBy") + + +globals()["replace'"] = replaceBy + +# return function (f) { +# return function (s2) { +# return s2.replace(r, function (match) { +# return f(match)(Array.prototype.splice.call(arguments, 1, arguments.length - 3)); +# }); + + +def _searchImpl(just, nothing, r, s): + m = re.search(r, s) + if m: + return just(m.start()) + else: + return nothing + + +def _search(just): + return lambda nothing: lambda r: lambda s: _searchImpl(just, nothing, r, s) + + +def split(r): + return lambda s: s.split(r) diff --git a/python-ffi/Data/String/Unsafe.py b/python-ffi/Data/String/Unsafe.py new file mode 100644 index 0000000..455d7e8 --- /dev/null +++ b/python-ffi/Data/String/Unsafe.py @@ -0,0 +1,14 @@ +def charAt(i): + def ap(s): + if i >= 0 and i < len(s): + return s[i] + + raise IndexError("Data.String.Unsafe.charAt: Invalid index.") + + return ap + + +def char(s): + if len(s) == 1: + return s[0] + raise ValueError("Data.String.Unsafe.char: Expected string of length 1.")