All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.lightningkite.khrysalis.generic.PartialTranslator.kt Maven / Gradle / Ivy

The newest version!
package com.lightningkite.khrysalis.generic

import java.util.*
import java.util.concurrent.ConcurrentLinkedQueue
import kotlin.collections.HashMap

interface TranslatorInterface {
    fun translate(
        rule: Any,
        out: OUT,
        afterPriority: Int = Int.MAX_VALUE
    ): RESULT
}

fun  PartialTranslator.Context.line() {
    out.appendln()
}

fun  PartialTranslator.Context.line(text: String) {
    out.appendln(text)
}

inline fun  PartialTranslator.Context.line(action: () -> Unit) {
    action()
    out.appendln()
}

abstract class PartialTranslator {

    open val parent: TranslatorInterface? = null

    abstract fun getIdentifier(rule: IN): IDENTIFIER
    abstract fun emitDefault(identifier: IDENTIFIER, rule: IN, out: OUT): RESULT

    inner class Handler(
        val identifier: IDENTIFIER,
        val condition: Context.() -> Boolean = { true },
        val priority: Int = 0,
        val action: Context.() -> RESULT
    ) : Comparable {
        private val uuid: UUID = UUID.randomUUID()
        override fun compareTo(other: Handler): Int {
            var result = other.priority.compareTo(this.priority)
            if (result == 0) {
                result = this.uuid.compareTo(other.uuid)
            }
            return result
        }
    }

    open inner class Context {
        val partialTranslator = this@PartialTranslator
        lateinit var rule: IN
        lateinit var out: OUT
        var noReuse: Boolean = false
        var option: Handler? = null

        fun doSuper(): RESULT = translate(rule, out, option?.priority ?: Int.MAX_VALUE)
        fun defer(identifier: IDENTIFIER) = translate(identifier, rule, out)

        fun emit(item: IN?): RESULT? {
            if (item == null) return null
            return translate(item, out)
        }

        inline operator fun IN?.unaryPlus() = emit(this)
        inline operator fun IN?.unaryMinus() = emit(this)

        @JvmName("unaryPlusAnyNullable")
        inline operator fun Any?.unaryPlus() = emit(this)

        @JvmName("unaryMinusAnyNullable")
        inline operator fun Any?.unaryMinus() = emit(this)

        inline fun write(item: IN) = emit(item)

        @JvmName("emitAny")
        fun emit(item: Any?): RESULT? {
            if (item == null) return null
            return parent!!.translate(item, out)
        }
    }

    val recycledContexts = ConcurrentLinkedQueue()
    open fun makeContext(): Context = Context()
    open fun updateContext(
        context: Context,
        rule: IN,
        out: OUT
    ) {
        context.rule = rule
        context.out = out
    }

    inline fun  useContext(
        rule: IN,
        out: OUT,
        action: Context.() -> R
    ): R {
        val pulled = recycledContexts.poll() ?: makeContext()
        updateContext(pulled, rule, out)
        val result = action.invoke(pulled)
        if (!pulled.noReuse) {
            recycledContexts.add(pulled)
        }
        return result
    }

    val handlers: HashMap> = HashMap()

    fun handle(
        identifier: IDENTIFIER,
        condition: Context.() -> Boolean = { true },
        priority: Int = 0,
        action: Context.() -> RESULT
    ): Handler {
        val option = Handler(
            identifier = identifier,
            priority = priority,
            condition = condition,
            action = action
        )
        handlers.getOrPut(identifier) { TreeSet() }.add(option)
        return option
    }

    open fun translate(
        identifier: IDENTIFIER,
        rule: IN,
        out: OUT,
        afterPriority: Int = Int.MAX_VALUE
    ): RESULT {
        return useContext(rule, out) {
            handlers[identifier]?.asSequence()
                ?.dropWhile { it.priority >= afterPriority }
                ?.filter { it.condition.invoke(this) }
                ?.firstOrNull()
                ?.let {
                    this.option = it
                    it.action.invoke(this)
                } ?: emitDefault(identifier, rule, out)
        }
    }

    fun translate(
        rule: IN,
        out: OUT,
        afterPriority: Int = Int.MAX_VALUE
    ): RESULT = translate(getIdentifier(rule), rule, out, afterPriority)
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy