Skip to content

Commit

Permalink
move to single expression interpreter
Browse files Browse the repository at this point in the history
  • Loading branch information
Zhirkevich Alexander Y authored and Zhirkevich Alexander Y committed Jul 26, 2024
1 parent e5214d5 commit 47db2f1
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 150 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@ package io.github.alexzhirkevich.compottie.internal.animation
import io.github.alexzhirkevich.compottie.dynamic.PropertyProvider
import io.github.alexzhirkevich.compottie.dynamic.derive
import io.github.alexzhirkevich.compottie.internal.AnimationState
import io.github.alexzhirkevich.compottie.internal.animation.expressions.ExpressionEvaluator
import io.github.alexzhirkevich.compottie.internal.animation.expressions.ExpressionInterpreter
import io.github.alexzhirkevich.compottie.internal.animation.expressions.MainExpressionInterpreter
import io.github.alexzhirkevich.compottie.internal.animation.expressions.RawExpressionEvaluator
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient

internal abstract class DynamicProperty<T : Any> : ExpressionProperty<T>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package io.github.alexzhirkevich.compottie.internal.animation.expressions
import io.github.alexzhirkevich.compottie.internal.AnimationState
import io.github.alexzhirkevich.compottie.internal.animation.RawProperty

internal val EXPR_DEBUG_PRINT_ENABLED = true
internal val EXPR_DEBUG_PRINT_ENABLED = false

internal fun interface Expression {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ private class ExpressionEvaluatorImpl(expr : String) : ExpressionEvaluator {

private val context = DefaultEvaluatorContext()

private val expression: Expression = MainExpressionInterpreter(expr, context).interpret()
private val expression: Expression = ExpressionInterpreterImpl(expr, context).interpret()

private val errors = mutableSetOf<String?>()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,29 +33,42 @@ import io.github.alexzhirkevich.compottie.internal.animation.expressions.operati
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract

internal class SingleExpressionInterpreter(
expr : String,
internal class ExpressionInterpreterImpl(
private val expr : String,
private val context: EvaluationContext
) : ExpressionInterpreter {

private var pos = -1
private var ch: Char = ' '

private val expr = expr
.replace("{\n","{")
.replace("\n}"," }")

override fun interpret(): Expression {
pos = -1
ch = ' '
if (EXPR_DEBUG_PRINT_ENABLED) {
println("Parsing $expr")
}
nextChar()
val x = parseAssignment(OpGlobalContext)
val expressions = buildList {
var x : Expression? = null
do {
while (eat(';')){
}
if (pos >= expr.length){
break
}

x = parseAssignment(if (x is ExpressionContext<*>) x else OpGlobalContext)
add(x)
} while (pos < expr.length)
}

require(pos <= expr.length) {
"Unexpected Lottie expression $expr"
}
return x.also {

return OpBlock(expressions, false).also {
pos = -1
ch = ' '
if (EXPR_DEBUG_PRINT_ENABLED) {
println("Expression parsed: $expr")
}
Expand All @@ -69,17 +82,18 @@ internal class SingleExpressionInterpreter(
}

private fun nextChar() {
ch = if (++pos < expr.length) expr[pos] else ';'
ch = if (++pos < expr.length) expr[pos] else ' '
}

private fun prevChar() {
ch = if (--pos > 0 && pos < expr.length) expr[pos] else ';'
ch = if (--pos > 0 && pos < expr.length) expr[pos] else ' '
}

private fun Char.skip() : Boolean = this == ' ' || this == '\n'

private fun eat(charToEat: Char): Boolean {
while (ch.skip()) nextChar()
while (ch.skip() && pos < expr.length)
nextChar()

if (ch == charToEat) {
nextChar()
Expand Down Expand Up @@ -389,7 +403,7 @@ internal class SingleExpressionInterpreter(
do {
nextChar()
} while (
ch.isFun() && !(isReserved(expr.substring(startPos, pos)) && ch == ' ')
pos < expr.length && ch.isFun() && !(isReserved(expr.substring(startPos, pos)) && ch == ' ')
)

val func = expr.substring(startPos, pos).trim()
Expand Down

This file was deleted.

14 changes: 9 additions & 5 deletions compottie/src/commonTest/kotlin/expressions/TestUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,19 @@ import kotlin.test.assertEquals

internal const val ret = "\$bm_rt"

internal fun String.executeExpression() : Any {
val value = AnimatedNumber.Default(0f, this)
val state = MockAnimationState(0f)
val evaluator = ExpressionEvaluator(this)
return value.run { evaluator.run { evaluate(state) } }
}

internal fun String.assertSimpleExprEquals(expected : Any) {
"var $ret=$this".assertExprReturns(expected)
"var $ret=$this".assertSimpleExprReturns(expected)
}

internal fun String.assertSimpleExprReturns(expected : Any) {
val value = AnimatedNumber.Default(0f, this)
val state = MockAnimationState(0f)
val evaluator = ExpressionEvaluator(this)
assertEquals(expected, value.run { evaluator.run { evaluate(state) } })
assertEquals(expected, executeExpression())
}

internal fun String.assertExprReturns(expected : Any) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package expressions.global

import expressions.assertSimpleExprEquals
import expressions.executeExpression
import kotlin.test.Test
import kotlin.test.assertFails

class SyntaxExpressionsTest {

@Test
fun newline_property() {
"""
Math
.imul(3,4)
.toString()
""".trimIndent().assertSimpleExprEquals("12")

"""
Math
.imul(3,4)
.toString()
""".trimIndent().assertSimpleExprEquals("12")

"""
Math
.imul(3,4)
.toString()
;
""".trimIndent().assertSimpleExprEquals("12")


assertFails {
"""
Math
.imul(3,4);
.toString()
""".trimIndent().executeExpression()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,55 +33,55 @@ internal class JsStringExpressionsTest {

@Test
fun padEnd() {
"'abc'.padEnd(5))".assertExprEquals("abc ")
"'abc'.padEnd(5,'0'))".assertExprEquals("abc00")
"'abc'.padEnd(5,'12'))".assertExprEquals("abc12")
"'abc'.padEnd(6,'12'))".assertExprEquals("abc121")
"'abcdef'.padEnd(5,'0'))".assertExprEquals("abcdef")
"'abc'.padEnd(5)".assertExprEquals("abc ")
"'abc'.padEnd(5,'0')".assertExprEquals("abc00")
"'abc'.padEnd(5,'12')".assertExprEquals("abc12")
"'abc'.padEnd(6,'12')".assertExprEquals("abc121")
"'abcdef'.padEnd(5,'0')".assertExprEquals("abcdef")
}

@Test
fun padStart() {
"'abc'.padStart(5))".assertExprEquals(" abc")
"'abc'.padStart(5,'0'))".assertExprEquals("00abc")
"'abc'.padStart(5,'12'))".assertExprEquals("12abc")
"'abc'.padStart(6,'12'))".assertExprEquals("121abc")
"'abcdef'.padStart(5,'0'))".assertExprEquals("abcdef")
"'abc'.padStart(5)".assertExprEquals(" abc")
"'abc'.padStart(5,'0')".assertExprEquals("00abc")
"'abc'.padStart(5,'12')".assertExprEquals("12abc")
"'abc'.padStart(6,'12')".assertExprEquals("121abc")
"'abcdef'.padStart(5,'0')".assertExprEquals("abcdef")
}

@Test
fun repeat() {
"'abc'.repeat(3))".assertExprEquals("abcabcabc")
"'abc'.repeat(0))".assertExprEquals("")
"'abc'.repeat(3)".assertExprEquals("abcabcabc")
"'abc'.repeat(0)".assertExprEquals("")
}

@Test
fun replace() {
"'aabbcc'.replace('b','f'))".assertExprEquals("aafbcc")
"'aabbcc'.replace('x','ff'))".assertExprEquals("aabbcc")
"'aabbcc'.replace('','ff'))".assertExprEquals("ffaabbcc")
"'aabbcc'.replace('b','f')".assertExprEquals("aafbcc")
"'aabbcc'.replace('x','ff')".assertExprEquals("aabbcc")
"'aabbcc'.replace('','ff')".assertExprEquals("ffaabbcc")
}

@Test
fun replaceAll() {
"'aabbcc'.replaceAll('b','f'))".assertExprEquals("aaffcc")
"'aabbcc'.replaceAll('x','ff'))".assertExprEquals("aabbcc")
"'aabbcc'.replaceAll('','ff'))".assertExprEquals("ffaabbcc")
"'aabbcc'.replaceAll('b','f')".assertExprEquals("aaffcc")
"'aabbcc'.replaceAll('x','ff')".assertExprEquals("aabbcc")
"'aabbcc'.replaceAll('','ff')".assertExprEquals("ffaabbcc")
}

@Test
fun trim() {
"' abc '.trim())".assertExprEquals("abc")
"'abc '.trim())".assertExprEquals("abc")
"' abc'.trim())".assertExprEquals("abc")
"' abc '.trim()".assertExprEquals("abc")
"'abc '.trim()".assertExprEquals("abc")
"' abc'.trim()".assertExprEquals("abc")

"' abc'.trimStart())".assertExprEquals("abc")
"' abc '.trimStart())".assertExprEquals("abc ")
"'abc '.trimStart())".assertExprEquals("abc ")
"' abc'.trimStart()".assertExprEquals("abc")
"' abc '.trimStart()".assertExprEquals("abc ")
"'abc '.trimStart()".assertExprEquals("abc ")

"' abc'.trimEnd())".assertExprEquals(" abc")
"' abc '.trimEnd())".assertExprEquals(" abc")
"'abc '.trimEnd())".assertExprEquals("abc")
"' abc'.trimEnd()".assertExprEquals(" abc")
"' abc '.trimEnd()".assertExprEquals(" abc")
"'abc '.trimEnd()".assertExprEquals("abc")
}
@Test
fun substring() {
Expand Down
9 changes: 4 additions & 5 deletions example/shared/src/commonMain/kotlin/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ import io.github.alexzhirkevich.compottie.rememberResourcesAssetsManager
import io.github.alexzhirkevich.compottie.rememberResourcesFontManager
import io.github.alexzhirkevich.shared.generated.resources.ComicNeue
import io.github.alexzhirkevich.shared.generated.resources.Res
import lottiefiles.LottieFilesScreen
import org.jetbrains.compose.resources.ExperimentalResourceApi
import kotlin.math.roundToInt

Expand Down Expand Up @@ -144,7 +143,7 @@ public fun App() {
LottieCompositionSpec.ResourceString("expr/move_horizontal.json")
// LottieCompositionSpec.ResourceString("expr/wiggle.json")
// LottieCompositionSpec.ResourceString("expr/noise.json")
// LottieCompositionSpec.ResourceString(TEST)
// LottieCompositionSpec.ResourceString(IMAGE_ASSET)
//
// LottieCompositionSpec.Url(
// "https://assets-v2.lottiefiles.com/a/9286b092-117a-11ee-b857-2712bc869389/WSepKUr5be.lottie"
Expand Down Expand Up @@ -199,9 +198,9 @@ public fun App() {
// else -> null
// }
// },
// assetsManager = rememberResourcesAssetsManager(
// readBytes = Res::readBytes
// ),
assetsManager = rememberResourcesAssetsManager(
readBytes = Res::readBytes
),
)

Image(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ internal class LottieFilesViewModel() : ViewModel() {
.jsonObject
.get("data")!!

println(resp)

_files.value = json.decodeFromJsonElement<List<LottieFile>>(files)
_pageCount.value = resp.get("originalPageCount")?.jsonPrimitive?.intOrNull ?: 0
Expand Down

0 comments on commit 47db2f1

Please sign in to comment.