fix #28 basic map supports (still no iterators)

This commit is contained in:
sergeych committed 2025-06-16 01:12:04 +04:00
1 parent a4448ab2ff
commit c002204420
13 files changed
+183 -12

No files matched your search

@@ -56,7 +56,7 @@ data class ArgsDeclaration(val params: List<Item>, val endTokenType: Token.Type)
else -> {
println("callArgs: ${callArgs.joinToString()}")
println("tailBlockMode: ${arguments.tailBlockMode}")
context.raiseArgumentError("too few arguments for the call")
context.raiseIllegalArgument("too few arguments for the call")
}
}
assign(a, value)
@@ -77,7 +77,7 @@ data class ArgsDeclaration(val params: List<Item>, val endTokenType: Token.Type)
}
a.defaultValue != null -> a.defaultValue.execute(context)
else -> context.raiseArgumentError("too few arguments for the call")
else -> context.raiseIllegalArgument("too few arguments for the call")
}
assign(a, value)
i--
@@ -98,7 +98,7 @@ data class ArgsDeclaration(val params: List<Item>, val endTokenType: Token.Type)
processEllipsis(leftIndex, end)
} else {
if (leftIndex < callArgs.size)
context.raiseArgumentError("too many arguments for the call")
context.raiseIllegalArgument("too many arguments for the call")
}
}
@@ -23,7 +23,11 @@ class Context(
raiseError(ObjIndexOutOfBoundsException(this, message))
@Suppress("unused")
fun raiseArgumentError(message: String = "Illegal argument error"): Nothing =
fun raiseIllegalArgument(message: String = "Illegal argument error"): Nothing =
raiseError(ObjIllegalArgumentException(this, message))
@Suppress("unused")
fun raiseNoSuchElement(message: String = "No such element"): Nothing =
raiseError(ObjIllegalArgumentException(this, message))
fun raiseClassCastError(msg: String): Nothing = raiseError(ObjClassCastException(this, msg))
@@ -254,6 +254,7 @@ open class Obj {
companion object {
inline fun <reified T> from(obj: T): Obj {
@Suppress("UNCHECKED_CAST")
return when (obj) {
is Obj -> obj
is Double -> ObjReal(obj)
@@ -263,6 +264,7 @@ open class Obj {
is String -> ObjString(obj)
is CharSequence -> ObjString(obj.toString())
is Boolean -> ObjBool(obj)
is Set<*> -> ObjSet((obj as Set<Obj>).toMutableSet())
Unit -> ObjVoid
null -> ObjNull
is Iterator<*> -> ObjKotlinIterator(obj)
@@ -423,6 +425,7 @@ open class ObjException(exceptionClass: ExceptionClass, val context: Context, va
"ClassCastException",
"IndexOutOfBoundsException",
"IllegalArgumentException",
"NoSuchElementException",
"IllegalAssignmentException",
"SymbolNotDefinedException",
"IterationEndException",
@@ -447,8 +450,11 @@ class ObjIndexOutOfBoundsException(context: Context, message: String = "index ou
class ObjIllegalArgumentException(context: Context, message: String = "illegal argument") :
ObjException("IllegalArgumentException", context, message)
class ObjNoSuchElementException(context: Context, message: String = "no such element") :
ObjException("IllegalArgumentException", context, message)
class ObjIllegalAssignmentException(context: Context, message: String = "illegal assignment") :
ObjException("IllegalAssignmentException", context, message)
ObjException("NoSuchElementException", context, message)
class ObjSymbolNotDefinedException(context: Context, message: String = "symbol is not defined") :
ObjException("SymbolNotDefinedException", context, message)
@@ -9,6 +9,10 @@ data class ObjInt(var value: Long) : Obj(), Numeric {
override fun byValueCopy(): Obj = ObjInt(value)
override fun hashCode(): Int {
return value.hashCode()
}
override suspend fun getAndIncrement(context: Context): Obj {
return ObjInt(value).also { value++ }
}
@@ -77,6 +81,8 @@ data class ObjInt(var value: Long) : Obj(), Numeric {
}
companion object {
val Zero = ObjInt(0)
val One = ObjInt(1)
val type = ObjClass("Int")
}
}
@@ -47,7 +47,7 @@ class ObjList(val list: MutableList<Obj> = mutableListOf()) : Obj() {
}
}
else -> context.raiseArgumentError("Illegal index object for a list: ${index.inspect()}")
else -> context.raiseIllegalArgument("Illegal index object for a list: ${index.inspect()}")
}
}
@@ -114,6 +114,11 @@ class ObjList(val list: MutableList<Obj> = mutableListOf()) : Obj() {
return list.map { it.toKotlin(context) }
}
override fun hashCode(): Int {
// check?
return list.hashCode()
}
companion object {
val type = ObjClass("List", ObjArray).apply {
@@ -0,0 +1,71 @@
package net.sergeych.lyng
class ObjMap(val map: MutableMap<Obj,Obj>): Obj() {
override val objClass = type
override suspend fun getAt(context: Context, index: Obj): Obj =
map.getOrElse(index) { context.raiseNoSuchElement() }
override suspend fun contains(context: Context, other: Obj): Boolean {
return other in map
}
override fun toString(): String = map.toString()
companion object {
suspend fun listToMap(context: Context, list: List<Obj>): MutableMap<Obj,Obj> {
val map = mutableMapOf<Obj, Obj>()
if (list.isEmpty()) return map
val first = list.first()
if (first.isInstanceOf(ObjArray)) {
if( first.invokeInstanceMethod(context,"size").toInt() != 2)
context.raiseIllegalArgument(
"list to construct map entry should exactly be 2 element Array like [key,value], got $list"
)
} else context.raiseIllegalArgument("first element of map list be a Collection of 2 elements; got $first")
list.forEach {
map[it.getAt(context,ObjInt.Zero)] = it.getAt(context,ObjInt.One)
}
return map
}
val type = object: ObjClass("Map", ObjCollection) {
override suspend fun callOn(context: Context): Obj {
return ObjMap(listToMap(context, context.args.list))
}
}.apply {
addFn("getOrNull") {
val key = args.firstAndOnly(pos)
thisAs<ObjMap>().map.getOrElse(key) { ObjNull }
}
addFn("getOrPut") {
val key = requiredArg<Obj>(0)
thisAs<ObjMap>().map.getOrPut(key) {
val lambda = requiredArg<Statement>(1)
lambda.execute(this)
}
}
addFn("size") {
thisAs<ObjMap>().map.size.toObj()
}
addFn("remove") {
thisAs<ObjMap>().map.remove(requiredArg<Obj>(0))?.toObj() ?: ObjNull
}
addFn("clear") {
thisAs<ObjMap>().map.clear()
thisObj
}
addFn("keys") {
thisAs<ObjMap>().map.keys.toObj()
}
addFn("values") {
ObjList(thisAs<ObjMap>().map.values.toMutableList())
}
}
}
}
@@ -10,6 +10,8 @@ data class ObjReal(val value: Double) : Obj(), Numeric {
override val toObjInt: ObjInt by lazy { ObjInt(longValue) }
override val toObjReal: ObjReal by lazy { ObjReal(value) }
override val objClass: ObjClass = type
override fun byValueCopy(): Obj = ObjReal(value)
override suspend fun compareTo(context: Context, other: Obj): Int {
@@ -19,7 +21,9 @@ data class ObjReal(val value: Double) : Obj(), Numeric {
override fun toString(): String = value.toString()
override val objClass: ObjClass = type
override fun hashCode(): Int {
return value.hashCode()
}
override suspend fun plus(context: Context, other: Obj): Obj =
ObjReal(this.value + other.toDouble())
@@ -44,12 +44,12 @@ class ObjSet(val set: MutableSet<Obj> = mutableSetOf()) : Obj() {
return if (other is ObjSet) {
ObjSet(set.intersect(other.set).toMutableSet())
} else
context.raiseArgumentError("set operator * requires another set")
context.raiseIllegalArgument("set operator * requires another set")
}
override suspend fun minus(context: Context, other: Obj): Obj {
if (other !is ObjSet)
context.raiseArgumentError("set operator - requires another set")
context.raiseIllegalArgument("set operator - requires another set")
return ObjSet(set.minus(other.set).toMutableSet())
}
@@ -66,6 +66,8 @@ class ObjSet(val set: MutableSet<Obj> = mutableSetOf()) : Obj() {
}
companion object {
val type = object : ObjClass("Set", ObjCollection) {
override suspend fun callOn(context: Context): Obj {
return ObjSet(context.args.list.toMutableSet())
@@ -46,7 +46,11 @@ data class ObjString(val value: String) : Obj() {
}
return ObjString(value.substring(start, end))
}
context.raiseArgumentError("String index must be Int or Range")
context.raiseIllegalArgument("String index must be Int or Range")
}
override fun hashCode(): Int {
return value.hashCode()
}
override suspend fun callOn(context: Context): Obj {
@@ -58,7 +62,7 @@ data class ObjString(val value: String) : Obj() {
value.contains(other.value)
else if (other is ObjChar)
value.contains(other.value)
else context.raiseArgumentError("String.contains can't take $other")
else context.raiseIllegalArgument("String.contains can't take $other")
}
companion object {
@@ -154,6 +154,7 @@ class Script(
addConst("List", ObjList.type)
addConst("Set", ObjSet.type)
addConst("Range", ObjRange.type)
addConst("Map", ObjMap.type)
@Suppress("RemoveRedundantQualifierName")
addConst("Callable", Statement.type)
// interfaces