diff --git a/orx-expression-evaluator-typed/src/commonMain/kotlin/typed/MemberFunctions.kt b/orx-expression-evaluator-typed/src/commonMain/kotlin/typed/MemberFunctions.kt index a84c9eed..7140a1e5 100644 --- a/orx-expression-evaluator-typed/src/commonMain/kotlin/typed/MemberFunctions.kt +++ b/orx-expression-evaluator-typed/src/commonMain/kotlin/typed/MemberFunctions.kt @@ -14,12 +14,35 @@ internal fun String.memberFunctions(n: String): ((Array) -> Any)? { internal fun List<*>.memberFunctions(n: String): ((Array) -> 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>).max() } + "min" -> { n -> (this as List>).min() } + "maxBy" -> { n -> + val lambda = (n[0] as (Any) -> Any); this.maxByOrNull { lambda(it!!) as Comparable } ?: error("no max") + } + + "minBy" -> { n -> + val lambda = (n[0] as (Any) -> Any); this.minByOrNull { lambda(it!!) as Comparable } ?: error("no max") + } + "sorted" -> { n -> (this as List>).sorted() } + "sortedBy" -> { n -> + val lambda = (n[0] as (Any) -> Any); this.sortedBy { lambda(it!!) as Comparable } + } + "sortedByDescending" -> { n -> + val lambda = (n[0] as (Any) -> Any); this.sortedByDescending { lambda(it!!) as Comparable } + } + "reversed" -> { n -> this.reversed() } + else -> null } } \ No newline at end of file diff --git a/orx-expression-evaluator-typed/src/commonMain/kotlin/typed/TypedExpressions.kt b/orx-expression-evaluator-typed/src/commonMain/kotlin/typed/TypedExpressions.kt index 0f992d9e..fad30a90 100644 --- a/orx-expression-evaluator-typed/src/commonMain/kotlin/typed/TypedExpressions.kt +++ b/orx-expression-evaluator-typed/src/commonMain/kotlin/typed/TypedExpressions.kt @@ -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) diff --git a/orx-expression-evaluator/src/commonMain/antlr/KeyLangParser.g4 b/orx-expression-evaluator/src/commonMain/antlr/KeyLangParser.g4 index 421744f4..747713be 100644 --- a/orx-expression-evaluator/src/commonMain/antlr/KeyLangParser.g4 +++ b/orx-expression-evaluator/src/commonMain/antlr/KeyLangParser.g4 @@ -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