Created
June 19, 2024 05:45
-
-
Save hikaMaeng/4a58151f256d9af7480f4bcff54d15bb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@file:Suppress("NOTHING_TO_INLINE") | |
package kore.rule | |
import kore.rule.Rule.Item | |
import kore.vo.task.Task | |
import kore.wrap.W | |
import kore.wrap.Wrap | |
class Rule @PublishedApi internal constructor(){ | |
companion object { | |
inline operator fun invoke(block:Group.()->Unit): Rule = Rule().also{it.group.block()} | |
} | |
sealed interface R{ | |
operator fun DSL.invoke(value:Any, param:Array<out Any>):Any | |
} | |
object DSL{ | |
fun fail(value:Any, msg:String):Throwable = Throwable("$msg : value:$value") | |
fun any(value:Any, param:Array<out Any>, vararg items:Item):Any{ | |
var result:Any = value | |
items.any{ | |
result = it.run{invoke(value, param)} | |
result !is Throwable | |
} | |
return result | |
} | |
fun all(value:Any, param:Array<out Any>, vararg items:Item):Any{ | |
var result:Any = value | |
items.all{ | |
result = it.run{invoke(value, param)} | |
result !is Throwable | |
} | |
return result | |
} | |
} | |
fun interface Item:R | |
data object Or:R{override fun DSL.invoke(value:Any, param:Array<out Any>):Any = value} | |
class Group:R{ | |
@PublishedApi internal val rules:ArrayList<R> = arrayListOf() | |
override fun DSL.invoke(value:Any, param:Array<out Any>):Any{ | |
return DSL.run{ | |
var result:Any = value | |
var i = 0 | |
while(i < rules.size){ | |
val it:R = rules[i] | |
if(it == Or) break | |
val prev:Any = result | |
result = it.run{invoke(result, param)} | |
if(result is Throwable){ | |
if(i < rules.size - 2 && rules[i + 1] == Or){ | |
result = prev | |
i++ | |
} else break | |
} | |
i++ | |
} | |
result | |
} | |
} | |
inline val or:Boolean get() = rules.add(Or) | |
inline fun rule(noinline block:DSL.(Any, Array<out Any>)->Any){rules.add(Item(block))} | |
inline fun rule(item:Item){rules.add(item)} | |
inline fun group(block:Group.()->Unit){rules.add(Group().also{it.block()})} | |
inline fun add(item:R){rules.add(item)} | |
} | |
@PublishedApi internal val group:Group = Group() | |
operator fun invoke(value:Any, vararg param:Any):Wrap<Any>{ | |
val result:Any = DSL.run{ | |
group.run{DSL.invoke(value, param)} | |
} | |
return if(result is Throwable) W(result) else W(result) | |
} | |
} | |
inline fun Task.ruleItem(rule:Rule.R){ | |
rule(Rule{ | |
rules.add(rule) | |
}) | |
} | |
inline fun Task.anyRuleItem(vararg rules:Rule.R){ | |
rule(Rule{ | |
rules.forEach{ | |
add(it) | |
add(Rule.Or) | |
} | |
}) | |
} | |
inline fun Task.allRuleItem(vararg rules:Rule.R){ | |
rule(Rule{ | |
rules.forEach{add(it)} | |
}) | |
} | |
inline fun Task.rule(rule:Rule){ | |
addSetTask { vo, _, v -> | |
rule(v,vo).getOrFailEffect { err -> throw err } | |
} | |
} | |
inline fun Task.anyRule(vararg rules: Rule) { | |
addSetTask { vo, _, v -> | |
var value: Any? = v | |
val result = rules.any { rule -> | |
value = rule(v)() | |
value != null | |
} | |
/**or이기 때문에 만약 실패한다면 rules의 마지막 요소의 error를 표시해준다.*/ | |
if (!result) rules.last()(v,vo).getOrFailEffect { throw it } | |
else result | |
} | |
} | |
inline fun Task.allRule(vararg rules: Rule) { | |
addSetTask{_, _, v -> | |
rules.fold(v){acc, it-> | |
it(acc).getOrFailEffect { throw it } //실패 시 바로 종료 | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment