diff --git a/build.gradle.kts b/build.gradle.kts index cfb09b7..e58c167 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,9 +2,9 @@ plugins { kotlin("jvm") `java-library` `maven-publish` + `signing` id("io.github.gradle-nexus.publish-plugin") version "1.1.0" id("org.jetbrains.dokka") version "1.8.10" - id("signing") } nexusPublishing { @@ -110,46 +110,42 @@ subprojects { } publishing { - publications { - create("mavenJava") { - from(components["kotlin"]) - artifactId = varintName - - artifact(tasks["javadocJar"]) - artifact(tasks["sourcesJar"]) - - pom { - name.set("decomat") - description.set("DecoMat - Deconstructive Pattern Matching for Kotlin") - url.set("https://github.com/exoquery/decomat") - - licenses { - license { - name.set("The Apache Software License, Version 2.0") - url.set("http://www.apache.org/licenses/LICENSE-2.0.txt") - distribution.set("repo") - } + publications.withType { + pom { + name.set("decomat") + description.set("DecoMat - Deconstructive Pattern Matching for Kotlin") + url.set("https://github.com/deusaquilus/pprint-kotlin") + + licenses { + license { + name.set("The Apache Software License, Version 2.0") + url.set("http://www.apache.org/licenses/LICENSE-2.0.txt") + distribution.set("repo") } + } - developers { - developer { - name.set("Alexander Ioffe") - email.set("deusaquilus@gmail.com") - organization.set("github") - organizationUrl.set("http://www.github.com") - } + developers { + developer { + name.set("Alexander Ioffe") + email.set("deusaquilus@gmail.com") + organization.set("github") + organizationUrl.set("http://www.github.com") } + } - scm { - url.set("https://github.com/exoquery/decomat/tree/main") - connection.set("scm:git:git://github.com/ExoQuery/DecoMat.git") - developerConnection.set("scm:git:ssh://github.com:ExoQuery/DecoMat.git") - } + scm { + url.set("https://github.com/exoquery/decomat/tree/main") + connection.set("scm:git:git://github.com/ExoQuery/DecoMat.git") + developerConnection.set("scm:git:ssh://github.com:ExoQuery/DecoMat.git") } } } } + tasks.withType { + onlyIf { !project.hasProperty("nosign") } + } + // Check the 'skipSigning' project property if (!project.hasProperty("nosign")) { // If 'skipSigning' is not present, apply the signing plugin and configure it @@ -158,7 +154,7 @@ subprojects { signing { // use the properties passed as command line args // -Psigning.keyId=${{secrets.SIGNING_KEY_ID}} -Psigning.password=${{secrets.SIGNING_PASSWORD}} -Psigning.secretKeyRingFile=$(echo ~/.gradle/secring.gpg) - sign(publishing.publications["mavenJava"]) + sign(publishing.publications) } } } diff --git a/decomat-core/build.gradle.kts b/decomat-core/build.gradle.kts index 1db06d5..2f9e074 100644 --- a/decomat-core/build.gradle.kts +++ b/decomat-core/build.gradle.kts @@ -30,6 +30,12 @@ plugins { sourceSets["main"].kotlin.srcDir(file("build/templates")) +/* +Note that the error "could not list directory ...git/DecoMat/decomat-core/src/templates +is actually misleading. The actual error will be something else in the freemarker template +but for some reason a higher level task can't list the directory of the ftl building fails. +In order to get the real error add --stacktrace to the './gradlew runFreemarkerTemplate' task + */ tasks.register("template_base", TemplateTask::class) { data = mutableMapOf("key" to "value") from("src/templates/") diff --git a/decomat-core/src/main/kotlin/io/decomat/CustomPattern.kt b/decomat-core/src/main/kotlin/io/decomat/CustomPattern.kt index 491cc2c..2370b4b 100644 --- a/decomat-core/src/main/kotlin/io/decomat/CustomPattern.kt +++ b/decomat-core/src/main/kotlin/io/decomat/CustomPattern.kt @@ -13,13 +13,6 @@ inline fun , P2 : Pattern, R1, R2, reified R> customPattern noinline matchName: (R) -> Components2? ): Pattern2 = CustomPattern2(nested1, nested2, matchName, Typed()) -inline fun , P2 : Pattern, P3 : Pattern, R1, R2, R3, reified R> customPattern3( - nested1: P1, - nested2: P2, - nested3: P3, - noinline matchName: (R) -> Components3? -): Pattern3 = CustomPattern3(nested1, nested2, nested3, matchName, Typed()) - class CustomPattern1, R1, R>( val innerMatch: P1, val match: (R) -> Components1?, @@ -66,27 +59,28 @@ class CustomPattern2, P2: Pattern, R1, R2, R>( } -class CustomPattern3, P2: Pattern, P3: Pattern, R1, R2, R3, R>( + +class CustomPattern2M, M, P2: Pattern, R1, R2, R>( val innerMatchA: P1, val innerMatchB: P2, - val innerMatchC: P3, - val match: (R) -> Components3?, + val match: (R) -> Components2M?, val tpe: Typed -): Pattern3(innerMatchA, innerMatchB, innerMatchC, tpe) { +): Pattern2M(innerMatchA, innerMatchB, tpe) { override fun matches(comps: ProductClass): Boolean = match(comps.value).let { it != null && innerMatchA.matchesAny(it.a as Any) && - innerMatchB.matchesAny(it.b as Any) && - innerMatchC.matchesAny(it.c as Any) + innerMatchB.matchesAny(it.b as Any) } - override fun divideIntoComponents(instance: ProductClass): Components3 = + override fun divideInto3Components(instance: ProductClass): Components2M = match(instance.value) ?: failToDivide(instance) - override fun divideIntoComponentsAny(instance: kotlin.Any): Components3 = + override fun divideInto3ComponentsAny(instance: kotlin.Any): Components2M = if (isType(instance, tpe.type)) match(instance as R) ?: failToDivide(instance) else failToDivide(instance) } + + diff --git a/decomat-core/src/main/kotlin/io/decomat/Pattern.kt b/decomat-core/src/main/kotlin/io/decomat/Pattern.kt index c75bc39..48ccece 100644 --- a/decomat-core/src/main/kotlin/io/decomat/Pattern.kt +++ b/decomat-core/src/main/kotlin/io/decomat/Pattern.kt @@ -91,36 +91,3 @@ abstract class Pattern2, P2: Pattern, R1, R2, R>(val pattern else -> fail("must match properly") // todo refine message } } - -abstract class Pattern3, P2: Pattern, P3: Pattern, R1, R2, R3, R>(val pattern1: P1, val pattern2: P2, val pattern3: P3, override val typeR: Typed): - Pattern { - open override fun matches(comps: ProductClass) = - comps.value.isType(typeR) - && - when(val compsDef = comps.isIfHas()) { - is ProductClass3<*, *, *, *> -> - wrapNonComps(compsDef.a).let { pattern1.matches(it) } - && - wrapNonComps(compsDef.b).let { pattern2.matches(it) } - && - wrapNonComps(compsDef.c).let { pattern3.matches(it) } - else -> false - } - - open fun divideIntoComponentsAny(instance: kotlin.Any): Components3 = - when(instance) { - is HasProductClass<*> -> - divideIntoComponentsAny(instance.productComponents) - is ProductClass3<*, *, *, *> -> - if (!isType(instance.value, typeR.type)) fail("Invalid type of data") // todo refine message - else divideIntoComponents(instance as ProductClass) - else -> fail("Cannot divide $instance into components. It is not a Product2 class.") - } - - open fun divideIntoComponents(instance: ProductClass): Components3 = - when(val inst = instance.isIfHas()) { - is ProductClass3<*, *, *, *> -> - Components3(inst.a as R1, inst.b as R2, inst.c as R3) - else -> fail("must match properly") // todo refine message - } -} diff --git a/decomat-core/src/main/kotlin/io/decomat/PatternM.kt b/decomat-core/src/main/kotlin/io/decomat/PatternM.kt index b522f81..9a538c5 100644 --- a/decomat-core/src/main/kotlin/io/decomat/PatternM.kt +++ b/decomat-core/src/main/kotlin/io/decomat/PatternM.kt @@ -15,18 +15,22 @@ abstract class Pattern2M, M, P2: Pattern, R1, R2, R>(val pat else -> false } - // assumign the matches function already said 'false' if it doesn't match so at this point just throw an error - open fun divideIntoComponentsAny(instance: kotlin.Any): Components2M = + // use 3-component division in then then-functions for Pattern2M-family but + // use the 2-component division in the superclass of this in the Pattenr2M family + // (the fact that we do this allows us to reuse then thenXX methods for the Pattern2M family + // otherwise would would need to reimplement all of them for Pattern2M giving it the performance + // probem of Pattern3) + open fun divideInto3ComponentsAny(instance: kotlin.Any): Components2M = when(instance) { is HasProductClass<*> -> - divideIntoComponentsAny(instance.productComponents) + divideInto3ComponentsAny(instance.productComponents) is ProductClass2M<*, *, *, *> -> if (!isType(instance.value, typeR.type)) fail("Invalid type of data") // todo refine message - else divideIntoComponents(instance as ProductClass) + else divideInto3Components(instance as ProductClass) else -> fail("Cannot divide $instance into components. It is not a Product2 class.") } - open fun divideIntoComponents(instance: ProductClass): Components2M = + open fun divideInto3Components(instance: ProductClass): Components2M = when(val inst = instance.isIfHas()) { is ProductClass2M<*, *, *, *> -> // for FlatMap_M: ~Pattern2 R1 and R2 will be Query diff --git a/decomat-core/src/main/kotlin/io/decomat/ProductClass.kt b/decomat-core/src/main/kotlin/io/decomat/ProductClass.kt index 06084f1..4699826 100644 --- a/decomat-core/src/main/kotlin/io/decomat/ProductClass.kt +++ b/decomat-core/src/main/kotlin/io/decomat/ProductClass.kt @@ -87,5 +87,3 @@ data class Components1(val a: @UnsafeVariance A): Components data class Components2(val a: @UnsafeVariance A, val b: @UnsafeVariance B): Components data class Components2M(val a: @UnsafeVariance A, val m: @UnsafeVariance M, val b: @UnsafeVariance B): Components - -data class Components3(val a: @UnsafeVariance A, val b: @UnsafeVariance B, val c: @UnsafeVariance C): Components \ No newline at end of file diff --git a/decomat-core/src/main/kotlin/io/decomat/ThenM2P2.kt b/decomat-core/src/main/kotlin/io/decomat/ThenM2P2.kt index 845a98b..e6f775d 100644 --- a/decomat-core/src/main/kotlin/io/decomat/ThenM2P2.kt +++ b/decomat-core/src/main/kotlin/io/decomat/ThenM2P2.kt @@ -1,159 +1,159 @@ -package io.decomat - - -class ThenM0P2, P11: Pattern, R11, M1, P12: Pattern, R12, R1, P2: Pattern0, R2, R>( - override val pat: Pattern2, - override val check: (R) -> Boolean -): Stage, R> { - - inline fun useComponents(r: R, f: (Components2M, R2) -> O): O { - val (r1, r2) = pat.divideIntoComponentsAny(r as Any) - //skip - val (r11, m1, r12) = pat.pattern1.divideIntoComponentsAny(r1 as Any) - return f(Components2M(r11, m1, r12), r2) - } - - inline fun thenIf(crossinline f: (Components2M, R2) -> Boolean) = - ThenM0P2(pat) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } - - inline fun thenIfThis(crossinline f: R.(Components2M, R2) -> Boolean) = - ThenM0P2(pat) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } - - inline fun then(crossinline f: (Components2M, R2) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } - - inline fun thenThis(crossinline f: R.(Components2M, R2) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } -} - - - -class ThenM1P2, P11: Pattern, R11, M1, P12: Pattern, R12, R1, P2: Pattern1, P21: Pattern, R21, R2, R>( - override val pat: Pattern2, - override val check: (R) -> Boolean -): Stage, R> { - - inline fun useComponents(r: R, f: (Components2M, Components1) -> O): O { - val (r1, r2) = pat.divideIntoComponentsAny(r as Any) - //skip - val (r11, m1, r12) = pat.pattern1.divideIntoComponentsAny(r1 as Any) - val (r21) = pat.pattern2.divideIntoComponentsAny(r2 as Any) - return f(Components2M(r11, m1, r12), Components1(r21)) - } - - inline fun thenIf(crossinline f: (Components2M, Components1) -> Boolean) = - ThenM1P2(pat) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } - - inline fun thenIfThis(crossinline f: R.(Components2M, Components1) -> Boolean) = - ThenM1P2(pat) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } - - inline fun then(crossinline f: (Components2M, Components1) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } - - inline fun thenThis(crossinline f: R.(Components2M, Components1) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } -} - - - -class ThenM2P2, P11: Pattern, R11, M1, P12: Pattern, R12, R1, P2: Pattern2, P21: Pattern, R21, P22: Pattern, R22, R2, R>( - override val pat: Pattern2, - override val check: (R) -> Boolean -): Stage, R> { - - inline fun useComponents(r: R, f: (Components2M, Components2) -> O): O { - val (r1, r2) = pat.divideIntoComponentsAny(r as Any) - //skip - val (r11, m1, r12) = pat.pattern1.divideIntoComponentsAny(r1 as Any) - val (r21, r22) = pat.pattern2.divideIntoComponentsAny(r2 as Any) - return f(Components2M(r11, m1, r12), Components2(r21, r22)) - } - - inline fun thenIf(crossinline f: (Components2M, Components2) -> Boolean) = - ThenM2P2(pat) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } - - inline fun thenIfThis(crossinline f: R.(Components2M, Components2) -> Boolean) = - ThenM2P2(pat) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } - - inline fun then(crossinline f: (Components2M, Components2) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } - - inline fun thenThis(crossinline f: R.(Components2M, Components2) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } -} - - -class Then0MP2, R1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R>( - override val pat: Pattern2, - override val check: (R) -> Boolean -): Stage, R> { - - inline fun useComponents(r: R, f: (R1, Components2M) -> O): O { - val (r1, r2) = pat.divideIntoComponentsAny(r as Any) - //skip - return f(r1, pat.pattern2.divideIntoComponentsAny(r2 as Any)) - } - - inline fun thenIf(crossinline f: (R1, Components2M) -> Boolean) = - Then0MP2(pat) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } - - inline fun thenIfThis(crossinline f: R.(R1, Components2M) -> Boolean) = - Then0MP2(pat) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } - - inline fun then(crossinline f: (R1, Components2M) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } - - inline fun thenThis(crossinline f: R.(R1, Components2M) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } -} - - -class Then1MP2, P11: Pattern, R11, R1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R>( - override val pat: Pattern2, - override val check: (R) -> Boolean -): Stage, R> { - - inline fun useComponents(r: R, f: (Components1, Components2M) -> O): O { - val (r1, r2) = pat.divideIntoComponentsAny(r as Any) - //skip - return f(pat.pattern1.divideIntoComponentsAny(r1 as Any), pat.pattern2.divideIntoComponentsAny(r2 as Any)) - } - - inline fun thenIf(crossinline f: (Components1, Components2M) -> Boolean) = - Then1MP2(pat) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } - - inline fun thenIfThis(crossinline f: R.(Components1, Components2M) -> Boolean) = - Then1MP2(pat) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } - - inline fun then(crossinline f: (Components1, Components2M) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } - - inline fun thenThis(crossinline f: R.(Components1, Components2M) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } -} - - -class Then2MP2, P11: Pattern, R11, P12: Pattern, R12, R1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R>( - override val pat: Pattern2, - override val check: (R) -> Boolean -): Stage, R> { - - inline fun useComponents(r: R, f: (Components2, Components2M) -> O): O { - val (r1, r2) = pat.divideIntoComponentsAny(r as Any) - //skip - return f(pat.pattern1.divideIntoComponentsAny(r1 as Any), pat.pattern2.divideIntoComponentsAny(r2 as Any)) - } - - inline fun thenIf(crossinline f: (Components2, Components2M) -> Boolean) = - Then2MP2(pat) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } - - inline fun thenIfThis(crossinline f: R.(Components2, Components2M) -> Boolean) = - Then2MP2(pat) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } - - inline fun then(crossinline f: (Components2, Components2M) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } - - inline fun thenThis(crossinline f: R.(Components2, Components2M) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } -} - +//package io.decomat +// +// +//class ThenM0P2, P11: Pattern, R11, M1, P12: Pattern, R12, R1, P2: Pattern0, R2, R>( +// override val pat: Pattern2, +// override val check: (R) -> Boolean +//): Stage, R> { +// +// inline fun useComponents(r: R, f: (Components2M, R2) -> O): O { +// val (r1, r2) = pat.divideIntoComponentsAny(r as Any) +// //skip +// val (r11, m1, r12) = pat.pattern1.divideInto3ComponentsAny(r1 as Any) +// return f(Components2M(r11, m1, r12), r2) +// } +// +// inline fun thenIf(crossinline f: (Components2M, R2) -> Boolean) = +// ThenM0P2(pat) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } +// +// inline fun thenIfThis(crossinline f: R.(Components2M, R2) -> Boolean) = +// ThenM0P2(pat) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } +// +// inline fun then(crossinline f: (Components2M, R2) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } +// +// inline fun thenThis(crossinline f: R.(Components2M, R2) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } +//} +// +// +// +//class ThenM1P2, P11: Pattern, R11, M1, P12: Pattern, R12, R1, P2: Pattern1, P21: Pattern, R21, R2, R>( +// override val pat: Pattern2, +// override val check: (R) -> Boolean +//): Stage, R> { +// +// inline fun useComponents(r: R, f: (Components2M, Components1) -> O): O { +// val (r1, r2) = pat.divideIntoComponentsAny(r as Any) +// //skip +// val (r11, m1, r12) = pat.pattern1.divideInto3ComponentsAny(r1 as Any) +// val (r21) = pat.pattern2.divideIntoComponentsAny(r2 as Any) +// return f(Components2M(r11, m1, r12), Components1(r21)) +// } +// +// inline fun thenIf(crossinline f: (Components2M, Components1) -> Boolean) = +// ThenM1P2(pat) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } +// +// inline fun thenIfThis(crossinline f: R.(Components2M, Components1) -> Boolean) = +// ThenM1P2(pat) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } +// +// inline fun then(crossinline f: (Components2M, Components1) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } +// +// inline fun thenThis(crossinline f: R.(Components2M, Components1) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } +//} +// +// +// +//class ThenM2P2, P11: Pattern, R11, M1, P12: Pattern, R12, R1, P2: Pattern2, P21: Pattern, R21, P22: Pattern, R22, R2, R>( +// override val pat: Pattern2, +// override val check: (R) -> Boolean +//): Stage, R> { +// +// inline fun useComponents(r: R, f: (Components2M, Components2) -> O): O { +// val (r1, r2) = pat.divideIntoComponentsAny(r as Any) +// //skip +// val (r11, m1, r12) = pat.pattern1.divideInto3ComponentsAny(r1 as Any) +// val (r21, r22) = pat.pattern2.divideIntoComponentsAny(r2 as Any) +// return f(Components2M(r11, m1, r12), Components2(r21, r22)) +// } +// +// inline fun thenIf(crossinline f: (Components2M, Components2) -> Boolean) = +// ThenM2P2(pat) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } +// +// inline fun thenIfThis(crossinline f: R.(Components2M, Components2) -> Boolean) = +// ThenM2P2(pat) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } +// +// inline fun then(crossinline f: (Components2M, Components2) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } +// +// inline fun thenThis(crossinline f: R.(Components2M, Components2) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } +//} +// +// +//class Then0MP2, R1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R>( +// override val pat: Pattern2, +// override val check: (R) -> Boolean +//): Stage, R> { +// +// inline fun useComponents(r: R, f: (R1, Components2M) -> O): O { +// val (r1, r2) = pat.divideIntoComponentsAny(r as Any) +// //skip +// return f(r1, pat.pattern2.divideInto3ComponentsAny(r2 as Any)) +// } +// +// inline fun thenIf(crossinline f: (R1, Components2M) -> Boolean) = +// Then0MP2(pat) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } +// +// inline fun thenIfThis(crossinline f: R.(R1, Components2M) -> Boolean) = +// Then0MP2(pat) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } +// +// inline fun then(crossinline f: (R1, Components2M) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } +// +// inline fun thenThis(crossinline f: R.(R1, Components2M) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } +//} +// +// +//class Then1MP2, P11: Pattern, R11, R1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R>( +// override val pat: Pattern2, +// override val check: (R) -> Boolean +//): Stage, R> { +// +// inline fun useComponents(r: R, f: (Components1, Components2M) -> O): O { +// val (r1, r2) = pat.divideIntoComponentsAny(r as Any) +// //skip +// return f(pat.pattern1.divideIntoComponentsAny(r1 as Any), pat.pattern2.divideInto3ComponentsAny(r2 as Any)) +// } +// +// inline fun thenIf(crossinline f: (Components1, Components2M) -> Boolean) = +// Then1MP2(pat) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } +// +// inline fun thenIfThis(crossinline f: R.(Components1, Components2M) -> Boolean) = +// Then1MP2(pat) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } +// +// inline fun then(crossinline f: (Components1, Components2M) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } +// +// inline fun thenThis(crossinline f: R.(Components1, Components2M) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } +//} +// +// +//class Then2MP2, P11: Pattern, R11, P12: Pattern, R12, R1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R>( +// override val pat: Pattern2, +// override val check: (R) -> Boolean +//): Stage, R> { +// +// inline fun useComponents(r: R, f: (Components2, Components2M) -> O): O { +// val (r1, r2) = pat.divideIntoComponentsAny(r as Any) +// //skip +// return f(pat.pattern1.divideIntoComponentsAny(r1 as Any), pat.pattern2.divideInto3ComponentsAny(r2 as Any)) +// } +// +// inline fun thenIf(crossinline f: (Components2, Components2M) -> Boolean) = +// Then2MP2(pat) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } +// +// inline fun thenIfThis(crossinline f: R.(Components2, Components2M) -> Boolean) = +// Then2MP2(pat) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } +// +// inline fun then(crossinline f: (Components2, Components2M) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(c1, c2) }) } +// +// inline fun thenThis(crossinline f: R.(Components2, Components2M) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, c2 -> f(v, c1, c2) }) } +//} +// diff --git a/decomat-core/src/main/kotlin/io/decomat/ThenMP2M.kt b/decomat-core/src/main/kotlin/io/decomat/ThenMP2M.kt index 523d33a..11517bf 100644 --- a/decomat-core/src/main/kotlin/io/decomat/ThenMP2M.kt +++ b/decomat-core/src/main/kotlin/io/decomat/ThenMP2M.kt @@ -1,159 +1,164 @@ -package io.decomat - -fun , R1, M1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R> case(pat: Pattern2M) = Then0MP2M(pat, {true}) - -class Then0MP2M, R1, M1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R>( - override val pat: Pattern2M, - override val check: (R) -> Boolean -): Stage, R> { - - inline fun useComponents(r: R, f: (R1, M1, Components2M) -> O): O { - val (r1, m1, r2) = pat.divideIntoComponentsAny(r as Any) - //skip - val (r21, m2, r22) = pat.pattern2.divideIntoComponentsAny(r2 as Any) - return f(r1, m1, Components2M(r21, m2, r22)) - } - inline fun thenIf(crossinline f: (R1, M1, Components2M) -> Boolean) = - Then0MP2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } - - inline fun thenIfThis(crossinline f: R.(R1, M1, Components2M) -> Boolean) = - Then0MP2M(pat) { v -> useComponents(v, { c1, m1, c2 -> f(v, c1, m1, c2) }) } - - inline fun then(crossinline f: (R1, M1, Components2M) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } - - inline fun thenThis(crossinline f: R.(R1, M1, Components2M) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } -} - -fun , P11: Pattern, R11, R1, M1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R> case(pat: Pattern2M) = Then1MP2M(pat, {true}) - -class Then1MP2M, P11: Pattern, R11, R1, M1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R>( - override val pat: Pattern2M, - override val check: (R) -> Boolean -): Stage, R> { - - inline fun useComponents(r: R, f: (Components1, M1, Components2M) -> O): O { - val (r1, m1, r2) = pat.divideIntoComponentsAny(r as Any) - //skip - val (r11) = pat.pattern1.divideIntoComponentsAny(r1 as Any) - val (r21, m2, r22) = pat.pattern2.divideIntoComponentsAny(r2 as Any) - return f(Components1(r11), m1, Components2M(r21, m2, r22)) - } - - inline fun thenIf(crossinline f: (Components1, M1, Components2M) -> Boolean) = - Then1MP2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } - - inline fun thenIfThis(crossinline f: R.(Components1, M1, Components2M) -> Boolean) = - Then1MP2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } - - inline fun then(crossinline f: (Components1, M1, Components2M) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } -} - -fun , P11: Pattern, R11, P12: Pattern, R12, R1, M1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R> case(pat: Pattern2M) = Then2MP2M(pat, {true}) - -class Then2MP2M, P11: Pattern, R11, P12: Pattern, R12, R1, M1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R>( - override val pat: Pattern2M, - override val check: (R) -> Boolean -): Stage, R> { - - inline fun useComponents(r: R, f: (Components2, M1, Components2M) -> O): O { - val (r1, m1, r2) = pat.divideIntoComponentsAny(r as Any) - //skip - val (r11, r12) = pat.pattern1.divideIntoComponentsAny(r1 as Any) - val (r21, m2, r22) = pat.pattern2.divideIntoComponentsAny(r2 as Any) - return f(Components2(r11, r12), m1, Components2M(r21, m2, r22)) - } - - inline fun thenIf(crossinline f: (Components2, M1, Components2M) -> Boolean) = - Then2MP2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } - - inline fun thenIfThis(crossinline f: R.(Components2, M1, Components2M) -> Boolean) = - Then2MP2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } - - inline fun then(crossinline f: (Components2, M1, Components2M) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } - - inline fun thenThis(crossinline f: R.(Components2, M1, Components2M) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } -} - - - -fun , P11: Pattern, R11, M1, P12: Pattern, R12, R1, P2: Pattern0, R2, M2, R> case(pat: Pattern2M) = ThenM0P2M(pat, {true}) - -class ThenM0P2M, P11: Pattern, R11, M1, P12: Pattern, R12, R1, P2: Pattern0, R2, M2, R>( - override val pat: Pattern2M, - override val check: (R) -> Boolean -): Stage, R> { - - inline fun useComponents(r: R, f: (Components2M, M2, R2) -> O): O { - val (r1, m2, r2) = pat.divideIntoComponentsAny(r as Any) - //skip - val (r11, m1, r12) = pat.pattern1.divideIntoComponentsAny(r1 as Any) - return f(Components2M(r11, m1, r12), m2, r2) - } - inline fun thenIf(crossinline f: (Components2M, M2, R2) -> Boolean) = - ThenM0P2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } - - inline fun thenIfThis(crossinline f: R.(Components2M, M2, R2) -> Boolean) = - ThenM0P2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } - - inline fun then(crossinline f: (Components2M, M2, R2) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } - - inline fun thenThis(crossinline f: R.(Components2M, M2, R2) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } -} - - -fun , P11: Pattern, R11, P12: Pattern, R12, R1, P2: Pattern1, P21: Pattern, R21, R2, M2, R> case(pat: Pattern2M) = ThenM1P2M(pat, {true}) - -class ThenM1P2M, P11: Pattern, R11, M1, P12: Pattern, R12, R1, P2: Pattern1, P21: Pattern, R21, R2, M2, R>( - override val pat: Pattern2M, - override val check: (R) -> Boolean -): Stage, R> { - - inline fun useComponents(r: R, f: (Components2M, M2, Components1) -> O): O { - val (r1, m2, r2) = pat.divideIntoComponentsAny(r as Any) - //skip - val (r11, m1, r12) = pat.pattern1.divideIntoComponentsAny(r1 as Any) - val (r21) = pat.pattern2.divideIntoComponentsAny(r2 as Any) - return f(Components2M(r11, m1, r12), m2, Components1(r21)) - } - inline fun thenIf(crossinline f: (Components2M, M2, Components1) -> Boolean) = - ThenM1P2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } - - inline fun thenIfThis(crossinline f: R.(Components2M, M2, Components1) -> Boolean) = - ThenM1P2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } - - inline fun then(crossinline f: (Components2M, M2, Components1) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } -} - -class ThenM2P2M, P11: Pattern, R11, M1, P12: Pattern, R12, R1, P2: Pattern2, P21: Pattern, R21, P22: Pattern, R22, R2, M2, R>( - override val pat: Pattern2M, - override val check: (R) -> Boolean -): Stage, R> { - - inline fun useComponents(r: R, f: (Components2M, M2, Components2) -> O): O { - val (r1, m2, r2) = pat.divideIntoComponentsAny(r as Any) - //skip - val (r11, m1, r12) = pat.pattern1.divideIntoComponentsAny(r1 as Any) - val (r21, r22) = pat.pattern2.divideIntoComponentsAny(r2 as Any) - return f(Components2M(r11, m1, r12), m2, Components2(r21, r22)) - } - - inline fun thenIf(crossinline f: (Components2M, M2, Components2) -> Boolean) = - ThenM2P2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } - - inline fun thenIfThis(crossinline f: R.(Components2M, M2, Components2) -> Boolean) = - ThenM2P2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } - - inline fun then(crossinline f: (Components2M, M2, Components2) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } - - inline fun thenThis(crossinline f: R.(Components2M, M2, Components2) -> O) = - StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } -} +//package io.decomat +// +//fun , R1, M1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R> case(pat: Pattern2M) = Then0MP2M(pat, {true}) +// +//// This family of functions defines only usages of Pattern2M inside of other Pattern2M instances +//// since Pattern2M extends Pattern2, we can delegate to Pattern2 for the ThenXX family of methods +//// (the fact that we do this allows us to reuse then thenXX methods for the Pattern2M family +//// otherwise would would need to reimplement all of them for Pattern2M giving it the performance +//// probem of Pattern3) +//class Then0MP2M, R1, M1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R>( +// override val pat: Pattern2M, +// override val check: (R) -> Boolean +//): Stage, R> { +// +// inline fun useComponents(r: R, f: (R1, M1, Components2M) -> O): O { +// val (r1, m1, r2) = pat.divideInto3ComponentsAny(r as Any) +// //skip +// val (r21, m2, r22) = pat.pattern2.divideInto3ComponentsAny(r2 as Any) +// return f(r1, m1, Components2M(r21, m2, r22)) +// } +// inline fun thenIf(crossinline f: (R1, M1, Components2M) -> Boolean) = +// Then0MP2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } +// +// inline fun thenIfThis(crossinline f: R.(R1, M1, Components2M) -> Boolean) = +// Then0MP2M(pat) { v -> useComponents(v, { c1, m1, c2 -> f(v, c1, m1, c2) }) } +// +// inline fun then(crossinline f: (R1, M1, Components2M) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } +// +// inline fun thenThis(crossinline f: R.(R1, M1, Components2M) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } +//} +// +//fun , P11: Pattern, R11, R1, M1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R> case(pat: Pattern2M) = Then1MP2M(pat, {true}) +// +//class Then1MP2M, P11: Pattern, R11, R1, M1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R>( +// override val pat: Pattern2M, +// override val check: (R) -> Boolean +//): Stage, R> { +// +// inline fun useComponents(r: R, f: (Components1, M1, Components2M) -> O): O { +// val (r1, m1, r2) = pat.divideInto3ComponentsAny(r as Any) +// //skip +// val (r11) = pat.pattern1.divideIntoComponentsAny(r1 as Any) +// val (r21, m2, r22) = pat.pattern2.divideInto3ComponentsAny(r2 as Any) +// return f(Components1(r11), m1, Components2M(r21, m2, r22)) +// } +// +// inline fun thenIf(crossinline f: (Components1, M1, Components2M) -> Boolean) = +// Then1MP2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } +// +// inline fun thenIfThis(crossinline f: R.(Components1, M1, Components2M) -> Boolean) = +// Then1MP2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } +// +// inline fun then(crossinline f: (Components1, M1, Components2M) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } +//} +// +//fun , P11: Pattern, R11, P12: Pattern, R12, R1, M1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R> case(pat: Pattern2M) = Then2MP2M(pat, {true}) +// +//class Then2MP2M, P11: Pattern, R11, P12: Pattern, R12, R1, M1, P2: Pattern2M, P21: Pattern, R21, M2, P22: Pattern, R22, R2, R>( +// override val pat: Pattern2M, +// override val check: (R) -> Boolean +//): Stage, R> { +// +// inline fun useComponents(r: R, f: (Components2, M1, Components2M) -> O): O { +// val (r1, m1, r2) = pat.divideInto3ComponentsAny(r as Any) +// //skip +// val (r11, r12) = pat.pattern1.divideIntoComponentsAny(r1 as Any) +// val (r21, m2, r22) = pat.pattern2.divideInto3ComponentsAny(r2 as Any) +// return f(Components2(r11, r12), m1, Components2M(r21, m2, r22)) +// } +// +// inline fun thenIf(crossinline f: (Components2, M1, Components2M) -> Boolean) = +// Then2MP2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } +// +// inline fun thenIfThis(crossinline f: R.(Components2, M1, Components2M) -> Boolean) = +// Then2MP2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } +// +// inline fun then(crossinline f: (Components2, M1, Components2M) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } +// +// inline fun thenThis(crossinline f: R.(Components2, M1, Components2M) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } +//} +// +// +// +//fun , P11: Pattern, R11, M1, P12: Pattern, R12, R1, P2: Pattern0, R2, M2, R> case(pat: Pattern2M) = ThenM0P2M(pat, {true}) +// +//class ThenM0P2M, P11: Pattern, R11, M1, P12: Pattern, R12, R1, P2: Pattern0, R2, M2, R>( +// override val pat: Pattern2M, +// override val check: (R) -> Boolean +//): Stage, R> { +// +// inline fun useComponents(r: R, f: (Components2M, M2, R2) -> O): O { +// val (r1, m2, r2) = pat.divideInto3ComponentsAny(r as Any) +// //skip +// val (r11, m1, r12) = pat.pattern1.divideInto3ComponentsAny(r1 as Any) +// return f(Components2M(r11, m1, r12), m2, r2) +// } +// inline fun thenIf(crossinline f: (Components2M, M2, R2) -> Boolean) = +// ThenM0P2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } +// +// inline fun thenIfThis(crossinline f: R.(Components2M, M2, R2) -> Boolean) = +// ThenM0P2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } +// +// inline fun then(crossinline f: (Components2M, M2, R2) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } +// +// inline fun thenThis(crossinline f: R.(Components2M, M2, R2) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } +//} +// +// +//fun , P11: Pattern, R11, P12: Pattern, R12, R1, P2: Pattern1, P21: Pattern, R21, R2, M2, R> case(pat: Pattern2M) = ThenM1P2M(pat, {true}) +// +//class ThenM1P2M, P11: Pattern, R11, M1, P12: Pattern, R12, R1, P2: Pattern1, P21: Pattern, R21, R2, M2, R>( +// override val pat: Pattern2M, +// override val check: (R) -> Boolean +//): Stage, R> { +// +// inline fun useComponents(r: R, f: (Components2M, M2, Components1) -> O): O { +// val (r1, m2, r2) = pat.divideInto3ComponentsAny(r as Any) +// //skip +// val (r11, m1, r12) = pat.pattern1.divideInto3ComponentsAny(r1 as Any) +// val (r21) = pat.pattern2.divideIntoComponentsAny(r2 as Any) +// return f(Components2M(r11, m1, r12), m2, Components1(r21)) +// } +// inline fun thenIf(crossinline f: (Components2M, M2, Components1) -> Boolean) = +// ThenM1P2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } +// +// inline fun thenIfThis(crossinline f: R.(Components2M, M2, Components1) -> Boolean) = +// ThenM1P2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } +// +// inline fun then(crossinline f: (Components2M, M2, Components1) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } +//} +// +//class ThenM2P2M, P11: Pattern, R11, M1, P12: Pattern, R12, R1, P2: Pattern2, P21: Pattern, R21, P22: Pattern, R22, R2, M2, R>( +// override val pat: Pattern2M, +// override val check: (R) -> Boolean +//): Stage, R> { +// +// inline fun useComponents(r: R, f: (Components2M, M2, Components2) -> O): O { +// val (r1, m2, r2) = pat.divideInto3ComponentsAny(r as Any) +// //skip +// val (r11, m1, r12) = pat.pattern1.divideInto3ComponentsAny(r1 as Any) +// val (r21, r22) = pat.pattern2.divideIntoComponentsAny(r2 as Any) +// return f(Components2M(r11, m1, r12), m2, Components2(r21, r22)) +// } +// +// inline fun thenIf(crossinline f: (Components2M, M2, Components2) -> Boolean) = +// ThenM2P2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } +// +// inline fun thenIfThis(crossinline f: R.(Components2M, M2, Components2) -> Boolean) = +// ThenM2P2M(pat) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } +// +// inline fun then(crossinline f: (Components2M, M2, Components2) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } +// +// inline fun thenThis(crossinline f: R.(Components2M, M2, Components2) -> O) = +// StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } +//} diff --git a/decomat-core/src/main/kotlin/io/decomat/ThenPattern1.kt b/decomat-core/src/main/kotlin/io/decomat/ThenPattern1.kt index 53e868a..43c7f44 100644 --- a/decomat-core/src/main/kotlin/io/decomat/ThenPattern1.kt +++ b/decomat-core/src/main/kotlin/io/decomat/ThenPattern1.kt @@ -82,7 +82,7 @@ class Then2M, P11: Pattern, R11, ): Stage, R> { inline fun useComponents(r: R, f: (Components2M) -> O): O { val (r1) = pat.divideIntoComponentsAny(r as Any) - val (r11, m1, r12) = pat.pattern1.divideIntoComponentsAny(r1 as Any) + val (r11, m1, r12) = pat.pattern1.divideInto3ComponentsAny(r1 as Any) return f(Components2M(r11, m1, r12)) } diff --git a/decomat-core/src/templates/Pattern3.ftl b/decomat-core/src/templates/Pattern3.ftl index b806dcb..e45aec5 100644 --- a/decomat-core/src/templates/Pattern3.ftl +++ b/decomat-core/src/templates/Pattern3.ftl @@ -1,17 +1,20 @@ [#ftl] +[#macro divideIntoComponentsAnyX num] + [@compress single_line=true] + [#if num == 3]divideInto3ComponentsAny + [#else]divideIntoComponentsAny + [/#if] + [/@compress] +[/#macro] + [#macro Pattern num] [@compress single_line=true] [#if num == 0]Pattern0 [#elseif num == 1]Pattern1 [#elseif num == 2]Pattern2 - [#elseif num == 3]Pattern3 - [#-- - If want to add Pattern 4 etc... can just add a clause here, and then take the This____ generating part and just add one more there - Don't need to re-do all the macro patterns - [#elseif num == 4]Pattern3 - --] + [#elseif num == 3]Pattern2M [/#if] [/@compress] [/#macro] @@ -38,14 +41,14 @@ [#-- R1 --] R${mod} [#elseif num == 3] - [#-- (P1:) Pattern3, --] - Pattern3, + [#-- (P1:) Pattern2M, --] + Pattern2M, [#-- P11: Pattern, R11 --] P${mod}1: Pattern, R${mod}1, + [#-- M --] + M${mod}, [#-- P12: Pattern, R12 --] P${mod}2: Pattern, R${mod}2, - [#-- P13: Pattern, R13 --] - P${mod}3: Pattern, R${mod}3, [#-- R1 --] R${mod} [/#if] @@ -58,7 +61,7 @@ [#if num == 0]R${mod} [#elseif num == 1]Components1 [#elseif num == 2]Components2 - [#elseif num == 3]Components3 + [#elseif num == 3]Components2M [/#if] [/@compress] [/#macro] @@ -67,7 +70,9 @@ [#macro vars mod max] [@compress single_line=true] [#if max == 0]r${max} - [#else]([#list 1..max as a]r${mod}${a}[#sep], [/#sep][/#list]) + [#elseif max == 1 || max == 2]([#list 1..max as a]r${mod}${a}[#sep], [/#sep][/#list]) + [#elseif max == 3](r${mod}1, m${mod}, r${mod}2) + [#else] [/#if] [/@compress] [/#macro] @@ -78,7 +83,7 @@ [#if num == 0]r${mod} [#elseif num == 1]Components1(r${mod}1) [#elseif num == 2]Components2(r${mod}1, r${mod}2) - [#elseif num == 3]Components3(r${mod}1, r${mod}2, r${mod}3) + [#elseif num == 3]Components2M(r${mod}1, m${mod}, r${mod}2) [/#if] [/@compress] [/#macro] @@ -89,9 +94,9 @@ [/@compress] [/#macro] -[#macro compVars3 i1 i2 i3] +[#macro compVars2M i1 i2] [@compress single_line=true] - [@compVar 1 i1 /], [@compVar 2 i2 /], [@compVar 3 i3 /] + [@compVar 1 i1 /], m, [@compVar 2 i2 /] [/@compress] [/#macro] @@ -100,12 +105,14 @@ [@output file="decomat-core/build/templates/io/decomat/Then2.kt"] package io.decomat -[#list 0..2 as i1] - [#list 0..2 as i2] +[#list 0..3 as i1] + [#list 0..3 as i2] [#-- fun , P2: Pattern0, P11: Pattern, R11, R1, R2, R> case(pat: Pattern2) = Then10(pat, {true}) --] +[#-- No 'M' variable for these because these are all based on Pattern2, a separate clause is for Pattern2M variants --] fun case(pat: [@Pattern 2 /]) = Then${i1}${i2}(pat, {true}) +[#-- No 'M' variable for these because these are all based on Pattern2, a separate clause is for Pattern2M variants --] class Then${i1}${i2}( override val pat: [@Pattern 2 /], override val check: (R) -> Boolean @@ -113,8 +120,8 @@ class Then${i1}${i2}( inline fun useComponents(r: R, f: ([@Components 1 i1 /], [@Components 2 i2 /]) -> O): O { val (r1, r2) = pat.divideIntoComponentsAny(r as Any) - [#if i1 != 0]val [@vars 1 i1 /] = pat.pattern1.divideIntoComponentsAny(r1 as Any)[#else]//skip[/#if] - [#if i2 != 0]val [@vars 2 i2 /] = pat.pattern2.divideIntoComponentsAny(r2 as Any)[#else]//skip[/#if] + [#if i1 != 0]val [@vars 1 i1 /] = pat.pattern1.[@divideIntoComponentsAnyX i1 /](r1 as Any)[#else]//skip[/#if] + [#if i2 != 0]val [@vars 2 i2 /] = pat.pattern2.[@divideIntoComponentsAnyX i2 /](r2 as Any)[#else]//skip[/#if] return f([@compVars2 i1, i2 /]) } inline fun thenIf(crossinline f: ([@Components 1 i1 /], [@Components 2 i2 /]) -> Boolean) = @@ -131,41 +138,41 @@ class Then${i1}${i2}( } [/#list] [/#list] -[/@output] +[#-- ******************************************************************************************************* --] +[#-- ***************************** The Variants that are Pattern2M at the base ***************************** --] +[#-- ******************************************************************************************************* --] -[#--[@output file="decomat-core/build/templates/io/decomat/Then3.kt"]--] -[#--package io.decomat--] +[#list 0..3 as i1] + [#list 0..3 as i2] -[#--[#list 0..3 as i1]--] -[#-- [#list 0..3 as i2]--] -[#-- [#list 0..3 as i3]--] -[#-- fun , P2: Pattern0, P11: Pattern, R11, R1, R2, R> case(pat: Pattern2) = Then10(pat, {true}) --] +fun case(pat: [@Pattern 3 /]) = Then${i1}M${i2}(pat, {true}) + +class Then${i1}M${i2}( + override val pat: [@Pattern 3 /], + override val check: (R) -> Boolean +): Stage<[@Pattern 3 /], R> { + + inline fun useComponents(r: R, f: ([@Components 1 i1 /], M, [@Components 2 i2 /]) -> O): O { + val (r1, m, r2) = pat.divideInto3ComponentsAny(r as Any) + [#if i1 != 0]val [@vars 1 i1 /] = pat.pattern1.[@divideIntoComponentsAnyX i1 /](r1 as Any)[#else]//skip[/#if] + [#if i2 != 0]val [@vars 2 i2 /] = pat.pattern2.[@divideIntoComponentsAnyX i2 /](r2 as Any)[#else]//skip[/#if] + return f([@compVars2M i1, i2 /]) + } + inline fun thenIf(crossinline f: ([@Components 1 i1 /], M, [@Components 2 i2 /]) -> Boolean) = + Then${i1}M${i2}(pat) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } -[#--fun case(pat: [@Pattern 3 /]) = Then${i1}${i2}${i3}(pat, {true})--] - -[#--class Then${i1}${i2}${i3}(--] -[#-- override val pat: [@Pattern 3 /],--] -[#-- override val check: (R) -> Boolean--] -[#--): Stage<[@Pattern 3 /], R> {--] - -[#-- inline fun useComponents(r: R, f: ([@Components 1 i1 /], [@Components 2 i2 /], [@Components 3 i3 /]) -> O): O =--] -[#-- (r as? ProductClass<*>)?.let {--] -[#-- val (r1, r2, r3) = pat.divideIntoComponentsAny(it)--] -[#-- [#if i1 != 0]val [@vars 1 i1 /] = pat.pattern1.divideIntoComponentsAny(r1 as Any)[#else]//skip[/#if]--] -[#-- [#if i2 != 0]val [@vars 2 i2 /] = pat.pattern2.divideIntoComponentsAny(r2 as Any)[#else]//skip[/#if]--] -[#-- [#if i3 != 0]val [@vars 3 i3 /] = pat.pattern3.divideIntoComponentsAny(r3 as Any)[#else]//skip[/#if]--] -[#-- f([@compVars3 i1, i2, i3 /])--] -[#-- } ?: notRightCls(r)--] - -[#-- inline fun then(crossinline f: ([@Components 1 i1 /], [@Components 2 i2 /], [@Components 3 i3 /]) -> O) =--] -[#-- StageCase(pat, check) { value -> useComponents(value, f) }--] - -[#-- inline fun thenThis(crossinline f: R.() -> ([@Components 1 i1 /], [@Components 2 i2 /], [@Components 3 i3 /]) -> O) =--] -[#-- StageCase(pat, check) { v -> useComponents(v, f(v)) }--] -[#--}--] - -[#-- [/#list]--] -[#-- [/#list]--] -[#--[/#list]--] -[#--[/@output]--] \ No newline at end of file + inline fun thenIfThis(crossinline f: R.([@Components 1 i1 /], M, [@Components 2 i2 /]) -> Boolean) = + Then${i1}M${i2}(pat) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } + + inline fun then(crossinline f: ([@Components 1 i1 /], M, [@Components 2 i2 /]) -> O) = + StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(c1, m, c2) }) } + + inline fun thenThis(crossinline f: R.([@Components 1 i1 /], M, [@Components 2 i2 /]) -> O) = + StageCase(pat, check) { v -> useComponents(v, { c1, m, c2 -> f(v, c1, m, c2) }) } +} + [/#list] +[/#list] + + +[/@output] diff --git a/decomat-core/src/test/kotlin/io/decomat/ExampleDsl.kt b/decomat-core/src/test/kotlin/io/decomat/ExampleDsl.kt index fa58dab..11ecee6 100644 --- a/decomat-core/src/test/kotlin/io/decomat/ExampleDsl.kt +++ b/decomat-core/src/test/kotlin/io/decomat/ExampleDsl.kt @@ -1,11 +1,10 @@ package io.decomat -// TODO how to create a custom pattern that can be used to have user-defined logic -// i.e. equivalent of a custom `unapply` implmentation - -// FlatMap(IsAny, Any).then { a, (b, c) -> ... } -// FlatMap_M(IsAny, Map_M(IsAny, IsAny, Any)).then { a, (b, c) -> ... } -// of Map.Any +/* +For some reason here I used the pattern where single letters A, B etc... are the pattern +vars and the AP, BP are the pattern atom as opposed to the generated code where +AP, BP are the pattern vars and A, B are the atoms + */ sealed interface Query data class FlatMap(val head: Query, val body: Query): Query, HasProductClass { diff --git a/decomat-core/src/test/kotlin/io/decomat/middle/ExampleMiddleDsl.kt b/decomat-core/src/test/kotlin/io/decomat/middle/ExampleMiddleDsl.kt new file mode 100644 index 0000000..72ab973 --- /dev/null +++ b/decomat-core/src/test/kotlin/io/decomat/middle/ExampleMiddleDsl.kt @@ -0,0 +1,55 @@ +package io.decomat.middle + +import io.decomat.* + +/* +For some reason here I used the pattern where single letters A, B etc... are the pattern +vars and the AP, BP are the pattern atom as opposed to the generated code where +AP, BP are the pattern vars and A, B are the atoms + */ + +sealed interface Query +data class FlatMap(val head: Query, val middle: String, val body: Query): Query, HasProductClass { + override val productComponents = ProductClass2M(this, head, middle, body) + + // Needed for static extension FlatMap_M + companion object { + // important for a, b to be A, B instead of just Pattern, Pattern because + // the resolution to the correct `case` function doesn't know which case to choose + // since case-functions are defined on specific Pattern subclasses e.g. case(P: Pattern3<...>) + // all of them start to apply as soon as you generalize to Pattern + operator fun , B: Pattern, AP: Query, BP: Query> get(a: A, b: B): Pattern2M = FlatMap_M(a, b) + } +} + +operator fun , B: Pattern, AP: Query, BP: Query> FlatMap.Companion.get(a: A, b: B) = FlatMap_M(a, b) +class FlatMap_M, B: Pattern, AP: Query, BP: Query>(a: A, b: B): Pattern2M(a, b, Typed()) + +data class Map(val head: Query, val middle: String, val body: Query): Query, HasProductClass { + override val productComponents = ProductClass2M(this, head, middle, body) + + companion object { + operator fun , B: Pattern, AP: Query, BP: Query> get(a: Pattern, b: Pattern) = Map_M(a, b) + } +} + +operator fun , B: Pattern, AP: Query, BP: Query> Map.Companion.get(a: A, b: B) = Map_M(a, b) +val Is.Companion.Map get() = Is() + +class Map_M, P2: Pattern, A1: Query, A2: Query>(a: P1, b: P2): Pattern2M(a, b, Typed()) + +data class Distinct(val body: Query): Query, HasProductClass { + override val productComponents get() = ProductClass1(this, body) + companion object { + operator fun , AP: Query> get(a: Pattern) = Distinct_M(a) + } +} + +class Distinct_M, A: Query>(a: P): Pattern1(a, Typed()) + +operator fun , AP: Query> Distinct.Companion.get(a: A) = Distinct_M(a) + +data class Entity(val name: String): Query + + + diff --git a/decomat-core/src/test/kotlin/io/decomat/middle/MatchTest.kt b/decomat-core/src/test/kotlin/io/decomat/middle/MatchTest.kt new file mode 100644 index 0000000..5edb484 --- /dev/null +++ b/decomat-core/src/test/kotlin/io/decomat/middle/MatchTest.kt @@ -0,0 +1,140 @@ +package io.decomat.middle + +import io.decomat.* +import org.junit.jupiter.api.Assertions.assertFalse +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import kotlin.test.fail + +@Suppress("DANGEROUS_CHARACTERS") +class MatchTest { + val foo = Entity("foo") + val bar = Entity("bar") + val baz = Entity("baz") + val waz = Entity("waz") + val kaz = Entity("kaz") + val idA = "AAA" + val idB = "BBB" + val idC = "CCC" + + @Test + fun `flatMap(?, ?)`() { + assertTrue(FlatMap[Is(), Is()].matches(FlatMap(foo, idA, bar))) + assertTrue(FlatMap[Is(), Is()].matches(FlatMap(foo, idA, Map(foo, idB, Map(waz, idC, kaz))))) + } + + infix fun T.shouldBe(b: T): Unit = assertEquals(this, b) + + @Test + fun `flatMap(?, ?) - match`() { + on(FlatMap(foo, idA, bar)).match( + case(FlatMap[Is(), Is(waz)]).then { a, m, b -> fail() }, + case(FlatMap[Is(), Is()]).then { a, m, b -> Res3(a, m, b) } + ) shouldBe Res3(foo, idA, bar) + + assertTrue(FlatMap[Is(), Is()].matches(FlatMap(foo, idA, bar))) + assertTrue(FlatMap[Is(), Is()].matches(FlatMap(foo, idA, Map(foo, idB, Map(waz, idC, kaz))))) + } + + @Test + fun `flatMap(?, Map(?))`() { + on(FlatMap(foo, idA, Map(bar, idB, baz))).match( + case(FlatMap[Is(), Map[Is(), Is(waz)]]).then { a, m, b -> fail() }, + case(FlatMap[Is(), Is()]).then { a, m, b -> Res3(a, m, b) } + ) shouldBe Res3(foo, idA, Map(bar, idB, baz)) + + assertTrue( + FlatMap[Is(), Is()].matches(FlatMap(foo, idA, Map(bar, idB, baz))) + ) + } + + @Test + fun `flatMap(Map(?), ?)`() { + on(FlatMap(Map(foo, idB, bar), idA, baz)).match( + case(FlatMap[Map[Is(), Is(waz)], Is()]).then { a, m, b -> fail() }, + case(FlatMap[Is(), Is()]).then { a, m, b -> Res3(a, m, b) } + ) shouldBe Res3(Map(foo, idB, bar), idA, baz) + + assertTrue( + FlatMap[Is(), Is()].matches(FlatMap(foo, idA, Map(bar, idB, baz))) + ) + } + + @Test + fun `flatMap(Map(?), Map(?))`() { + on(FlatMap(Map(foo, idA, bar), idB, Map(baz, idC, waz))).match( + case(FlatMap[Map[Is(), Is(kaz)], Map[Is(), Is(kaz)]]).then { a, m, b -> fail() }, + case(FlatMap[Map[Is(), Is()], Map[Is(), Is()]]).then { (a1, am, a2), m, (b1, bm, b2) -> Res3(Res3(a1, am, a2), m, Res3(b1, bm, b2)) } + ) shouldBe Res3(Res3(foo, idA, bar), idB, Res3(baz, idC, waz)) + + assertTrue( + FlatMap[Map[Is(), Is()], Map[Is(), Is()]].matches(FlatMap(Map(foo, idA, bar), idB, Map(baz, idC, waz))) + ) + } + + @Test + fun `flatMap(?, Map(Map))`() { + on(FlatMap(foo, idA, Map(bar, idB, baz))).match( + case(FlatMap[Is(), Map[Is(), Is(waz)]]).then { a, m, b -> fail() }, + case(FlatMap[Is(), Map[Is(), Is()]]).then { a, m, (b1, m1, b2) -> Res3(a, m, Res3(b1, m1, b2)) } + ) shouldBe Res3(foo, idA, Res3(bar, idB, baz)) + + assertTrue( + FlatMap[Is(), Map[Is(), Is()]].matches(FlatMap(foo, idA, Map(foo, idB, Map(waz, idC, kaz)))) + ) + } + + @Test + fun `flatMap(Map(Map), ?)`() { + on(FlatMap(Map(foo, idA, bar), idB, baz)).match( + case(FlatMap[Map[Is(), Is(waz)], Is()]).then { a, m, b -> fail() }, + case(FlatMap[Map[Is(), Is()], Is()]).then { (a1, m1, a2), m, b -> Res3(Res3(a1, m1, a2), m, b) } + ) shouldBe Res3(Res3(foo, idA, bar), idB, baz) + + assertTrue( + FlatMap[Map[Is(), Is()], Is()].matches(FlatMap(Map(foo, idA, bar), idB, baz)) + ) + } + + @Test + fun `flatMap(Map(Map), Map(Map))`() { + on(FlatMap(Map(foo, idA, bar), idB, Map(baz, idC, waz))).match( + case(FlatMap[Map[Is(), Is(kaz)], Map[Is(), Is(kaz)]]).then { a, m, b -> fail() }, + case(FlatMap[Map[Is(), Is()], Map[Is(), Is()]]).then { (a1, m1, a2), m, (b1, m2, b2) -> Res3(Res3(a1, m1, a2), m, Res3(b1, m2, b2)) } + ) shouldBe Res3(Res3(foo, idA, bar), idB, Res3(baz, idC, waz)) + + assertTrue( + FlatMap[Map[Is(), Is()], Map[Is(), Is()]].matches(FlatMap(Map(foo, idA, bar), idB, Map(baz, idC, waz))) + ) + } + + @Test + fun `flatMap(?, Map(!Entity) - Negative`() { + assertFalse( + FlatMap[Is(), Map[Is(), Is()]].matches(FlatMap(foo, idA, Map(foo, idB, Map(waz, idC, kaz)))) + ) + } + + @Test + fun `flatMap(?, Map(!Map) - Negative`() { + assertFalse( + FlatMap[Is(), Map[Is(), Is()]].matches(FlatMap(foo, idA, Map(foo, idB, foo))) + ) + } + + @Test + fun `flatMap(foo, Map(?))`() { + assertTrue( + FlatMap[Is(foo), Map[Is(), Is()]].matches(FlatMap(foo, idA, Map(foo, idB, foo))) + ) + } + + @Test + fun `flatMap(!foo, Map(?)) - Negative`() { + assertFalse( + FlatMap[Is(bar), Map[Is(), Is()]].matches(FlatMap(foo, idA, Map(foo, idB, foo))) + ) + } + +} \ No newline at end of file