Skip to content

Commit

Permalink
classes wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Zhirkevich Alexander Y authored and Zhirkevich Alexander Y committed Sep 13, 2024
1 parent d8598fd commit 9844343
Show file tree
Hide file tree
Showing 26 changed files with 935 additions and 190 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +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.ecmascript.SyntaxError
import io.github.alexzhirkevich.skriptie.ecmascript.TypeError


public enum class VariableType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import io.github.alexzhirkevich.skriptie.VariableType
import io.github.alexzhirkevich.skriptie.argForNameOrIndex
import io.github.alexzhirkevich.skriptie.ecmascript.ESAny
import io.github.alexzhirkevich.skriptie.ecmascript.ESObject
import io.github.alexzhirkevich.skriptie.ecmascript.ESObjectBase
import io.github.alexzhirkevich.skriptie.ecmascript.SyntaxError
import io.github.alexzhirkevich.skriptie.ecmascript.TypeError
import io.github.alexzhirkevich.skriptie.ecmascript.unresolvedReference
import io.github.alexzhirkevich.skriptie.invoke

public class FunctionParam(
Expand All @@ -23,11 +27,33 @@ internal interface Callable {
operator fun invoke(args: List<Expression>, context: ScriptRuntime) : Any?
}


internal class Function(
val name : String,
override val name : String,
val parameters : List<FunctionParam>,
private val body : Expression
) : Callable {
val body : Expression,
var thisRef : Any? = null,
val isClassMember : Boolean = false,
var isStatic : Boolean = false,
val extraVariables: Map<String, Pair<VariableType, Any?>> = emptyMap(),
) : ESObject by ESObjectBase(name), Callable, Named {
override val type: String
get() = "function"

fun copy(
body: Expression = this.body,
extraVariables: Map<String, Pair<VariableType, Any?>> = emptyMap(),
) : Function{
return Function(
name = name,
parameters = parameters,
body = body,
thisRef = thisRef,
isClassMember = isClassMember,
extraVariables = this.extraVariables + extraVariables
)
}

init {
val varargs = parameters.count { it.isVararg }

Expand All @@ -40,53 +66,56 @@ internal class Function(
args: List<Expression>,
context: ScriptRuntime,
): Any? {
try {
return try {
val arguments = buildMap {
parameters.fastForEachIndexed { i, p ->
val value = if (p.isVararg){
val value = if (p.isVararg) {
args.drop(i).fastMap { it(context) }
} else {
requireNotNull(args.argForNameOrIndex(i, p.name) ?: p.default) {
"'${p.name}' argument of '$name' function is missing"
}.invoke(context)
(args.argForNameOrIndex(i, p.name) ?: p.default)
?.invoke(context)
?: Unit
}
this[p.name] = Pair(
VariableType.Local,
value
)
this[p.name] = VariableType.Local to value
}
thisRef?.let {
this["this"] = VariableType.Const to it
}
}
return context.withScope(arguments, body::invoke)
context.withScope(arguments + extraVariables, body::invoke)
} catch (ret: BlockReturn) {
return ret.value
ret.value
}
}
}

internal fun OpFunctionExec(
name : String,
receiver : Expression?,
parameters : List<Expression>,
) = Expression { ctx ->
internal class OpFunctionExec(
override val name : String,
val receiver : Expression?,
val parameters : List<Expression>,
) : Expression, Named {
override fun invokeRaw(context: ScriptRuntime): Any? {
val res = receiver?.invoke(context)
val function = when {
res == null -> context[name]
res is Callable && name.isBlank() -> res
res is ESObject -> res[name]
res is ESAny -> {
return res.invoke(name, context, parameters)
}

val res = receiver?.invoke(ctx)
val function = when {
res == null -> ctx[name]
res is Callable && name.isBlank() -> res
res is ESObject -> res[name]
res is ESAny -> {
return@Expression res.invoke(name, ctx, parameters)
else -> null
}
else -> null
}
if (function is Unit){
unresolvedReference(name)
}
if (function !is Callable){
throw TypeError("$name ($function) is not a function")
if (function is Unit) {
unresolvedReference(name)
}
if (function !is Callable) {
throw TypeError("$name ($function) is not a function")
}
return function.invoke(
args = parameters,
context = context,
)
}
function.invoke(
args = parameters,
context = ctx,
)
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.github.alexzhirkevich.skriptie.common

internal interface Named {

val name : String
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import io.github.alexzhirkevich.skriptie.ScriptRuntime
import io.github.alexzhirkevich.skriptie.VariableType
import io.github.alexzhirkevich.skriptie.ecmascript.ESAny
import io.github.alexzhirkevich.skriptie.ecmascript.ESObject
import io.github.alexzhirkevich.skriptie.ecmascript.TypeError
import io.github.alexzhirkevich.skriptie.invoke

internal class OpAssign(
val type : VariableType? = null,
val variableName : String,
val receiver : Expression?=null,
var isStatic : Boolean = false,
val assignableValue : Expression,
private val merge : ((Any?, Any?) -> Any?)?
) : Expression {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
package io.github.alexzhirkevich.skriptie.common

import io.github.alexzhirkevich.skriptie.Expression
import io.github.alexzhirkevich.skriptie.ScriptRuntime
import io.github.alexzhirkevich.skriptie.invoke

internal fun OpCompare(
a : Expression,
b : Expression,
comparator : (Comparable<*>, Comparable<*>) -> Any
comparator : (Comparable<*>, Comparable<*>, ScriptRuntime) -> Any
) = Expression {
comparator(
a(it) as Comparable<*>,
b(it) as Comparable<*>
b(it) as Comparable<*>,
it
)
}



internal val OpGreaterComparator : (Comparable<*>, Comparable<*>) -> Boolean = { a, b ->
internal val OpGreaterComparator : (Comparable<*>, Comparable<*>, ScriptRuntime) -> Boolean = { a, b, _ ->

if (a is Number && b is Number) {
a.toDouble() > b.toDouble()
Expand All @@ -25,18 +27,19 @@ internal val OpGreaterComparator : (Comparable<*>, Comparable<*>) -> Boolean = {
}
}

internal val OpLessComparator : (Comparable<*>, Comparable<*>) -> Boolean = { a, b ->
internal val OpLessComparator : (Comparable<*>, Comparable<*>, ScriptRuntime) -> Boolean = { a, b, _ ->
if (a is Number && b is Number) {
a.toDouble() < b.toDouble()
} else {
a.toString() < b.toString()
}
}

internal val OpTypedEqualsComparator : (Comparable<*>, Comparable<*>) -> Boolean = { a, b ->
OpEqualsImpl(a, b, true)
internal val OpTypedEqualsComparator : (Comparable<*>, Comparable<*>, ScriptRuntime) -> Boolean = { a, b, r ->
OpEqualsImpl(a, b, true, r)
}

internal val OpEqualsComparator : (Comparable<*>, Comparable<*>) -> Boolean = { a, b ->
OpEqualsImpl(a, b, false)
}
internal val OpEqualsComparator : (Comparable<*>, Comparable<*>,ScriptRuntime) -> Boolean =
{ a, b, r ->
OpEqualsImpl(a, b, false, r)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.github.alexzhirkevich.skriptie.common

import io.github.alexzhirkevich.skriptie.Expression
import io.github.alexzhirkevich.skriptie.ScriptRuntime
import io.github.alexzhirkevich.skriptie.invoke
import io.github.alexzhirkevich.skriptie.javascript.JsWrapper

Expand All @@ -9,22 +10,27 @@ internal fun OpEquals(
b : Expression,
isTyped : Boolean
) = Expression {
OpEqualsImpl(a(it), b(it), isTyped)
OpEqualsImpl(a(it), b(it), isTyped, it)
}

internal tailrec fun OpEqualsImpl(a : Any?, b : Any?, typed : Boolean) : Boolean {
internal fun OpEqualsImpl(a : Any?, b : Any?, typed : Boolean, runtime: ScriptRuntime) : Boolean {

if (!typed) {
if (a is JsWrapper<*>) {
return OpEqualsImpl(a.value, b, typed, runtime)
}

if (b is JsWrapper<*>) {
return OpEqualsImpl(a, b.value, typed, runtime)
}
}

return when {
a == null || b == null -> a == b
a is Number && b is Number -> a.toDouble() == b.toDouble()
typed || a::class == b::class -> {
if (a is JsWrapper<*> && b is JsWrapper<*>) {
OpEqualsImpl(a.value, b.value, typed)
} else {
a == b
}
}
a is String && b is Number -> a.toDoubleOrNull() == b.toDouble()
b is String && a is Number -> b.toDoubleOrNull() == a.toDouble()
typed -> a::class == b::class && OpEqualsImpl(a, b, false, runtime)
a::class == b::class -> a == b
b is Number -> runtime.toNumber(a).toDouble() == b.toDouble()
a is Number -> runtime.toNumber(b).toDouble() == a.toDouble()
else -> a.toString() == b.toString()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import io.github.alexzhirkevich.skriptie.Expression
import io.github.alexzhirkevich.skriptie.ScriptRuntime
import io.github.alexzhirkevich.skriptie.VariableType
import io.github.alexzhirkevich.skriptie.ecmascript.ESAny
import io.github.alexzhirkevich.skriptie.ecmascript.unresolvedReference
import io.github.alexzhirkevich.skriptie.invoke
import kotlin.jvm.JvmInline

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.github.alexzhirkevich.skriptie.common

import io.github.alexzhirkevich.skriptie.Expression
import io.github.alexzhirkevich.skriptie.VariableType
import io.github.alexzhirkevich.skriptie.ecmascript.SyntaxError
import io.github.alexzhirkevich.skriptie.invoke

internal class ThrowableValue(val value : Any?) : Throwable(message = value?.toString()) {
Expand Down
Loading

0 comments on commit 9844343

Please sign in to comment.