From ecb3bdd8eef8161180967fd2a63359d0510d9aa0 Mon Sep 17 00:00:00 2001 From: alex-s168 <63254202+alex-s168@users.noreply.github.com> Date: Wed, 28 Feb 2024 21:35:08 +0100 Subject: [PATCH] aaaaaa --- .gitignore | 4 +- build.gradle.kts | 13 +- gradlew | 41 ++-- gradlew.bat | 15 +- .../kotlin/me/alex_s168/kreflect/Clazz.kt | 195 +++++++++++++++--- src/main/kotlin/me/alex_s168/kreflect/Fnp.kt | 27 ++- 6 files changed, 237 insertions(+), 58 deletions(-) mode change 100644 => 100755 gradlew diff --git a/.gitignore b/.gitignore index b63da45..a6638d5 100644 --- a/.gitignore +++ b/.gitignore @@ -39,4 +39,6 @@ bin/ .vscode/ ### Mac OS ### -.DS_Store \ No newline at end of file +.DS_Store + +kls_database.db \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 4254c05..8e78f45 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,10 +3,6 @@ plugins { application } -application { - mainClass = "me.alex_s168.kreflect.TermKt" -} - group = "me.alex_s168" version = "0.1" @@ -23,6 +19,11 @@ dependencies { tasks.test { useJUnitPlatform() } + kotlin { - jvmToolchain(17) -} \ No newline at end of file + jvmToolchain(11) +} + +application { + mainClass.set("me.alex_s168.kreflect.FnpKt") +} diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 index 1b6c787..1aa94a4 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ @@ -205,6 +214,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index 107acd3..93e3f59 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/src/main/kotlin/me/alex_s168/kreflect/Clazz.kt b/src/main/kotlin/me/alex_s168/kreflect/Clazz.kt index dd64717..78dfa24 100644 --- a/src/main/kotlin/me/alex_s168/kreflect/Clazz.kt +++ b/src/main/kotlin/me/alex_s168/kreflect/Clazz.kt @@ -1,11 +1,8 @@ package me.alex_s168.kreflect -import kotlinx.io.Buffer -import kotlinx.io.RawSource +import kotlinx.io.* import kotlinx.io.files.Path import kotlinx.io.files.SystemFileSystem -import kotlinx.io.readByteArray -import kotlinx.io.readTo import kotlin.math.max import kotlin.math.min @@ -13,13 +10,27 @@ interface IndexableSequence: Sequence { operator fun get(index: Int): T } -fun lazySequence(vararg init: Pair, f: (Int, (Int) -> T) -> T): IndexableSequence = +data class Obj(val v: T) + +data class MutObj(val v: T) + +fun lazySequence(vararg init: Pair, default: Obj?, f: (Int, (Int) -> T) -> T): IndexableSequence = object : IndexableSequence { val map = mutableMapOf(*init) + var current: Int? = null + fun comp(iIn: Int): T { val i = max(0, iIn) - return map[i] ?: f(i, ::comp).also { map[i] = it } + if (current == i) + return (default ?: throw Exception("recursion detected")).v + return map[i] ?: let { + current = i + val res = f(i, ::comp) + map[i] = res + current = null + res + } } override fun get(index: Int) = comp(index) @@ -35,6 +46,90 @@ fun lazySequence(vararg init: Pair, f: (Int, (Int) -> T) -> T): Inde } } +fun easySequence(vararg init: Pair, f: (Int, (Int) -> T?) -> T?): Sequence = + lazySequence(*init, default = Obj(null)) { i, ff -> + f(i) { index -> + var indexC = index + var v: T? = null + while (indexC > 0 && v == null) + v = ff(indexC --) + v + } + } + +fun Sequence.easyMappingSequence(vararg init: Pair, f: (Int, (Int) -> T?, (Int) -> I) -> T?): Sequence { + val indexable = this.asIndexable() + return easySequence(*init) { i, ff -> + f(i, ff, indexable::get) + }.limitBy(indexable) + .removeNull() +} + +fun IndexableSequence.modifier(mod: (Sequence) -> Sequence) = + object : IndexableSequence { + val other = mod(this@modifier) + + override fun iterator(): Iterator = + other.iterator() + + override fun get(index: Int): T = + this@modifier[index] + } + +fun Sequence.removeNull(): Sequence = + mapNotNull { it } + +fun IndexableSequence.removeNull(): IndexableSequence = + modifier { it.removeNull() } + +fun Sequence.limitBy(other: Sequence): Sequence = + object : Sequence { + override fun iterator(): Iterator = + object : Iterator { + val s = this@limitBy.iterator() + val o = other.iterator() + + override fun hasNext(): Boolean = + o.hasNext() && s.hasNext() + + override fun next(): A = + s.next().also { o.next() } + } + } + +fun IndexableSequence.limitBy(other: Sequence): IndexableSequence = + modifier { it.limitBy(other) } + +fun Sequence.asIndexable(): IndexableSequence { + if (this is IndexableSequence) + return this + + return object : IndexableSequence { + val iter = this@asIndexable.iterator() + val values = mutableListOf() + + override fun get(index: Int): T { + if (index >= values.size) { + repeat(index + 1 - values.size) { + values.add(iter.next()) + } + } + return values[index] + } + + override fun iterator(): Iterator = + object : Iterator { + var i = 0 + + override fun hasNext(): Boolean = + i < values.size || iter.hasNext() + + override fun next(): T = + get(i ++) + } + } +} + typealias Operator = (I) -> O fun caching(tiedGet: () -> T, calc: (T) -> O) = object : Lazy { @@ -191,6 +286,9 @@ val Iterable.contents get() = val Sequence.contents get() = Contents(this.asIterable()) +val Array.contents get() = + Contents(this.asIterable()) + fun Sequence.map(chain: OperationChain): Sequence = chain.processAll(this) @@ -387,6 +485,18 @@ Note: If we call f for any number below 0, it will call f(0) instead. TODO # Contents +TODO + +# Monads +TODO + +# Easy Sequence +TODO + +# Easy Mapping Sequence +TODO + +# Obj and MutObj TODO */ @@ -409,31 +519,30 @@ fun Monad.print() = fun Monad.asPath() = bind { Path(it) } -fun ByteBatchSequence.stringify(batch: Int): Sequence { +fun ByteBatchSequence.stringify(batch: Int = 64): Sequence { val iter = iterator() - return sequence { + return generateSequence { if (iter.hasNext()) - yield(iter.nextBytes(batch).decodeToString()) + iter.nextBytes(batch).decodeToString() + else null } } fun (() -> RawSource).readerSequence(): ByteBatchSequence = object : ByteBatchSequence { inner class Iter: ByteBatchIterator { - val src = this@readerSequence() - val buffer = Buffer() + val buffered = this@readerSequence().buffered() override fun nextBytes(limit: Int): ByteArray { - src.readAtMostTo(buffer, limit - buffer.size) - return buffer.readByteArray() + val out = ByteArray(limit) + var i = 0 + while (!(buffered.exhausted() || i == limit - 1)) + out[i ++] = buffered.readByte() + return out.sliceArray(0..i) } - override fun nextBytes(dest: ByteArray): Int { - src.readAtMostTo(buffer, max(0, dest.size - buffer.size)) - val c = buffer.size - buffer.readTo(dest) - return min(c.toInt(), dest.size) - } + override fun nextBytes(dest: ByteArray): Int = + nextBytes(dest.size).also { it.copyInto(dest) }.size override fun next(limit: Int): List = nextBytes(limit).toList() @@ -453,17 +562,55 @@ fun (() -> RawSource).readerSequence(): ByteBatchSequence = } override fun next(): Byte = - nextBytes(1).first() + buffered.readByte() - override fun hasNext(): Boolean { - return src.readAtMostTo(buffer, 1) > 0 - } + override fun hasNext(): Boolean = + !buffered.exhausted() } override fun iterator(): ByteBatchIterator = Iter() } +fun Iterable>.rewrap(): Monad> = + Monad { + val iter = this@rewrap.iterator() + generateSequence { + if (iter.hasNext())iter.next().impure() + else null + } + } + +fun Sequence>.rewrap(): Monad> = + Monad { + val iter = this@rewrap.iterator() + sequence { if (iter.hasNext()) yield(iter.next().impure()) } + } + +fun Sequence>.combine(): Monad = + Monad { this@combine.forEach { it.impure() } } + +fun Iterable>.combineIter(): Monad = + Monad { this@combineIter.forEach { it.impure() } } + +fun Monad>>.combine(): Monad = + Monad { this@combine.impure().forEach { it.impure() } } + +fun Monad>>.combineIter(): Monad = + Monad { this@combineIter.impure().forEach { it.impure() } } + +fun Monad>.mapIter(transform: (T) -> R): Monad> = + bind { it.map { x -> transform(x) } } + +fun Monad>.map(transform: (T) -> R): Monad> = + bind { it.map { x -> transform(x) } } + +fun Monad>>.flatten(): Monad> = + bind { it.flatten() } + +fun Monad.stringify(batch: Int = 64): Monad> = + bind { it.stringify(batch) } + fun Monad.read() = bind { p -> { SystemFileSystem.source(p) }.readerSequence() } @@ -477,4 +624,4 @@ fun main() { .map(String::reversed) .finalize() println(chain.process(120).contents) -}*/ \ No newline at end of file +}*/ diff --git a/src/main/kotlin/me/alex_s168/kreflect/Fnp.kt b/src/main/kotlin/me/alex_s168/kreflect/Fnp.kt index 6d4eb81..d9e9511 100644 --- a/src/main/kotlin/me/alex_s168/kreflect/Fnp.kt +++ b/src/main/kotlin/me/alex_s168/kreflect/Fnp.kt @@ -1,16 +1,27 @@ package me.alex_s168.kreflect -import kotlinx.io.files.Path - -fun main() { - +fun main(args: Array) { + // pureCat(args) + // .impure() + val inp = sequenceOf("AAA", "BBB", "AAA", "AAA", "AAA", "BBB") + val out = inp.easyMappingSequence { i, s, m -> + if (s(i-1) == m(i)) null + else m(i) + } + println(out.contents) } -fun pureMain(args: Array): Monad = - args.map { +fun pureCat(args: Array): Monad = + args + .ifEmpty { arrayOf("-") } + .map { if (it == "-") readIn() else unit(it) .asPath() .read() - .bind { it.stringify(64) } - } \ No newline at end of file + .stringify() + } + .rewrap() + .flatten() + .map { unit(it).print() } + .combine() \ No newline at end of file