operators overriding
This commit is contained in:
1 parent
fe5dded7af
commit
2c0a6c7b34
24 files changed
+216
-57
No files matched your search
@@ -1351,8 +1351,11 @@ class Compiler(
|
||||
|
||||
val isMember = (codeContexts.lastOrNull() is CodeContext.ClassBody)
|
||||
|
||||
if (!isMember && (isOverride || isClosed))
|
||||
throw ScriptError(currentToken.pos, "modifiers override and closed are only allowed for class members")
|
||||
if (!isMember && isClosed)
|
||||
throw ScriptError(currentToken.pos, "modifier closed is only allowed for class members")
|
||||
|
||||
if (!isMember && isOverride && currentToken.value != "fun" && currentToken.value != "fn")
|
||||
throw ScriptError(currentToken.pos, "modifier override outside class is only allowed for extension functions")
|
||||
|
||||
if (!isMember && isAbstract && currentToken.value != "class")
|
||||
throw ScriptError(currentToken.pos, "modifier abstract at top level is only allowed for classes")
|
||||
|
||||
@@ -143,11 +143,17 @@ open class Obj {
|
||||
open suspend fun compareTo(scope: Scope, other: Obj): Int {
|
||||
if (other === this) return 0
|
||||
if (other === ObjNull || other === ObjUnset || other === ObjVoid) return 2
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "compareTo", Arguments(other)) {
|
||||
scope.raiseNotImplemented("compareTo for ${objClass.className}")
|
||||
}.cast<ObjInt>(scope).toInt()
|
||||
}
|
||||
|
||||
open suspend fun equals(scope: Scope, other: Obj): Boolean {
|
||||
if (other === this) return true
|
||||
val m = objClass.getInstanceMemberOrNull("equals") ?: scope.findExtension(objClass, "equals")
|
||||
if (m != null) {
|
||||
return invokeInstanceMethod(scope, "equals", Arguments(other)).toBool()
|
||||
}
|
||||
return try {
|
||||
compareTo(scope, other) == 0
|
||||
} catch (e: ExecutionError) {
|
||||
@@ -225,46 +231,66 @@ open class Obj {
|
||||
* Class of the object: definition of member functions (top-level), etc.
|
||||
* Note that using lazy allows to avoid endless recursion here
|
||||
*/
|
||||
open val objClass: ObjClass = rootObjectType
|
||||
open val objClass: ObjClass get() = rootObjectType
|
||||
|
||||
open suspend fun plus(scope: Scope, other: Obj): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "plus", Arguments(other)) {
|
||||
scope.raiseNotImplemented("plus for ${objClass.className}")
|
||||
}
|
||||
}
|
||||
|
||||
open suspend fun minus(scope: Scope, other: Obj): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "minus", Arguments(other)) {
|
||||
scope.raiseNotImplemented("minus for ${objClass.className}")
|
||||
}
|
||||
}
|
||||
|
||||
open suspend fun negate(scope: Scope): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "negate", Arguments.EMPTY) {
|
||||
scope.raiseNotImplemented("negate for ${objClass.className}")
|
||||
}
|
||||
}
|
||||
|
||||
open suspend fun mul(scope: Scope, other: Obj): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "mul", Arguments(other)) {
|
||||
scope.raiseNotImplemented("mul for ${objClass.className}")
|
||||
}
|
||||
}
|
||||
|
||||
open suspend fun div(scope: Scope, other: Obj): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "div", Arguments(other)) {
|
||||
scope.raiseNotImplemented("div for ${objClass.className}")
|
||||
}
|
||||
}
|
||||
|
||||
open suspend fun mod(scope: Scope, other: Obj): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "mod", Arguments(other)) {
|
||||
scope.raiseNotImplemented("mod for ${objClass.className}")
|
||||
}
|
||||
}
|
||||
|
||||
open suspend fun logicalNot(scope: Scope): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "logicalNot", Arguments.EMPTY) {
|
||||
scope.raiseNotImplemented("logicalNot for ${objClass.className}")
|
||||
}
|
||||
}
|
||||
|
||||
open suspend fun logicalAnd(scope: Scope, other: Obj): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "logicalAnd", Arguments(other)) {
|
||||
scope.raiseNotImplemented("logicalAnd for ${objClass.className}")
|
||||
}
|
||||
}
|
||||
|
||||
open suspend fun logicalOr(scope: Scope, other: Obj): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "logicalOr", Arguments(other)) {
|
||||
scope.raiseNotImplemented("logicalOr for ${objClass.className}")
|
||||
}
|
||||
}
|
||||
|
||||
open suspend fun operatorMatch(scope: Scope, other: Obj): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "operatorMatch", Arguments(other)) {
|
||||
scope.raiseNotImplemented("operatorMatch for ${objClass.className}")
|
||||
}
|
||||
}
|
||||
|
||||
open suspend fun operatorNotMatch(scope: Scope, other: Obj): Obj {
|
||||
@@ -273,27 +299,39 @@ open class Obj {
|
||||
|
||||
// Bitwise ops default (override in numeric types that support them)
|
||||
open suspend fun bitAnd(scope: Scope, other: Obj): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "bitAnd", Arguments(other)) {
|
||||
scope.raiseNotImplemented("bitAnd for ${objClass.className}")
|
||||
}
|
||||
}
|
||||
|
||||
open suspend fun bitOr(scope: Scope, other: Obj): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "bitOr", Arguments(other)) {
|
||||
scope.raiseNotImplemented("bitOr for ${objClass.className}")
|
||||
}
|
||||
}
|
||||
|
||||
open suspend fun bitXor(scope: Scope, other: Obj): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "bitXor", Arguments(other)) {
|
||||
scope.raiseNotImplemented("bitXor for ${objClass.className}")
|
||||
}
|
||||
}
|
||||
|
||||
open suspend fun shl(scope: Scope, other: Obj): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "shl", Arguments(other)) {
|
||||
scope.raiseNotImplemented("shl for ${objClass.className}")
|
||||
}
|
||||
}
|
||||
|
||||
open suspend fun shr(scope: Scope, other: Obj): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "shr", Arguments(other)) {
|
||||
scope.raiseNotImplemented("shr for ${objClass.className}")
|
||||
}
|
||||
}
|
||||
|
||||
open suspend fun bitNot(scope: Scope): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
return invokeInstanceMethod(scope, "bitNot", Arguments.EMPTY) {
|
||||
scope.raiseNotImplemented("bitNot for ${objClass.className}")
|
||||
}
|
||||
}
|
||||
|
||||
open suspend fun assign(scope: Scope, other: Obj): Obj? = null
|
||||
@@ -305,15 +343,43 @@ open class Obj {
|
||||
* if( the operation is not defined, it returns null and the compiler would try
|
||||
* to generate it as 'this = this + other', reassigning its variable
|
||||
*/
|
||||
open suspend fun plusAssign(scope: Scope, other: Obj): Obj? = null
|
||||
open suspend fun plusAssign(scope: Scope, other: Obj): Obj? {
|
||||
val m = objClass.getInstanceMemberOrNull("plusAssign") ?: scope.findExtension(objClass, "plusAssign")
|
||||
return if (m != null) {
|
||||
invokeInstanceMethod(scope, "plusAssign", Arguments(other))
|
||||
} else null
|
||||
}
|
||||
|
||||
/**
|
||||
* `-=` operations, see [plusAssign]
|
||||
*/
|
||||
open suspend fun minusAssign(scope: Scope, other: Obj): Obj? = null
|
||||
open suspend fun mulAssign(scope: Scope, other: Obj): Obj? = null
|
||||
open suspend fun divAssign(scope: Scope, other: Obj): Obj? = null
|
||||
open suspend fun modAssign(scope: Scope, other: Obj): Obj? = null
|
||||
open suspend fun minusAssign(scope: Scope, other: Obj): Obj? {
|
||||
val m = objClass.getInstanceMemberOrNull("minusAssign") ?: scope.findExtension(objClass, "minusAssign")
|
||||
return if (m != null) {
|
||||
invokeInstanceMethod(scope, "minusAssign", Arguments(other))
|
||||
} else null
|
||||
}
|
||||
|
||||
open suspend fun mulAssign(scope: Scope, other: Obj): Obj? {
|
||||
val m = objClass.getInstanceMemberOrNull("mulAssign") ?: scope.findExtension(objClass, "mulAssign")
|
||||
return if (m != null) {
|
||||
invokeInstanceMethod(scope, "mulAssign", Arguments(other))
|
||||
} else null
|
||||
}
|
||||
|
||||
open suspend fun divAssign(scope: Scope, other: Obj): Obj? {
|
||||
val m = objClass.getInstanceMemberOrNull("divAssign") ?: scope.findExtension(objClass, "divAssign")
|
||||
return if (m != null) {
|
||||
invokeInstanceMethod(scope, "divAssign", Arguments(other))
|
||||
} else null
|
||||
}
|
||||
|
||||
open suspend fun modAssign(scope: Scope, other: Obj): Obj? {
|
||||
val m = objClass.getInstanceMemberOrNull("modAssign") ?: scope.findExtension(objClass, "modAssign")
|
||||
return if (m != null) {
|
||||
invokeInstanceMethod(scope, "modAssign", Arguments(other))
|
||||
} else null
|
||||
}
|
||||
|
||||
open suspend fun getAndIncrement(scope: Scope): Obj {
|
||||
scope.raiseNotImplemented()
|
||||
|
||||
@@ -23,7 +23,7 @@ import net.sergeych.lynon.BitArray
|
||||
|
||||
class ObjBitBuffer(val bitArray: BitArray) : Obj() {
|
||||
|
||||
override val objClass = type
|
||||
override val objClass get() = type
|
||||
|
||||
override suspend fun getAt(scope: Scope, index: Obj): Obj {
|
||||
return bitArray[index.toLong()].toObj()
|
||||
|
||||
@@ -37,7 +37,7 @@ data class ObjBool(val value: Boolean) : Obj() {
|
||||
|
||||
override fun toString(): String = value.toString()
|
||||
|
||||
override val objClass: ObjClass = type
|
||||
override val objClass: ObjClass get() = type
|
||||
|
||||
override suspend fun logicalNot(scope: Scope): Obj = ObjBool(!value)
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ import kotlin.math.min
|
||||
|
||||
open class ObjBuffer(val byteArray: UByteArray) : Obj() {
|
||||
|
||||
override val objClass: ObjClass = type
|
||||
override val objClass: ObjClass get() = type
|
||||
|
||||
val hex by lazy { byteArray.encodeToHex("")}
|
||||
val base64 by lazy { byteArray.toByteArray().encodeToBase64Url()}
|
||||
|
||||
@@ -23,7 +23,7 @@ import net.sergeych.lyng.miniast.type
|
||||
|
||||
class ObjChar(val value: Char): Obj() {
|
||||
|
||||
override val objClass: ObjClass = type
|
||||
override val objClass: ObjClass get() = type
|
||||
|
||||
override suspend fun compareTo(scope: Scope, other: Obj): Int =
|
||||
(other as? ObjChar)?.let { value.compareTo(it.value) } ?: -1
|
||||
|
||||
@@ -25,7 +25,7 @@ import net.sergeych.lyng.miniast.type
|
||||
|
||||
class ObjCompletableDeferred(val completableDeferred: CompletableDeferred<Obj>): ObjDeferred(completableDeferred) {
|
||||
|
||||
override val objClass = type
|
||||
override val objClass get() = type
|
||||
|
||||
companion object {
|
||||
val type = object: ObjClass("CompletableDeferred", ObjDeferred.type){
|
||||
|
||||
@@ -24,7 +24,7 @@ import net.sergeych.lyng.miniast.type
|
||||
|
||||
open class ObjDeferred(val deferred: Deferred<Obj>): Obj() {
|
||||
|
||||
override val objClass = type
|
||||
override val objClass get() = type
|
||||
|
||||
companion object {
|
||||
val type = object: ObjClass("Deferred"){
|
||||
|
||||
@@ -29,7 +29,7 @@ import kotlin.time.Duration.Companion.seconds
|
||||
import kotlin.time.DurationUnit
|
||||
|
||||
class ObjDuration(val duration: Duration) : Obj() {
|
||||
override val objClass: ObjClass = type
|
||||
override val objClass: ObjClass get() = type
|
||||
|
||||
override fun toString(): String {
|
||||
return duration.toString()
|
||||
|
||||
@@ -23,7 +23,7 @@ import net.sergeych.lyng.Scope
|
||||
import net.sergeych.lyng.Statement
|
||||
|
||||
class ObjDynamicContext(val delegate: ObjDynamic) : Obj() {
|
||||
override val objClass: ObjClass = type
|
||||
override val objClass: ObjClass get() = type
|
||||
|
||||
companion object {
|
||||
val type = ObjClass("DelegateContext").apply {
|
||||
@@ -54,7 +54,7 @@ class ObjDynamicContext(val delegate: ObjDynamic) : Obj() {
|
||||
*/
|
||||
open class ObjDynamic(var readCallback: Statement? = null, var writeCallback: Statement? = null) : Obj() {
|
||||
|
||||
override val objClass: ObjClass = type
|
||||
override val objClass: ObjClass get() = type
|
||||
// Capture the lexical scope used to build this dynamic so callbacks can see outer locals
|
||||
internal var builderScope: Scope? = null
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ import kotlin.coroutines.cancellation.CancellationException
|
||||
|
||||
class ObjFlowBuilder(val output: SendChannel<Obj>) : Obj() {
|
||||
|
||||
override val objClass = type
|
||||
override val objClass get() = type
|
||||
|
||||
companion object {
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
@@ -91,7 +91,7 @@ private fun createLyngFlowInput(scope: Scope, producer: Statement): ReceiveChann
|
||||
|
||||
class ObjFlow(val producer: Statement, val scope: Scope) : Obj() {
|
||||
|
||||
override val objClass = type
|
||||
override val objClass get() = type
|
||||
|
||||
companion object {
|
||||
val type = object : ObjClass("Flow", ObjIterable) {
|
||||
@@ -119,7 +119,7 @@ class ObjFlow(val producer: Statement, val scope: Scope) : Obj() {
|
||||
|
||||
class ObjFlowIterator(val producer: Statement) : Obj() {
|
||||
|
||||
override val objClass: ObjClass = type
|
||||
override val objClass: ObjClass get() = type
|
||||
|
||||
private var channel: ReceiveChannel<Obj>? = null
|
||||
|
||||
|
||||
@@ -42,9 +42,6 @@ class ObjInstanceClass(val name: String, vararg parents: ObjClass) : ObjClass(na
|
||||
}
|
||||
|
||||
init {
|
||||
addFn("toString", true) {
|
||||
thisObj.toString(this, true)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,7 +29,7 @@ import net.sergeych.lyng.Scope
|
||||
*/
|
||||
class ObjKotlinIterator(val iterator: Iterator<Any?>) : Obj() {
|
||||
|
||||
override val objClass = type
|
||||
override val objClass get() = type
|
||||
|
||||
companion object {
|
||||
val type = ObjClass("KotlinIterator", ObjIterator).apply {
|
||||
@@ -46,7 +46,7 @@ class ObjKotlinIterator(val iterator: Iterator<Any?>) : Obj() {
|
||||
*/
|
||||
class ObjKotlinObjIterator(val iterator: Iterator<Obj>) : Obj() {
|
||||
|
||||
override val objClass = type
|
||||
override val objClass get() = type
|
||||
|
||||
companion object {
|
||||
val type = ObjClass("KotlinIterator", ObjIterator).apply {
|
||||
|
||||
@@ -56,7 +56,7 @@ class ObjMapEntry(val key: Obj, val value: Obj) : Obj() {
|
||||
return ObjString("(${key.toString(scope).value} => ${value.toString(scope).value})")
|
||||
}
|
||||
|
||||
override val objClass = type
|
||||
override val objClass get() = type
|
||||
|
||||
override suspend fun serialize(scope: Scope, encoder: LynonEncoder, lynonType: LynonType?) {
|
||||
encoder.encodeAny(scope,key)
|
||||
@@ -106,7 +106,7 @@ class ObjMapEntry(val key: Obj, val value: Obj) : Obj() {
|
||||
|
||||
class ObjMap(val map: MutableMap<Obj, Obj> = mutableMapOf()) : Obj() {
|
||||
|
||||
override val objClass = type
|
||||
override val objClass get() = type
|
||||
|
||||
override suspend fun getAt(scope: Scope, index: Obj): Obj =
|
||||
map.get(index) ?: ObjNull
|
||||
|
||||
@@ -26,7 +26,7 @@ import net.sergeych.lyng.miniast.addFnDoc
|
||||
import net.sergeych.lyng.miniast.type
|
||||
|
||||
class ObjMutex(val mutex: Mutex): Obj() {
|
||||
override val objClass = type
|
||||
override val objClass get() = type
|
||||
|
||||
companion object {
|
||||
val type = object: ObjClass("Mutex") {
|
||||
|
||||
@@ -27,7 +27,7 @@ class ObjRange(val start: Obj?, val end: Obj?, val isEndInclusive: Boolean) : Ob
|
||||
val isOpenStart by lazy { start == null || start.isNull }
|
||||
val isOpenEnd by lazy { end == null || end.isNull }
|
||||
|
||||
override val objClass: ObjClass = type
|
||||
override val objClass: ObjClass get() = type
|
||||
|
||||
override suspend fun defaultToString(scope: Scope): ObjString {
|
||||
val result = StringBuilder()
|
||||
|
||||
@@ -26,7 +26,7 @@ class ObjRangeIterator(val self: ObjRange) : Obj() {
|
||||
private var lastIndex = 0
|
||||
private var isCharRange: Boolean = false
|
||||
|
||||
override val objClass: ObjClass = type
|
||||
override val objClass: ObjClass get() = type
|
||||
|
||||
fun Scope.init() {
|
||||
val s = self.start
|
||||
@@ -84,7 +84,7 @@ class ObjFastIntRangeIterator(private val start: Int, private val endExclusive:
|
||||
|
||||
private var cur: Int = start
|
||||
|
||||
override val objClass: ObjClass = type
|
||||
override val objClass: ObjClass get() = type
|
||||
|
||||
fun hasNext(): Boolean = cur < endExclusive
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ data class ObjReal(val value: Double) : Obj(), Numeric {
|
||||
override val toObjInt: ObjInt get() = ObjInt.of(longValue)
|
||||
override val toObjReal: ObjReal get() = this
|
||||
|
||||
override val objClass: ObjClass = type
|
||||
override val objClass: ObjClass get() = type
|
||||
|
||||
override fun byValueCopy(): Obj = this
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import net.sergeych.lyng.miniast.addFnDoc
|
||||
import net.sergeych.lyng.miniast.type
|
||||
|
||||
class ObjRegex(val regex: Regex) : Obj() {
|
||||
override val objClass = type
|
||||
override val objClass get() = type
|
||||
|
||||
override suspend fun operatorMatch(scope: Scope, other: Obj): Obj {
|
||||
return regex.find(other.cast<ObjString>(scope).value)?.let {
|
||||
@@ -81,7 +81,7 @@ class ObjRegex(val regex: Regex) : Obj() {
|
||||
}
|
||||
|
||||
class ObjRegexMatch(val match: MatchResult) : Obj() {
|
||||
override val objClass = type
|
||||
override val objClass get() = type
|
||||
|
||||
val objGroups: ObjList by lazy {
|
||||
// Use groupValues so that index 0 is the whole match and subsequent indices are capturing groups,
|
||||
|
||||
@@ -81,7 +81,7 @@ class RingBuffer<T>(val maxSize: Int) : Iterable<T> {
|
||||
class ObjRingBuffer(val capacity: Int) : Obj() {
|
||||
val buffer = RingBuffer<Obj>(capacity)
|
||||
|
||||
override val objClass: ObjClass = type
|
||||
override val objClass: ObjClass get() = type
|
||||
|
||||
override suspend fun plusAssign(scope: Scope, other: Obj): Obj {
|
||||
buffer.add(other.byValueCopy())
|
||||
|
||||
@@ -28,7 +28,7 @@ import net.sergeych.lynon.LynonType
|
||||
|
||||
class ObjSet(val set: MutableSet<Obj> = mutableSetOf()) : Obj() {
|
||||
|
||||
override val objClass = type
|
||||
override val objClass get() = type
|
||||
|
||||
override suspend fun contains(scope: Scope, other: Obj): Boolean {
|
||||
return set.contains(other)
|
||||
|
||||
Reference in new issue
Block a user