Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Zhirkevich Alexander Y authored and Zhirkevich Alexander Y committed Jul 31, 2024
1 parent 0e52188 commit 87c4f9a
Show file tree
Hide file tree
Showing 49 changed files with 2,362 additions and 1,655 deletions.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion example/shared/src/commonMain/kotlin/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public suspend fun LottieCompositionSpec.Companion.ResourceString(
public fun App() {

// return InteractiveControlsScreen()
return LottieFilesScreen()
// return LottieFilesScreen()


// return LottieFontExample()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,11 @@ package io.github.alexzhirkevich.skriptie
import io.github.alexzhirkevich.skriptie.common.OpGetVariable
import io.github.alexzhirkevich.skriptie.common.OpIndex

public interface Expression<in C : ScriptContext> {
public fun interface Expression<in C : ScriptContext> {

public operator fun invoke(context: C): Any?
}

internal fun <C : ScriptContext> Expression(
block : (C) -> Any?
) : Expression<C> = object : Expression<C> {

override fun invoke(context: C): Any? {
return block(context)
}
}

internal fun Expression<*>.isAssignable() : Boolean {
return this is OpGetVariable && assignmentType == null ||
this is OpIndex && variable is OpGetVariable
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package io.github.alexzhirkevich.skriptie

import io.github.alexzhirkevich.skriptie.javascript.JSInterpretationContext
import kotlin.math.min

public class ExpressionContext : JSInterpretationContext() {

override fun sum(a: Any?, b: Any?): Any? {
return when {
a is List<*> && b is List<*> -> {
a as List<Number>
b as List<Number>

List(min(a.size, b.size)) {
a[it].toDouble() + b[it].toDouble()
}
}

a is List<*> && b is Number -> {
if (a is MutableList<*>) {
a as MutableList<Number>
a[0] = a[0].toDouble() + b.toDouble()
a
} else {
listOf((a as List<Number>).first().toDouble() + b.toDouble()) + a.drop(1)
}
}

a is Number && b is List<*> -> {
if (b is MutableList<*>) {
b as MutableList<Number>
b[0] = b[0].toDouble() + a.toDouble()
b
} else {
listOf(a.toDouble() + (b as List<Number>).first().toDouble()) + b.drop(1)
}
}

else -> super.sum(a, b)
}
}

override fun sub(a: Any?, b: Any?): Any? {
return when {
a is List<*> && b is List<*> -> {
a as List<Number>
b as List<Number>
List(min(a.size, b.size)) {
a[it].toDouble() - b[it].toDouble()
}
}
else -> super.sub(a, b)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package io.github.alexzhirkevich.skriptie

public interface GlobalContext<C : ScriptContext> : InterpretationContext<C> {

public fun isFalse(a : Any?) : Boolean

public fun sum(a : Any?, b : Any?) : Any?
public fun sub(a : Any?, b : Any?) : Any?
public fun mul(a : Any?, b : Any?) : Any?
Expand All @@ -12,4 +14,5 @@ public interface GlobalContext<C : ScriptContext> : InterpretationContext<C> {
public fun dec(a : Any?) : Any

public fun neg(a : Any?) : Any?
public fun pos(a : Any?) : Any?
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,28 @@ package io.github.alexzhirkevich.skriptie
import io.github.alexzhirkevich.skriptie.common.OpAssign


public interface InterpretationContext<C : ScriptContext> : Expression<C> {
public interface InterpretationContext<C : ScriptContext> : ExtensionContext<C>, Expression<C> {

override fun invoke(context: C): Any? = this

public fun interpret(callable: String?, args: List<Expression<C>>?): Expression<C>?

public override fun interpret(parent: Expression<C>, op: String?, args: List<Expression<C>>?): Expression<C>? = null
}

internal fun <C: ScriptContext> List<Expression<C>>.argForNameOrIndex(
index : Int,
vararg name : String,
) : Expression<C>? {

forEach { op ->
if (op is OpAssign && name.any { op.variableName == it }) {
return op.assignableValue
}
}

return argAtOrNull(index)
// forEach { op ->
// if (op is OpAssign && name.any { op.variableName == it }) {
// return op.assignableValue
// }
// }
//
// return argAtOrNull(index)
}

internal fun <C: ScriptContext> List<Expression<C>>.argAt(
Expand All @@ -39,9 +42,10 @@ internal fun <C: ScriptContext> List<Expression<C>>.argAtOrNull(
index : Int,
) : Expression<C>? {

return getOrNull(index).let {
if (it is OpAssign)
it.assignableValue
else it
}
return getOrNull(index)
// /**/.let {
// if (it is OpAssign)
// it.assignableValue
// else it
// }
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package io.github.alexzhirkevich.skriptie

public fun interface Script<C : ScriptContext> {
public operator fun invoke(engine: ScriptEngine<C>): Any?
public operator fun invoke(context: C): Any?
}

public fun <C : ScriptContext> Expression<C>.asScript(): Script<C> = Script { invoke(it.context) }
public fun <C : ScriptContext> Expression<C>.asScript(): Script<C> = Script { invoke(it) }

Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.github.alexzhirkevich.skriptie

import io.github.alexzhirkevich.skriptie.common.SyntaxError
import io.github.alexzhirkevich.skriptie.common.TypeError
import io.github.alexzhirkevich.skriptie.common.unresolvedReference


Expand All @@ -19,13 +21,12 @@ public interface ScriptContext {
extraVariables: Map<String, Pair<VariableType, Any?>> = emptyMap(),
block: (ScriptContext) -> Any?
): Any?

public fun reset()
}

private class BlockScriptContext(
private val parent : ScriptContext
) : BaseScriptContext() {
) : EcmascriptContext() {

override fun getVariable(name: String): Any? {
return if (name in variables) {
Expand All @@ -48,7 +49,7 @@ private class BlockScriptContext(
}
}

public abstract class BaseScriptContext : ScriptContext {
public abstract class EcmascriptContext : ScriptContext {

protected val variables: MutableMap<String, Pair<VariableType, Any?>> = mutableMapOf()

Expand All @@ -65,10 +66,10 @@ public abstract class BaseScriptContext : ScriptContext {
unresolvedReference(name)
}
if (type != null && name in variables) {
error("Identifier '$name' is already declared")
throw SyntaxError("Identifier '$name' is already declared")
}
if (type == null && variables[name]?.first == VariableType.Const) {
error("TypeError: Assignment to constant variable ('$name')")
throw TypeError("Assignment to constant variable ('$name')")
}
variables[name] = (type ?: variables[name]?.first)!! to value
}
Expand All @@ -91,4 +92,4 @@ public abstract class BaseScriptContext : ScriptContext {
override fun reset(){
variables.clear()
}
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
package io.github.alexzhirkevich.skriptie

public interface ScriptEngine<C : ScriptContext> {
public interface ScriptEngine<C : ScriptContext> : ScriptInterpreter<C> {

public val context : C

public fun compile(script : String) : Script<C>

public fun reset()
public fun reset() {
context.reset()
}
}

public fun <C : ScriptContext> ScriptEngine<C>.invoke(script: String) : Any? {
return compile(script).invoke(this)
return interpret(script).invoke(context)
}

public fun <C : ScriptContext> ScriptEngine(
context: C,
interpreter: ScriptInterpreter<C>
): ScriptEngine<C> = object : ScriptEngine<C>, ScriptInterpreter<C> by interpreter {
override val context: C
get() = context
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.github.alexzhirkevich.skriptie

internal interface ScriptInterpreter<C : ScriptContext> {
fun interpret() : Script<C>
public interface ScriptInterpreter<C : ScriptContext> {

public fun interpret(script : String) : Script<C>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.github.alexzhirkevich.skriptie.common

public sealed class SkriptieError(message : String?, cause : Throwable?) : Exception(message, cause)

public class SyntaxError(message : String? = null, cause : Throwable? = null) : SkriptieError(message, cause)

public class TypeError(message : String? = null, cause : Throwable? = null) : SkriptieError(message, cause)

public class ReferenceError(message : String? = null, cause : Throwable? = null) : SkriptieError(message, cause)

internal fun unresolvedReference(ref : String, obj : String? = null) : Nothing =
if (obj != null)
throw ReferenceError("Unresolved reference '$ref' for $obj")
else throw ReferenceError("$ref is not defined")
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package io.github.alexzhirkevich.skriptie.common
import io.github.alexzhirkevich.skriptie.Expression
import io.github.alexzhirkevich.skriptie.ScriptContext


internal class OpBlock<C : ScriptContext>(
val expressions: List<Expression<C>>,
private val scoped : Boolean,
Expand All @@ -25,14 +26,34 @@ internal class OpBlock<C : ScriptContext>(

if (expressions.size > 1) {
repeat(expressions.size - 1) {
val expr = expressions[it]
val res = expr(context)

if (expr is OpReturn<*>) {
return res
}
invoke(expressions[it], context)
}
}
return expressions.last().invoke(context)

return invoke(expressions.last(), context)
}

private fun invoke(expression: Expression<C>, context: C) : Any? {
val res = expression(context)
return when(expression){
is OpReturn -> throw BlockReturn(res)
is OpContinue -> throw BlockContinue
is OpBreak -> throw BlockBreak
else -> res
}
}
}
}


internal sealed class BlockException : Throwable()
internal data object BlockContinue : BlockException()
internal data object BlockBreak : BlockException()
internal class BlockReturn(val value: Any?) : BlockException()

internal class OpReturn<C : ScriptContext>(
val value : Expression<C>
) : Expression<C> by value

internal class OpContinue<C : ScriptContext> : Expression<C> by OpConstant(Unit)
internal class OpBreak<C : ScriptContext> : Expression<C> by OpConstant(Unit)

Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@ import io.github.alexzhirkevich.skriptie.Expression
import io.github.alexzhirkevich.skriptie.ScriptContext

internal fun <C : ScriptContext> OpNot(
condition : Expression<C>
) = Expression<C>{
!(condition(it) as Boolean)
condition : Expression<C>,
isFalse : (Any?) -> Boolean,
) = Expression<C> {
isFalse(condition(it))
}

internal fun <C : ScriptContext> OpBoolean(
a : Expression<C>,
b : Expression<C>,
isFalse : (Any?) -> Boolean,
op : (Boolean, Boolean) -> Boolean,
) = Expression<C> {
op(!a(it).isFalse(), !b(it).isFalse())
op(!isFalse(a(it)), !(isFalse(b(it))))
}

Loading

0 comments on commit 87c4f9a

Please sign in to comment.