diff --git a/skriptie/src/commonMain/kotlin/io/github/alexzhirkevich/skriptie/common/OpCompare.kt b/skriptie/src/commonMain/kotlin/io/github/alexzhirkevich/skriptie/common/OpCompare.kt index a012a8c..b037487 100644 --- a/skriptie/src/commonMain/kotlin/io/github/alexzhirkevich/skriptie/common/OpCompare.kt +++ b/skriptie/src/commonMain/kotlin/io/github/alexzhirkevich/skriptie/common/OpCompare.kt @@ -25,18 +25,24 @@ internal fun OpNot( -internal val OpGreaterComparator : (Comparable<*>, Comparable<*>, ScriptRuntime) -> Boolean = { a, b, _ -> +internal val OpGreaterComparator : (Comparable<*>, Comparable<*>, ScriptRuntime) -> Boolean = { a, b, r -> - if (a is Number && b is Number) { - a.toDouble() > b.toDouble() + val ka = r.toKotlin(a) + val kb = r.toKotlin(b) + + if (ka is Number || kb is Number) { + r.toNumber(a).toDouble() > r.toNumber(b).toDouble() } else { a.toString() > b.toString() } } -internal val OpLessComparator : (Comparable<*>, Comparable<*>, ScriptRuntime) -> Boolean = { a, b, _ -> - if (a is Number && b is Number) { - a.toDouble() < b.toDouble() +internal val OpLessComparator : (Comparable<*>, Comparable<*>, ScriptRuntime) -> Boolean = { a, b, r -> + val ka = r.toKotlin(a) + val kb = r.toKotlin(b) + + if (ka is Number || kb is Number) { + r.toNumber(a).toDouble() < r.toNumber(b).toDouble() } else { a.toString() < b.toString() } diff --git a/skriptie/src/commonMain/kotlin/io/github/alexzhirkevich/skriptie/ecmascript/ESInterpreterImpl.kt b/skriptie/src/commonMain/kotlin/io/github/alexzhirkevich/skriptie/ecmascript/ESInterpreterImpl.kt index 2531e65..b6e7c32 100644 --- a/skriptie/src/commonMain/kotlin/io/github/alexzhirkevich/skriptie/ecmascript/ESInterpreterImpl.kt +++ b/skriptie/src/commonMain/kotlin/io/github/alexzhirkevich/skriptie/ecmascript/ESInterpreterImpl.kt @@ -216,7 +216,8 @@ internal class ESInterpreterImpl( parseExpressionOp( context = context, blockContext = blockContext, - isExpressionStart = isExpressionStart + isExpressionStart = isExpressionStart, + factorOnly = unaryOnly ) } else { OpGetVariable(variableName, receiver = null) @@ -317,7 +318,7 @@ internal class ESInterpreterImpl( eatSequence("=>") -> OpConstant(parseArrowFunction(listOf(x), blockContext)) - eat('=') -> { + eatAndExpectNot('=', '='::equals) -> { checkAssignment() parseAssignmentValue(x, null) } @@ -406,10 +407,14 @@ internal class ESInterpreterImpl( context: Expression, logicalContext: LogicalContext? = null, blockContext: List, - isExpressionStart: Boolean = false + isExpressionStart: Boolean = false, + factorOnly : Boolean = false ): Expression { - var x = parseOperator3(context, logicalContext, blockContext, isExpressionStart) - + var x = if (factorOnly) { + parseFactorOp(context, blockContext, isExpressionStart) + } else { + parseOperator3(context, logicalContext, blockContext, isExpressionStart) + } while (true){ prepareNextChar() x = when { diff --git a/skriptie/src/commonMain/kotlin/io/github/alexzhirkevich/skriptie/javascript/JSLangContext.kt b/skriptie/src/commonMain/kotlin/io/github/alexzhirkevich/skriptie/javascript/JSLangContext.kt index 481cf47..84e69dc 100644 --- a/skriptie/src/commonMain/kotlin/io/github/alexzhirkevich/skriptie/javascript/JSLangContext.kt +++ b/skriptie/src/commonMain/kotlin/io/github/alexzhirkevich/skriptie/javascript/JSLangContext.kt @@ -221,9 +221,16 @@ private tailrec fun Any?.numberOrNull(withNaNs : Boolean = true) : Number? = whe null -> 0L true -> 1L false -> 0L - is JsString -> if (withNaNs) value.numberOrNull(withNaNs) else null - is JsArray -> if (withNaNs) value.numberOrNull(withNaNs) else null - is JsWrapper<*> -> value.numberOrNull() + + + is CharSequence -> when { + isEmpty() -> 0L + withNaNs -> { + val s = trim().toString() + s.toLongOrNull() ?: s.toDoubleOrNull() + } + else -> null + } is Byte -> toLong() is UByte -> toLong() is Short -> toLong() @@ -234,10 +241,6 @@ private tailrec fun Any?.numberOrNull(withNaNs : Boolean = true) : Number? = whe is Float -> toDouble() is Long -> this is Double -> this - is String -> if (withNaNs) { - val t = trim() - t.toLongOrNull() ?: t.toDoubleOrNull() - } else null is List<*> -> { if (withNaNs) { singleOrNull()?.numberOrNull(withNaNs) @@ -245,6 +248,7 @@ private tailrec fun Any?.numberOrNull(withNaNs : Boolean = true) : Number? = whe null } } + is JsWrapper<*> -> value.numberOrNull() else -> null } diff --git a/skriptie/src/commonTest/kotlin/js/ComparisonTest.kt b/skriptie/src/commonTest/kotlin/js/ComparisonTest.kt new file mode 100644 index 0000000..e4c5ad8 --- /dev/null +++ b/skriptie/src/commonTest/kotlin/js/ComparisonTest.kt @@ -0,0 +1,22 @@ +package js + +import kotlin.test.Test + +class ComparisonTest { + + @Test + fun number_string(){ + "'1' > 2".eval().assertEqualsTo(false) + "'1' == 1".eval().assertEqualsTo(true) + "'1' === 1".eval().assertEqualsTo(false) + + "'test' == 0".eval().assertEqualsTo(false) + "'test' == NaN".eval().assertEqualsTo(false) + + "'00100' < '1'".eval().assertEqualsTo(true) + "'00100' < 1".eval().assertEqualsTo(false) + + " +'2' > +'10'".eval().assertEqualsTo(false) + "'2' > '10'".eval().assertEqualsTo(true) + } +} \ No newline at end of file diff --git a/skriptie/src/commonTest/kotlin/js/SyntaxTest.kt b/skriptie/src/commonTest/kotlin/js/SyntaxTest.kt index fb3006c..d06adc2 100644 --- a/skriptie/src/commonTest/kotlin/js/SyntaxTest.kt +++ b/skriptie/src/commonTest/kotlin/js/SyntaxTest.kt @@ -152,8 +152,10 @@ class SyntaxTest { "typeof null".eval().assertEqualsTo("object") "typeof undefined".eval().assertEqualsTo("undefined") - "typeof 1===1".eval().assertEqualsTo("boolean") + "typeof 1===1".eval().assertEqualsTo(false) + "typeof 1>2".eval().assertEqualsTo(false) + "let x = 1; typeof ++x".eval().assertEqualsTo("number") "let x = 1; typeof x++".eval().assertEqualsTo("number") assertFailsWith { "let x = 1; typeof x = 2".eval()