[orx-expression-evaluator-typed] Add list index operator, list minBy/maxBy/sortedBy/min/max/sorted/first/last

This commit is contained in:
Edwin Jakobs
2024-06-12 22:06:57 +02:00
parent 0d44bc9cf0
commit e90cc2ec96
3 changed files with 46 additions and 2 deletions

View File

@@ -14,12 +14,35 @@ internal fun String.memberFunctions(n: String): ((Array<Any>) -> Any)? {
internal fun List<*>.memberFunctions(n: String): ((Array<Any>) -> Any)? {
return when (n) {
"first" -> { n -> this.first() ?: error("empty list") }
"last" -> { n -> this.last() ?: error("empty list") }
"take" -> { n -> this.take((n[0] as Number).toInt()) }
"drop" -> { n -> this.drop((n[0] as Number).toInt()) }
"takeLast" -> { n -> this.takeLast((n[0] as Number).toInt()) }
"dropLast" -> { n -> this.takeLast((n[0] as Number).toInt()) }
"map" -> { n -> val lambda = (n[0] as (Any)->Any); this.map { lambda(it!!) } }
"filter" -> { n -> val lambda = (n[0] as (Any)->Any); this.filter { (lambda(it!!) as Double).roundToInt() != 0 } }
"map" -> { n -> val lambda = (n[0] as (Any) -> Any); this.map { lambda(it!!) } }
"filter" -> { n ->
val lambda = (n[0] as (Any) -> Any); this.filter { (lambda(it!!) as Double).roundToInt() != 0 }
}
"max" -> { n -> (this as List<Comparable<Any>>).max() }
"min" -> { n -> (this as List<Comparable<Any>>).min() }
"maxBy" -> { n ->
val lambda = (n[0] as (Any) -> Any); this.maxByOrNull { lambda(it!!) as Comparable<Any> } ?: error("no max")
}
"minBy" -> { n ->
val lambda = (n[0] as (Any) -> Any); this.minByOrNull { lambda(it!!) as Comparable<Any> } ?: error("no max")
}
"sorted" -> { n -> (this as List<Comparable<Any>>).sorted() }
"sortedBy" -> { n ->
val lambda = (n[0] as (Any) -> Any); this.sortedBy { lambda(it!!) as Comparable<Any> }
}
"sortedByDescending" -> { n ->
val lambda = (n[0] as (Any) -> Any); this.sortedByDescending { lambda(it!!) as Comparable<Any> }
}
"reversed" -> { n -> this.reversed() }
else -> null
}
}

View File

@@ -97,10 +97,29 @@ abstract class TypedExpressionListenerBase(
override fun exitListLiteral(ctx: KeyLangParser.ListLiteralContext) {
val s = state
if (s.inFunctionLiteral > 0) {
return
}
val list = (0 until ctx.getExpression().size).map { s.valueStack.pop() }
s.valueStack.push(list.reversed())
}
override fun exitIndexExpression(ctx: KeyLangParser.IndexExpressionContext) {
val s = state
if (s.inFunctionLiteral > 0) {
return
}
val index = (s.valueStack.pop() as? Double)?.roundToInt() ?: error("index is not a number")
val listValue = s.valueStack.pop()
val value = when (listValue) {
is List<*> -> listValue[index] ?: error("got null")
is Function<*> -> (listValue as (Int)->Any)(index)
else -> error("can't index on '$listValue'")
}
s.valueStack.push(value)
}
override fun enterFunctionLiteral(ctx: KeyLangParser.FunctionLiteralContext) {
val s = state
s.inFunctionLiteral++
@@ -689,6 +708,7 @@ abstract class TypedExpressionListenerBase(
is Vector4 -> current.property(property)
is ColorRGBa -> current.property(property)
is Matrix44 -> current.property(property)
is String -> current.property(property)
else -> error("can't look up: ${current::class} '$current', root:'$root' ${ctx.text} ")
}
s.valueStack.push(current)

View File

@@ -22,6 +22,7 @@ expression : INTLIT # int
| expression DOT ID LPAREN expression COMMA expression RPAREN # memberFunctionCall2Expression
| expression DOT ID LPAREN expression COMMA expression COMMA expression RPAREN # memberFunctionCall3Expression
| expression DOT ID LPAREN expression COMMA expression COMMA expression COMMA expression RPAREN # memberFunctionCall4Expression
| expression LBRACKET expression RBRACKET # indexExpression
| ID LPAREN RPAREN # functionCall0Expression
| ID LPAREN expression RPAREN # functionCall1Expression
| ID LPAREN expression COMMA expression RPAREN # functionCall2Expression