diff --git a/README.md b/README.md index 9fc0b38..9351da8 100644 --- a/README.md +++ b/README.md @@ -75,21 +75,23 @@ runBlocking { ### Exchanging information -Script is executed over some `Context`. Create instance of the context, -add your specific vars and functions to it, an call over it: +Script is executed over some `Scope`. Create instance, +add your specific vars and functions to it, and call: ```kotlin -import new.sergeych.lyng.* + +import com.sun.source.tree.Scope +import new.sergeych.lyng.* // simple function -val context = Context().apply { +val scope = Scope().apply { addFn("addArgs") { var sum = 0.0 - for( a in args) sum += a.toDouble() + for (a in args) sum += a.toDouble() ObjReal(sum) } addConst("LIGHT_SPEED", ObjReal(299_792_458.0)) - + // callback back to kotlin to some suspend fn, for example:: // suspend fun doSomeWork(text: String): Int addFn("doSomeWork") { @@ -99,9 +101,9 @@ val context = Context().apply { } } // adding constant: -context.eval("addArgs(1,2,3)") // <- 6 +scope.eval("addArgs(1,2,3)") // <- 6 ``` -Note that the context stores all changes in it so you can make calls on a single context to preserve state between calls. +Note that the scope stores all changes in it so you can make calls on a single scope to preserve state between calls. ## Why? diff --git a/lyng/src/commonMain/kotlin/Common.kt b/lyng/src/commonMain/kotlin/Common.kt index 01d7e87..76e3e31 100644 --- a/lyng/src/commonMain/kotlin/Common.kt +++ b/lyng/src/commonMain/kotlin/Common.kt @@ -31,7 +31,7 @@ data class CommandResult( val error: String ) -val baseContext = Context().apply { +val baseScope = Scope().apply { addFn("exit") { exit(requireOnlyArg().toInt()) ObjVoid @@ -74,7 +74,7 @@ class Lyng(val launcher: (suspend () -> Unit) -> Unit) : CliktCommand() { val objargs = mutableListOf() script?.let { objargs += it } objargs += args - baseContext.addConst( + baseScope.addConst( "ARGV", ObjList( objargs.map { ObjString(it) }.toMutableList() ) @@ -82,7 +82,7 @@ class Lyng(val launcher: (suspend () -> Unit) -> Unit) : CliktCommand() { launcher { // there is no script name, it is a first argument instead: processErrors { - baseContext.eval(execute!!) + baseScope.eval(execute!!) } } } @@ -98,7 +98,7 @@ class Lyng(val launcher: (suspend () -> Unit) -> Unit) : CliktCommand() { ) echoFormattedHelp() } else { - baseContext.addConst("ARGV", ObjList(args.map { ObjString(it) }.toMutableList())) + baseScope.addConst("ARGV", ObjList(args.map { ObjString(it) }.toMutableList())) launcher { executeFile(script!!) } } } @@ -118,7 +118,7 @@ suspend fun executeFile(fileName: String) { text = text.substring(pos + 1) } processErrors { - Compiler.compile(Source(fileName, text)).execute(baseContext) + Compiler.compile(Source(fileName, text)).execute(baseScope) } } diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/AppliedContext.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/AppliedContext.kt deleted file mode 100644 index ac829c9..0000000 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/AppliedContext.kt +++ /dev/null @@ -1,17 +0,0 @@ -package net.sergeych.lyng - -/** - * Special version of the [Context] used to `apply` new this object to - * _parent context property. - * - * @param _parent context to apply to - * @param args arguments for the new context - * @param appliedContext the new context to apply, it will have lower priority except for `this` which - * will be reset by appliedContext's `this`. - */ -class AppliedContext(_parent: Context, args: Arguments, val appliedContext: Context) - : Context(_parent, args, appliedContext.pos, appliedContext.thisObj) { - override fun get(name: String): ObjRecord? = - if (name == "this") thisObj.asReadonly - else super.get(name) ?: appliedContext[name] -} \ No newline at end of file diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/AppliedScope.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/AppliedScope.kt new file mode 100644 index 0000000..8980fec --- /dev/null +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/AppliedScope.kt @@ -0,0 +1,17 @@ +package net.sergeych.lyng + +/** + * Special version of the [Scope] used to `apply` new this object to + * _parent context property. + * + * @param _parent context to apply to + * @param args arguments for the new context + * @param appliedScope the new context to apply, it will have lower priority except for `this` which + * will be reset by appliedContext's `this`. + */ +class AppliedScope(_parent: Scope, args: Arguments, val appliedScope: Scope) + : Scope(_parent, args, appliedScope.pos, appliedScope.thisObj) { + override fun get(name: String): ObjRecord? = + if (name == "this") thisObj.asReadonly + else super.get(name) ?: appliedScope[name] +} \ No newline at end of file diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ArgsDeclaration.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ArgsDeclaration.kt index 231ce45..0289af5 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ArgsDeclaration.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ArgsDeclaration.kt @@ -22,13 +22,13 @@ data class ArgsDeclaration(val params: List, val endTokenType: Token.Type) * parse args and create local vars in a given context */ suspend fun assignToContext( - context: Context, - arguments: Arguments = context.args, + scope: Scope, + arguments: Arguments = scope.args, defaultAccessType: AccessType = AccessType.Var, defaultVisibility: Visibility = Visibility.Public ) { fun assign(a: Item, value: Obj) { - context.addItem(a.name, (a.accessType ?: defaultAccessType).isMutable, value, + scope.addItem(a.name, (a.accessType ?: defaultAccessType).isMutable, value, a.visibility ?: defaultVisibility) } @@ -52,11 +52,11 @@ data class ArgsDeclaration(val params: List, val endTokenType: Token.Type) if (a.isEllipsis) break val value = when { i < callArgs.size -> callArgs[i] - a.defaultValue != null -> a.defaultValue.execute(context) + a.defaultValue != null -> a.defaultValue.execute(scope) else -> { println("callArgs: ${callArgs.joinToString()}") println("tailBlockMode: ${arguments.tailBlockMode}") - context.raiseIllegalArgument("too few arguments for the call") + scope.raiseIllegalArgument("too few arguments for the call") } } assign(a, value) @@ -76,8 +76,8 @@ data class ArgsDeclaration(val params: List, val endTokenType: Token.Type) callArgs[j--] } - a.defaultValue != null -> a.defaultValue.execute(context) - else -> context.raiseIllegalArgument("too few arguments for the call") + a.defaultValue != null -> a.defaultValue.execute(scope) + else -> scope.raiseIllegalArgument("too few arguments for the call") } assign(a, value) i-- @@ -98,7 +98,7 @@ data class ArgsDeclaration(val params: List, val endTokenType: Token.Type) processEllipsis(leftIndex, end) } else { if (leftIndex < callArgs.size) - context.raiseIllegalArgument("too many arguments for the call") + scope.raiseIllegalArgument("too many arguments for the call") } } diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Arguments.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Arguments.kt index 8367ce2..91f8097 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Arguments.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Arguments.kt @@ -2,11 +2,11 @@ package net.sergeych.lyng data class ParsedArgument(val value: Statement, val pos: Pos, val isSplat: Boolean = false) -suspend fun Collection.toArguments(context: Context,tailBlockMode: Boolean): Arguments { +suspend fun Collection.toArguments(scope: Scope, tailBlockMode: Boolean): Arguments { val list = mutableListOf() for (x in this) { - val value = x.value.execute(context) + val value = x.value.execute(scope) if (x.isSplat) { when { value is ObjList -> { @@ -14,11 +14,11 @@ suspend fun Collection.toArguments(context: Context,tailBlockMod } value.isInstanceOf(ObjIterable) -> { - val i = (value.invokeInstanceMethod(context, "toList") as ObjList).list + val i = (value.invokeInstanceMethod(scope, "toList") as ObjList).list i.forEach { list.add(it) } } - else -> context.raiseClassCastError("expected list of objects for splat argument") + else -> scope.raiseClassCastError("expected list of objects for splat argument") } } else list.add(value) @@ -38,8 +38,8 @@ data class Arguments(val list: List,val tailBlockMode: Boolean = false) : L /** * Convert to list of kotlin objects, see [Obj.toKotlin]. */ - suspend fun toKotlinList(context: Context): List { - return list.map { it.toKotlin(context) } + suspend fun toKotlinList(scope: Scope): List { + return list.map { it.toKotlin(scope) } } companion object { diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt index 3dd2f64..90bd5d4 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt @@ -380,11 +380,11 @@ class Compiler( val body = parseBlock(skipLeadingBrace = true) - var closure: Context? = null + var closure: Scope? = null val callStatement = statement { // and the source closure of the lambda which might have other thisObj. - val context = AppliedContext(closure!!, args, this) + val context = AppliedScope(closure!!, args, this) if (argsDeclaration == null) { // no args: automatic var 'it' val l = args.list @@ -1154,7 +1154,7 @@ class Compiler( } private suspend fun loopIntRange( - forContext: Context, start: Int, end: Int, loopVar: ObjRecord, + forScope: Scope, start: Int, end: Int, loopVar: ObjRecord, body: Statement, elseStatement: Statement?, label: String?, catchBreak: Boolean ): Obj { var result: Obj = ObjVoid @@ -1164,7 +1164,7 @@ class Compiler( for (i in start.. result = s.execute(it) } result } @@ -1452,7 +1452,7 @@ class Compiler( else parseBlock() - var closure: Context? = null + var closure: Scope? = null val fnBody = statement(t.pos) { callerContext -> callerContext.pos = start @@ -1497,7 +1497,7 @@ class Compiler( val block = parseScript() return statement(startPos) { // block run on inner context: - block.execute(if (it.skipContextCreation) it else it.copy(startPos)) + block.execute(if (it.skipScopeCreation) it else it.copy(startPos)) }.also { val t1 = cc.next() if (t1.type != Token.Type.RBRACE) @@ -1551,7 +1551,7 @@ class Compiler( // fun isLeftAssociative() = tokenType != Token.Type.OR && tokenType != Token.Type.AND companion object { - fun simple(tokenType: Token.Type, priority: Int, f: suspend (Context, Obj, Obj) -> Obj): Operator = + fun simple(tokenType: Token.Type, priority: Int, f: suspend (Scope, Obj, Obj) -> Obj): Operator = Operator(tokenType, priority, 2) { _: Pos, a: Accessor, b: Accessor -> Accessor { f(it, a.getter(it).value, b.getter(it).value).asReadonly } } diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Obj.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Obj.kt index 1237cc2..b851bf2 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Obj.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Obj.kt @@ -27,13 +27,13 @@ data class ObjRecord( * operator is implemented in [Compiler.allOps]. */ data class Accessor( - val getter: suspend (Context) -> ObjRecord, - val setterOrNull: (suspend (Context, Obj) -> Unit)? + val getter: suspend (Scope) -> ObjRecord, + val setterOrNull: (suspend (Scope, Obj) -> Unit)? ) { /** * Simplified constructor for immutable stores. */ - constructor(getter: suspend (Context) -> ObjRecord) : this(getter, null) + constructor(getter: suspend (Scope) -> ObjRecord) : this(getter, null) /** * Get the setter or throw. @@ -70,41 +70,41 @@ open class Obj { someClass == rootObjectType - suspend fun invokeInstanceMethod(context: Context, name: String, vararg args: Obj): Obj = - invokeInstanceMethod(context, name, Arguments(args.toList())) + suspend fun invokeInstanceMethod(scope: Scope, name: String, vararg args: Obj): Obj = + invokeInstanceMethod(scope, name, Arguments(args.toList())) suspend inline fun callMethod( - context: Context, + scope: Scope, name: String, args: Arguments = Arguments.EMPTY - ): T = invokeInstanceMethod(context, name, args) as T + ): T = invokeInstanceMethod(scope, name, args) as T open suspend fun invokeInstanceMethod( - context: Context, + scope: Scope, name: String, args: Arguments = Arguments.EMPTY ): Obj = // note that getInstanceMember traverses the hierarchy - objClass.getInstanceMember(context.pos, name).value.invoke(context, this, args) + objClass.getInstanceMember(scope.pos, name).value.invoke(scope, this, args) open suspend fun getInstanceMethod( - context: Context, + scope: Scope, name: String, args: Arguments = Arguments.EMPTY ): Obj = // note that getInstanceMember traverses the hierarchy - objClass.getInstanceMember(context.pos, name).value + objClass.getInstanceMember(scope.pos, name).value fun getMemberOrNull(name: String): Obj? = objClass.getInstanceMemberOrNull(name)?.value // methods that to override - open suspend fun compareTo(context: Context, other: Obj): Int { - context.raiseNotImplemented() + open suspend fun compareTo(scope: Scope, other: Obj): Int { + scope.raiseNotImplemented() } - open suspend fun contains(context: Context, other: Obj): Boolean { - return invokeInstanceMethod(context, "contains", other).toBool() + open suspend fun contains(scope: Scope, other: Obj): Boolean { + return invokeInstanceMethod(scope, "contains", other).toBool() } open val asStr: ObjString by lazy { @@ -117,90 +117,90 @@ open class Obj { */ open val objClass: ObjClass = rootObjectType - open suspend fun plus(context: Context, other: Obj): Obj { - context.raiseNotImplemented() + open suspend fun plus(scope: Scope, other: Obj): Obj { + scope.raiseNotImplemented() } - open suspend fun minus(context: Context, other: Obj): Obj { - context.raiseNotImplemented() + open suspend fun minus(scope: Scope, other: Obj): Obj { + scope.raiseNotImplemented() } - open suspend fun mul(context: Context, other: Obj): Obj { - context.raiseNotImplemented() + open suspend fun mul(scope: Scope, other: Obj): Obj { + scope.raiseNotImplemented() } - open suspend fun div(context: Context, other: Obj): Obj { - context.raiseNotImplemented() + open suspend fun div(scope: Scope, other: Obj): Obj { + scope.raiseNotImplemented() } - open suspend fun mod(context: Context, other: Obj): Obj { - context.raiseNotImplemented() + open suspend fun mod(scope: Scope, other: Obj): Obj { + scope.raiseNotImplemented() } - open suspend fun logicalNot(context: Context): Obj { - context.raiseNotImplemented() + open suspend fun logicalNot(scope: Scope): Obj { + scope.raiseNotImplemented() } - open suspend fun logicalAnd(context: Context, other: Obj): Obj { - context.raiseNotImplemented() + open suspend fun logicalAnd(scope: Scope, other: Obj): Obj { + scope.raiseNotImplemented() } - open suspend fun logicalOr(context: Context, other: Obj): Obj { - context.raiseNotImplemented() + open suspend fun logicalOr(scope: Scope, other: Obj): Obj { + scope.raiseNotImplemented() } - open suspend fun assign(context: Context, other: Obj): Obj? = null + open suspend fun assign(scope: Scope, other: Obj): Obj? = null /** * a += b * 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(context: Context, other: Obj): Obj? = null + open suspend fun plusAssign(scope: Scope, other: Obj): Obj? = null /** * `-=` operations, see [plusAssign] */ - open suspend fun minusAssign(context: Context, other: Obj): Obj? = null - open suspend fun mulAssign(context: Context, other: Obj): Obj? = null - open suspend fun divAssign(context: Context, other: Obj): Obj? = null - open suspend fun modAssign(context: Context, other: Obj): Obj? = null + 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 getAndIncrement(context: Context): Obj { - context.raiseNotImplemented() + open suspend fun getAndIncrement(scope: Scope): Obj { + scope.raiseNotImplemented() } - open suspend fun incrementAndGet(context: Context): Obj { - context.raiseNotImplemented() + open suspend fun incrementAndGet(scope: Scope): Obj { + scope.raiseNotImplemented() } - open suspend fun decrementAndGet(context: Context): Obj { - context.raiseNotImplemented() + open suspend fun decrementAndGet(scope: Scope): Obj { + scope.raiseNotImplemented() } - open suspend fun getAndDecrement(context: Context): Obj { - context.raiseNotImplemented() + open suspend fun getAndDecrement(scope: Scope): Obj { + scope.raiseNotImplemented() } /** * Convert Lyng object to its Kotlin counterpart */ - open suspend fun toKotlin(context: Context): Any? { + open suspend fun toKotlin(scope: Scope): Any? { return toString() } - fun willMutate(context: Context) { - if (isFrozen) context.raiseError("attempt to mutate frozen object") + fun willMutate(scope: Scope) { + if (isFrozen) scope.raiseError("attempt to mutate frozen object") } suspend fun sync(block: () -> T): T = monitor.withLock { block() } - open suspend fun readField(context: Context, name: String): ObjRecord { + open suspend fun readField(scope: Scope, name: String): ObjRecord { // could be property or class field: - val obj = objClass.getInstanceMemberOrNull(name) ?: context.raiseError("no such field: $name") + val obj = objClass.getInstanceMemberOrNull(name) ?: scope.raiseError("no such field: $name") return when (val value = obj.value) { is Statement -> { - ObjRecord(value.execute(context.copy(context.pos, newThisObj = this)), obj.isMutable) + ObjRecord(value.execute(scope.copy(scope.pos, newThisObj = this)), obj.isMutable) } // could be writable property naturally // null -> ObjNull.asReadonly @@ -208,49 +208,49 @@ open class Obj { } } - open suspend fun writeField(context: Context, name: String, newValue: Obj) { - willMutate(context) - val field = objClass.getInstanceMemberOrNull(name) ?: context.raiseError("no such field: $name") - if (field.isMutable) field.value = newValue else context.raiseError("can't assign to read-only field: $name") + open suspend fun writeField(scope: Scope, name: String, newValue: Obj) { + willMutate(scope) + val field = objClass.getInstanceMemberOrNull(name) ?: scope.raiseError("no such field: $name") + if (field.isMutable) field.value = newValue else scope.raiseError("can't assign to read-only field: $name") } - open suspend fun getAt(context: Context, index: Obj): Obj { - context.raiseNotImplemented("indexing") + open suspend fun getAt(scope: Scope, index: Obj): Obj { + scope.raiseNotImplemented("indexing") } - suspend fun getAt(context: Context, index: Int): Obj = getAt(context, ObjInt(index.toLong())) + suspend fun getAt(scope: Scope, index: Int): Obj = getAt(scope, ObjInt(index.toLong())) - open suspend fun putAt(context: Context, index: Int, newValue: Obj) { - context.raiseNotImplemented("indexing") + open suspend fun putAt(scope: Scope, index: Int, newValue: Obj) { + scope.raiseNotImplemented("indexing") } - open suspend fun callOn(context: Context): Obj { - context.raiseNotImplemented() + open suspend fun callOn(scope: Scope): Obj { + scope.raiseNotImplemented() } - suspend fun invoke(context: Context, thisObj: Obj, args: Arguments): Obj = - callOn(context.copy(context.pos, args = args, newThisObj = thisObj)) + suspend fun invoke(scope: Scope, thisObj: Obj, args: Arguments): Obj = + callOn(scope.copy(scope.pos, args = args, newThisObj = thisObj)) - suspend fun invoke(context: Context, thisObj: Obj, vararg args: Obj): Obj = + suspend fun invoke(scope: Scope, thisObj: Obj, vararg args: Obj): Obj = callOn( - context.copy( - context.pos, + scope.copy( + scope.pos, args = Arguments(args.toList()), newThisObj = thisObj ) ) - suspend fun invoke(context: Context, thisObj: Obj): Obj = + suspend fun invoke(scope: Scope, thisObj: Obj): Obj = callOn( - context.copy( - context.pos, + scope.copy( + scope.pos, args = Arguments.EMPTY, newThisObj = thisObj ) ) - suspend fun invoke(context: Context, atPos: Pos, thisObj: Obj, args: Arguments): Obj = - callOn(context.copy(atPos, args = args, newThisObj = thisObj)) + suspend fun invoke(scope: Scope, atPos: Pos, thisObj: Obj, args: Arguments): Obj = + callOn(scope.copy(atPos, args = args, newThisObj = thisObj)) val asReadonly: ObjRecord by lazy { ObjRecord(this, false) } @@ -271,7 +271,7 @@ open class Obj { args.firstAndOnly().callOn(copy(Arguments(thisObj))) } addFn("apply") { - val newContext = ( thisObj as? ObjInstance)?.instanceContext ?: this + val newContext = ( thisObj as? ObjInstance)?.instanceScope ?: this args.firstAndOnly() .callOn(newContext) thisObj @@ -319,7 +319,7 @@ object ObjVoid : Obj() { return other is ObjVoid || other is Unit } - override suspend fun compareTo(context: Context, other: Obj): Int { + override suspend fun compareTo(scope: Scope, other: Obj): Int { return if (other === this) 0 else -1 } @@ -329,7 +329,7 @@ object ObjVoid : Obj() { @Serializable @SerialName("null") object ObjNull : Obj() { - override suspend fun compareTo(context: Context, other: Obj): Int { + override suspend fun compareTo(scope: Scope, other: Obj): Int { return if (other === this) 0 else -1 } @@ -337,29 +337,29 @@ object ObjNull : Obj() { return other is ObjNull || other == null } - override suspend fun readField(context: Context, name: String): ObjRecord { - context.raiseNPE() + override suspend fun readField(scope: Scope, name: String): ObjRecord { + scope.raiseNPE() } - override suspend fun invokeInstanceMethod(context: Context, name: String, args: Arguments): Obj { - context.raiseNPE() + override suspend fun invokeInstanceMethod(scope: Scope, name: String, args: Arguments): Obj { + scope.raiseNPE() } - override suspend fun getAt(context: Context, index: Obj): Obj { - context.raiseNPE() + override suspend fun getAt(scope: Scope, index: Obj): Obj { + scope.raiseNPE() } - override suspend fun putAt(context: Context, index: Int, newValue: Obj) { - context.raiseNPE() + override suspend fun putAt(scope: Scope, index: Int, newValue: Obj) { + scope.raiseNPE() } - override suspend fun callOn(context: Context): Obj { - context.raiseNPE() + override suspend fun callOn(scope: Scope): Obj { + scope.raiseNPE() } override fun toString(): String = "null" - override suspend fun toKotlin(context: Context): Any? { + override suspend fun toKotlin(scope: Scope): Any? { return null } } @@ -401,14 +401,14 @@ data class ObjNamespace(val name: String) : Obj() { } } -open class ObjException(exceptionClass: ExceptionClass, val context: Context, val message: String) : Obj() { - constructor(name: String, context: Context, message: String) : this( +open class ObjException(exceptionClass: ExceptionClass, val scope: Scope, val message: String) : Obj() { + constructor(name: String, scope: Scope, message: String) : this( getOrCreateExceptionClass(name), - context, + scope, message ) - constructor(context: Context, message: String) : this(Root, context, message) + constructor(scope: Scope, message: String) : this(Root, scope, message) fun raise(): Nothing { throw ExecutionError(this) @@ -417,15 +417,15 @@ open class ObjException(exceptionClass: ExceptionClass, val context: Context, va override val objClass: ObjClass = exceptionClass override fun toString(): String { - return "ObjException:${objClass.className}:${context.pos}@${hashCode().encodeToHex()}" + return "ObjException:${objClass.className}:${scope.pos}@${hashCode().encodeToHex()}" } companion object { class ExceptionClass(val name: String, vararg parents: ObjClass) : ObjClass(name, *parents) { - override suspend fun callOn(context: Context): Obj { - val message = context.args.getOrNull(0)?.toString() ?: name - return ObjException(this, context, message) + override suspend fun callOn(scope: Scope): Obj { + val message = scope.args.getOrNull(0)?.toString() ?: name + return ObjException(this, scope, message) } override fun toString(): String = "ExceptionClass[$name]@${hashCode().encodeToHex()}" @@ -458,8 +458,8 @@ open class ObjException(exceptionClass: ExceptionClass, val context: Context, va existingErrorClasses[name] } - fun addExceptionsToContext(context: Context) { - context.addConst("Exception", Root) + fun addExceptionsToContext(scope: Scope) { + scope.addConst("Exception", Root) existingErrorClasses["Exception"] = Root for (name in listOf( "NullReferenceException", @@ -474,39 +474,39 @@ open class ObjException(exceptionClass: ExceptionClass, val context: Context, va "AccessException", "UnknownException", )) { - context.addConst(name, getOrCreateExceptionClass(name)) + scope.addConst(name, getOrCreateExceptionClass(name)) } } } } -class ObjNullReferenceException(context: Context) : ObjException("NullReferenceException", context, "object is null") +class ObjNullReferenceException(scope: Scope) : ObjException("NullReferenceException", scope, "object is null") -class ObjAssertionFailedException(context: Context, message: String) : - ObjException("AssertionFailedException", context, message) +class ObjAssertionFailedException(scope: Scope, message: String) : + ObjException("AssertionFailedException", scope, message) -class ObjClassCastException(context: Context, message: String) : ObjException("ClassCastException", context, message) -class ObjIndexOutOfBoundsException(context: Context, message: String = "index out of bounds") : - ObjException("IndexOutOfBoundsException", context, message) +class ObjClassCastException(scope: Scope, message: String) : ObjException("ClassCastException", scope, message) +class ObjIndexOutOfBoundsException(scope: Scope, message: String = "index out of bounds") : + ObjException("IndexOutOfBoundsException", scope, message) -class ObjIllegalArgumentException(context: Context, message: String = "illegal argument") : - ObjException("IllegalArgumentException", context, message) +class ObjIllegalArgumentException(scope: Scope, message: String = "illegal argument") : + ObjException("IllegalArgumentException", scope, message) @Suppress("unused") -class ObjNoSuchElementException(context: Context, message: String = "no such element") : - ObjException("IllegalArgumentException", context, message) +class ObjNoSuchElementException(scope: Scope, message: String = "no such element") : + ObjException("IllegalArgumentException", scope, message) -class ObjIllegalAssignmentException(context: Context, message: String = "illegal assignment") : - ObjException("NoSuchElementException", context, message) +class ObjIllegalAssignmentException(scope: Scope, message: String = "illegal assignment") : + ObjException("NoSuchElementException", scope, message) -class ObjSymbolNotDefinedException(context: Context, message: String = "symbol is not defined") : - ObjException("SymbolNotDefinedException", context, message) +class ObjSymbolNotDefinedException(scope: Scope, message: String = "symbol is not defined") : + ObjException("SymbolNotDefinedException", scope, message) -class ObjIterationFinishedException(context: Context) : - ObjException("IterationEndException", context, "iteration finished") +class ObjIterationFinishedException(scope: Scope) : + ObjException("IterationEndException", scope, "iteration finished") -class ObjAccessException(context: Context, message: String = "access not allowed error") : - ObjException("AccessException", context, message) +class ObjAccessException(scope: Scope, message: String = "access not allowed error") : + ObjException("AccessException", scope, message) -class ObjUnknownException(context: Context, message: String = "access not allowed error") : - ObjException("UnknownException", context, message) +class ObjUnknownException(scope: Scope, message: String = "access not allowed error") : + ObjException("UnknownException", scope, message) diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjArrayIterator.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjArrayIterator.kt index f3229a2..be75dac 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjArrayIterator.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjArrayIterator.kt @@ -7,9 +7,9 @@ class ObjArrayIterator(val array: Obj) : Obj() { private var nextIndex = 0 private var lastIndex = 0 - suspend fun init(context: Context) { + suspend fun init(scope: Scope) { nextIndex = 0 - lastIndex = array.invokeInstanceMethod(context, "size").toInt() + lastIndex = array.invokeInstanceMethod(scope, "size").toInt() ObjVoid } diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjBool.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjBool.kt index a81cfa2..5f2d510 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjBool.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjBool.kt @@ -3,7 +3,7 @@ package net.sergeych.lyng data class ObjBool(val value: Boolean) : Obj() { override val asStr by lazy { ObjString(value.toString()) } - override suspend fun compareTo(context: Context, other: Obj): Int { + override suspend fun compareTo(scope: Scope, other: Obj): Int { if (other !is ObjBool) return -2 return value.compareTo(other.value) } @@ -12,13 +12,13 @@ data class ObjBool(val value: Boolean) : Obj() { override val objClass: ObjClass = type - override suspend fun logicalNot(context: Context): Obj = ObjBool(!value) + override suspend fun logicalNot(scope: Scope): Obj = ObjBool(!value) - override suspend fun logicalAnd(context: Context, other: Obj): Obj = ObjBool(value && other.toBool()) + override suspend fun logicalAnd(scope: Scope, other: Obj): Obj = ObjBool(value && other.toBool()) - override suspend fun logicalOr(context: Context, other: Obj): Obj = ObjBool(value || other.toBool()) + override suspend fun logicalOr(scope: Scope, other: Obj): Obj = ObjBool(value || other.toBool()) - override suspend fun toKotlin(context: Context): Any { + override suspend fun toKotlin(scope: Scope): Any { return value } diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjChar.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjChar.kt index 2710460..593e9d5 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjChar.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjChar.kt @@ -4,7 +4,7 @@ class ObjChar(val value: Char): Obj() { override val objClass: ObjClass = type - override suspend fun compareTo(context: Context, other: Obj): Int = + override suspend fun compareTo(scope: Scope, other: Obj): Int = (other as? ObjChar)?.let { value.compareTo(it.value) } ?: -1 override fun toString(): String = value.toString() diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjClass.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjClass.kt index ab4f7a4..cfd3bab 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjClass.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjClass.kt @@ -21,13 +21,13 @@ open class ObjClass( override fun toString(): String = className - override suspend fun compareTo(context: Context, other: Obj): Int = if (other === this) 0 else -1 + override suspend fun compareTo(scope: Scope, other: Obj): Int = if (other === this) 0 else -1 - override suspend fun callOn(context: Context): Obj { + override suspend fun callOn(scope: Scope): Obj { val instance = ObjInstance(this) - instance.instanceContext = context.copy(newThisObj = instance,args = context.args) + instance.instanceScope = scope.copy(newThisObj = instance,args = scope.args) if (instanceConstructor != null) { - instanceConstructor!!.execute(instance.instanceContext) + instanceConstructor!!.execute(instance.instanceScope) } return instance } @@ -49,7 +49,7 @@ open class ObjClass( members[name] = ObjRecord(initialValue, isMutable, visibility) } - fun addFn(name: String, isOpen: Boolean = false, code: suspend Context.() -> Obj) { + fun addFn(name: String, isOpen: Boolean = false, code: suspend Scope.() -> Obj) { createField(name, statement { code() }, isOpen) } diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjInstance.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjInstance.kt index 73c2987..e9989df 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjInstance.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjInstance.kt @@ -2,52 +2,52 @@ package net.sergeych.lyng class ObjInstance(override val objClass: ObjClass) : Obj() { - internal lateinit var instanceContext: Context + internal lateinit var instanceScope: Scope - override suspend fun readField(context: Context, name: String): ObjRecord { - return instanceContext[name]?.let { + override suspend fun readField(scope: Scope, name: String): ObjRecord { + return instanceScope[name]?.let { if (it.visibility.isPublic) it else - context.raiseError(ObjAccessException(context, "can't access non-public field $name")) + scope.raiseError(ObjAccessException(scope, "can't access non-public field $name")) } - ?: super.readField(context, name) + ?: super.readField(scope, name) } - override suspend fun writeField(context: Context, name: String, newValue: Obj) { - instanceContext[name]?.let { f -> + override suspend fun writeField(scope: Scope, name: String, newValue: Obj) { + instanceScope[name]?.let { f -> if (!f.visibility.isPublic) - ObjIllegalAssignmentException(context, "can't assign to non-public field $name") - if (!f.isMutable) ObjIllegalAssignmentException(context, "can't reassign val $name").raise() - if (f.value.assign(context, newValue) == null) + ObjIllegalAssignmentException(scope, "can't assign to non-public field $name") + if (!f.isMutable) ObjIllegalAssignmentException(scope, "can't reassign val $name").raise() + if (f.value.assign(scope, newValue) == null) f.value = newValue - } ?: super.writeField(context, name, newValue) + } ?: super.writeField(scope, name, newValue) } - override suspend fun invokeInstanceMethod(context: Context, name: String, args: Arguments): Obj = - instanceContext[name]?.let { + override suspend fun invokeInstanceMethod(scope: Scope, name: String, args: Arguments): Obj = + instanceScope[name]?.let { if (it.visibility.isPublic) - it.value.invoke(context, this, args) + it.value.invoke(scope, this, args) else - context.raiseError(ObjAccessException(context, "can't invoke non-public method $name")) + scope.raiseError(ObjAccessException(scope, "can't invoke non-public method $name")) } - ?: super.invokeInstanceMethod(context, name, args) + ?: super.invokeInstanceMethod(scope, name, args) private val publicFields: Map - get() = instanceContext.objects.filter { it.value.visibility.isPublic } + get() = instanceScope.objects.filter { it.value.visibility.isPublic } override fun toString(): String { val fields = publicFields.map { "${it.key}=${it.value.value}" }.joinToString(",") return "${objClass.className}($fields)" } - override suspend fun compareTo(context: Context, other: Obj): Int { + override suspend fun compareTo(scope: Scope, other: Obj): Int { if (other !is ObjInstance) return -1 if (other.objClass != objClass) return -1 for (f in publicFields) { val a = f.value.value - val b = other.instanceContext[f.key]!!.value - val d = a.compareTo(context, b) + val b = other.instanceScope[f.key]!!.value + val d = a.compareTo(scope, b) if (d != 0) return d } return 0 diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjInt.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjInt.kt index 83aca70..7167b90 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjInt.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjInt.kt @@ -13,23 +13,23 @@ data class ObjInt(var value: Long) : Obj(), Numeric { return value.hashCode() } - override suspend fun getAndIncrement(context: Context): Obj { + override suspend fun getAndIncrement(scope: Scope): Obj { return ObjInt(value).also { value++ } } - override suspend fun getAndDecrement(context: Context): Obj { + override suspend fun getAndDecrement(scope: Scope): Obj { return ObjInt(value).also { value-- } } - override suspend fun incrementAndGet(context: Context): Obj { + override suspend fun incrementAndGet(scope: Scope): Obj { return ObjInt(++value) } - override suspend fun decrementAndGet(context: Context): Obj { + override suspend fun decrementAndGet(scope: Scope): Obj { return ObjInt(--value) } - override suspend fun compareTo(context: Context, other: Obj): Int { + override suspend fun compareTo(scope: Scope, other: Obj): Int { if (other !is Numeric) return -2 return value.compareTo(other.doubleValue) } @@ -38,29 +38,29 @@ data class ObjInt(var value: Long) : Obj(), Numeric { override val objClass: ObjClass = type - override suspend fun plus(context: Context, other: Obj): Obj = + override suspend fun plus(scope: Scope, other: Obj): Obj = if (other is ObjInt) ObjInt(this.value + other.value) else ObjReal(this.doubleValue + other.toDouble()) - override suspend fun minus(context: Context, other: Obj): Obj = + override suspend fun minus(scope: Scope, other: Obj): Obj = if (other is ObjInt) ObjInt(this.value - other.value) else ObjReal(this.doubleValue - other.toDouble()) - override suspend fun mul(context: Context, other: Obj): Obj = + override suspend fun mul(scope: Scope, other: Obj): Obj = if (other is ObjInt) { ObjInt(this.value * other.value) } else ObjReal(this.value * other.toDouble()) - override suspend fun div(context: Context, other: Obj): Obj = + override suspend fun div(scope: Scope, other: Obj): Obj = if (other is ObjInt) ObjInt(this.value / other.value) else ObjReal(this.value / other.toDouble()) - override suspend fun mod(context: Context, other: Obj): Obj = + override suspend fun mod(scope: Scope, other: Obj): Obj = if (other is ObjInt) ObjInt(this.value % other.value) else ObjReal(this.value.toDouble() % other.toDouble()) @@ -69,14 +69,14 @@ data class ObjInt(var value: Long) : Obj(), Numeric { * We are by-value type ([byValueCopy] is implemented) so we can do in-place * assignment */ - override suspend fun assign(context: Context, other: Obj): Obj? { + override suspend fun assign(scope: Scope, other: Obj): Obj? { return if (other is ObjInt) { value = other.value this } else null } - override suspend fun toKotlin(context: Context): Any { + override suspend fun toKotlin(scope: Scope): Any { return value } diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjKotlinIterator.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjKotlinIterator.kt index bb3e301..e739f36 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjKotlinIterator.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjKotlinIterator.kt @@ -47,11 +47,11 @@ class ObjKotlinObjIterator(val iterator: Iterator) : Obj() { * As Lyng is totally asynchronous, its iterator can't be trivially converted to Kotlin's synchronous iterator. * It is, though, trivially convertible to Kotlin's Flow. */ -fun Obj.toFlow(context: Context): Flow = flow { - val iterator = invokeInstanceMethod(context, "iterator") - val hasNext = iterator.getInstanceMethod(context, "hasNext") - val next = iterator.getInstanceMethod(context, "next") - while (hasNext.invoke(context, iterator).toBool()) { - emit(next.invoke(context, iterator)) +fun Obj.toFlow(scope: Scope): Flow = flow { + val iterator = invokeInstanceMethod(scope, "iterator") + val hasNext = iterator.getInstanceMethod(scope, "hasNext") + val next = iterator.getInstanceMethod(scope, "next") + while (hasNext.invoke(scope, iterator).toBool()) { + emit(next.invoke(scope, iterator)) } } \ No newline at end of file diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjList.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjList.kt index eee5820..82186d8 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjList.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjList.kt @@ -11,7 +11,7 @@ class ObjList(val list: MutableList = mutableListOf()) : Obj() { list.joinToString(separator = ", ") { it.inspect() } }]" - override suspend fun getAt(context: Context, index: Obj): Obj { + override suspend fun getAt(scope: Scope, index: Obj): Obj { return when (index) { is ObjInt -> { list[index.toInt()] @@ -47,23 +47,23 @@ class ObjList(val list: MutableList = mutableListOf()) : Obj() { } } - else -> context.raiseIllegalArgument("Illegal index object for a list: ${index.inspect()}") + else -> scope.raiseIllegalArgument("Illegal index object for a list: ${index.inspect()}") } } - override suspend fun putAt(context: Context, index: Int, newValue: Obj) { + override suspend fun putAt(scope: Scope, index: Int, newValue: Obj) { val i = index list[i] = newValue } - override suspend fun compareTo(context: Context, other: Obj): Int { + override suspend fun compareTo(scope: Scope, other: Obj): Int { if (other !is ObjList) return -2 val mySize = list.size val otherSize = other.list.size val commonSize = minOf(mySize, otherSize) for (i in 0.. = mutableListOf()) : Obj() { } } - override suspend fun plus(context: Context, other: Obj): Obj = + override suspend fun plus(scope: Scope, other: Obj): Obj = when { other is ObjList -> ObjList((list + other.list).toMutableList()) other.isInstanceOf(ObjIterable) -> { - val l = other.callMethod(context, "toList") + val l = other.callMethod(scope, "toList") ObjList((list + l.list).toMutableList()) } else -> - context.raiseError("'+': can't concatenate $this with $other") + scope.raiseError("'+': can't concatenate $this with $other") } - override suspend fun plusAssign(context: Context, other: Obj): Obj { + override suspend fun plusAssign(scope: Scope, other: Obj): Obj { // optimization if (other is ObjList) { list += other.list return this } if (other.isInstanceOf(ObjIterable)) { - val otherList = other.invokeInstanceMethod(context, "toList") as ObjList + val otherList = other.invokeInstanceMethod(scope, "toList") as ObjList list += otherList.list } else list += other return this } - override suspend fun contains(context: Context, other: Obj): Boolean { + override suspend fun contains(scope: Scope, other: Obj): Boolean { return list.contains(other) } override val objClass: ObjClass get() = type - override suspend fun toKotlin(context: Context): Any { - return list.map { it.toKotlin(context) } + override suspend fun toKotlin(scope: Scope): Any { + return list.map { it.toKotlin(scope) } } override fun hashCode(): Int { diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjMap.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjMap.kt index d214af2..b7974ef 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjMap.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjMap.kt @@ -2,17 +2,17 @@ package net.sergeych.lyng class ObjMapEntry(val key: Obj, val value: Obj) : Obj() { - override suspend fun compareTo(context: Context, other: Obj): Int { + override suspend fun compareTo(scope: Scope, other: Obj): Int { if (other !is ObjMapEntry) return -1 - val c = key.compareTo(context, other.key) + val c = key.compareTo(scope, other.key) if (c != 0) return c - return value.compareTo(context, other.value) + return value.compareTo(scope, other.value) } - override suspend fun getAt(context: Context, index: Obj): Obj = when (index.toInt()) { + override suspend fun getAt(scope: Scope, index: Obj): Obj = when (index.toInt()) { 0 -> key 1 -> value - else -> context.raiseIndexOutOfBounds() + else -> scope.raiseIndexOutOfBounds() } override fun toString(): String { @@ -23,8 +23,8 @@ class ObjMapEntry(val key: Obj, val value: Obj) : Obj() { companion object { val type = object : ObjClass("MapEntry", ObjArray) { - override suspend fun callOn(context: Context): Obj { - return ObjMapEntry(context.requiredArg(0), context.requiredArg(1)) + override suspend fun callOn(scope: Scope): Obj { + return ObjMapEntry(scope.requiredArg(0), scope.requiredArg(1)) } }.apply { addFn("key") { thisAs().key } @@ -38,14 +38,14 @@ class ObjMap(val map: MutableMap = mutableMapOf()) : Obj() { override val objClass = type - override suspend fun getAt(context: Context, index: Obj): Obj = - map.getOrElse(index) { context.raiseNoSuchElement() } + override suspend fun getAt(scope: Scope, index: Obj): Obj = + map.getOrElse(index) { scope.raiseNoSuchElement() } - override suspend fun contains(context: Context, other: Obj): Boolean { + override suspend fun contains(scope: Scope, other: Obj): Boolean { return other in map } - override suspend fun compareTo(context: Context, other: Obj): Int { + override suspend fun compareTo(scope: Scope, other: Obj): Int { if( other is ObjMap && other.map == map) return 0 return -1 } @@ -53,30 +53,30 @@ class ObjMap(val map: MutableMap = mutableMapOf()) : Obj() { companion object { - suspend fun listToMap(context: Context, list: List): MutableMap { + suspend fun listToMap(scope: Scope, list: List): MutableMap { val map = mutableMapOf() if (list.isEmpty()) return map val first = list.first() if (first.isInstanceOf(ObjArray)) { - if (first.invokeInstanceMethod(context, "size").toInt() != 2) - context.raiseIllegalArgument( + if (first.invokeInstanceMethod(scope, "size").toInt() != 2) + scope.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") + } else scope.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) + map[it.getAt(scope, ObjInt.Zero)] = it.getAt(scope, ObjInt.One) } return map } val type = object : ObjClass("Map", ObjCollection) { - override suspend fun callOn(context: Context): Obj { - return ObjMap(listToMap(context, context.args.list)) + override suspend fun callOn(scope: Scope): Obj { + return ObjMap(listToMap(scope, scope.args.list)) } }.apply { addFn("getOrNull") { diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjRange.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjRange.kt index e849607..92b2125 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjRange.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjRange.kt @@ -15,10 +15,10 @@ class ObjRange(val start: Obj?, val end: Obj?, val isEndInclusive: Boolean) : Ob return result.toString() } - suspend fun containsRange(context: Context, other: ObjRange): Boolean { + suspend fun containsRange(scope: Scope, other: ObjRange): Boolean { if (start != null) { // our start is not -∞ so other start should be GTE or is not contained: - if (other.start != null && start.compareTo(context, other.start) > 0) return false + if (other.start != null && start.compareTo(scope, other.start) > 0) return false } if (end != null) { // same with the end: if it is open, it can't be contained in ours: @@ -26,16 +26,16 @@ class ObjRange(val start: Obj?, val end: Obj?, val isEndInclusive: Boolean) : Ob // both exists, now there could be 4 cases: return when { other.isEndInclusive && isEndInclusive -> - end.compareTo(context, other.end) >= 0 + end.compareTo(scope, other.end) >= 0 !other.isEndInclusive && !isEndInclusive -> - end.compareTo(context, other.end) >= 0 + end.compareTo(scope, other.end) >= 0 other.isEndInclusive && !isEndInclusive -> - end.compareTo(context, other.end) > 0 + end.compareTo(scope, other.end) > 0 !other.isEndInclusive && isEndInclusive -> - end.compareTo(context, other.end) >= 0 + end.compareTo(scope, other.end) >= 0 else -> throw IllegalStateException("unknown comparison") } @@ -43,17 +43,17 @@ class ObjRange(val start: Obj?, val end: Obj?, val isEndInclusive: Boolean) : Ob return true } - override suspend fun contains(context: Context, other: Obj): Boolean { + override suspend fun contains(scope: Scope, other: Obj): Boolean { if (other is ObjRange) - return containsRange(context, other) + return containsRange(scope, other) if (start == null && end == null) return true if (start != null) { - if (start.compareTo(context, other) > 0) return false + if (start.compareTo(scope, other) > 0) return false } if (end != null) { - val cmp = end.compareTo(context, other) + val cmp = end.compareTo(scope, other) if (isEndInclusive && cmp < 0 || !isEndInclusive && cmp <= 0) return false } return true @@ -67,7 +67,7 @@ class ObjRange(val start: Obj?, val end: Obj?, val isEndInclusive: Boolean) : Ob start is ObjChar && end is ObjChar } - override suspend fun compareTo(context: Context, other: Obj): Int { + override suspend fun compareTo(scope: Scope, other: Obj): Int { return (other as? ObjRange)?.let { if( start == other.start && end == other.end ) 0 else -1 } diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjRangeIterator.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjRangeIterator.kt index bf2afb6..bffeac0 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjRangeIterator.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjRangeIterator.kt @@ -8,7 +8,7 @@ class ObjRangeIterator(val self: ObjRange) : Obj() { override val objClass: ObjClass = type - fun Context.init() { + fun Scope.init() { if (self.start == null || self.end == null) raiseError("next is only available for finite ranges") isCharRange = self.isCharRange @@ -24,7 +24,7 @@ class ObjRangeIterator(val self: ObjRange) : Obj() { fun hasNext(): Boolean = nextIndex < lastIndex - fun next(context: Context): Obj = + fun next(scope: Scope): Obj = if (nextIndex < lastIndex) { val x = if (self.isEndInclusive) self.start!!.toLong() + nextIndex++ @@ -33,7 +33,7 @@ class ObjRangeIterator(val self: ObjRange) : Obj() { if( isCharRange ) ObjChar(x.toInt().toChar()) else ObjInt(x) } else { - context.raiseError(ObjIterationFinishedException(context)) + scope.raiseError(ObjIterationFinishedException(scope)) } companion object { diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjReal.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjReal.kt index b1de8fd..63785af 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjReal.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjReal.kt @@ -14,7 +14,7 @@ data class ObjReal(val value: Double) : Obj(), Numeric { override fun byValueCopy(): Obj = ObjReal(value) - override suspend fun compareTo(context: Context, other: Obj): Int { + override suspend fun compareTo(scope: Scope, other: Obj): Int { if (other !is Numeric) return -2 return value.compareTo(other.doubleValue) } @@ -25,25 +25,25 @@ data class ObjReal(val value: Double) : Obj(), Numeric { return value.hashCode() } - override suspend fun plus(context: Context, other: Obj): Obj = + override suspend fun plus(scope: Scope, other: Obj): Obj = ObjReal(this.value + other.toDouble()) - override suspend fun minus(context: Context, other: Obj): Obj = + override suspend fun minus(scope: Scope, other: Obj): Obj = ObjReal(this.value - other.toDouble()) - override suspend fun mul(context: Context, other: Obj): Obj = + override suspend fun mul(scope: Scope, other: Obj): Obj = ObjReal(this.value * other.toDouble()) - override suspend fun div(context: Context, other: Obj): Obj = + override suspend fun div(scope: Scope, other: Obj): Obj = ObjReal(this.value / other.toDouble()) - override suspend fun mod(context: Context, other: Obj): Obj = + override suspend fun mod(scope: Scope, other: Obj): Obj = ObjReal(this.value % other.toDouble()) /** * Returns unboxed Double value */ - override suspend fun toKotlin(context: Context): Any { + override suspend fun toKotlin(scope: Scope): Any { return value } diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjSet.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjSet.kt index 6cc270b..b4b9a86 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjSet.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjSet.kt @@ -4,11 +4,11 @@ class ObjSet(val set: MutableSet = mutableSetOf()) : Obj() { override val objClass = type - override suspend fun contains(context: Context, other: Obj): Boolean { + override suspend fun contains(scope: Scope, other: Obj): Boolean { return set.contains(other) } - override suspend fun plus(context: Context, other: Obj): Obj { + override suspend fun plus(scope: Scope, other: Obj): Obj { return ObjSet( if (other is ObjSet) (set + other.set).toMutableSet() @@ -17,7 +17,7 @@ class ObjSet(val set: MutableSet = mutableSetOf()) : Obj() { ) } - override suspend fun plusAssign(context: Context, other: Obj): Obj { + override suspend fun plusAssign(scope: Scope, other: Obj): Obj { when (other) { is ObjSet -> { set += other.set @@ -29,9 +29,9 @@ class ObjSet(val set: MutableSet = mutableSetOf()) : Obj() { else -> { if (other.isInstanceOf(ObjIterable)) { - val i = other.invokeInstanceMethod(context, "iterable") - while (i.invokeInstanceMethod(context, "hasNext").toBool()) { - set += i.invokeInstanceMethod(context, "next") + val i = other.invokeInstanceMethod(scope, "iterable") + while (i.invokeInstanceMethod(scope, "hasNext").toBool()) { + set += i.invokeInstanceMethod(scope, "next") } } set += other @@ -40,16 +40,16 @@ class ObjSet(val set: MutableSet = mutableSetOf()) : Obj() { return this } - override suspend fun mul(context: Context, other: Obj): Obj { + override suspend fun mul(scope: Scope, other: Obj): Obj { return if (other is ObjSet) { ObjSet(set.intersect(other.set).toMutableSet()) } else - context.raiseIllegalArgument("set operator * requires another set") + scope.raiseIllegalArgument("set operator * requires another set") } - override suspend fun minus(context: Context, other: Obj): Obj { + override suspend fun minus(scope: Scope, other: Obj): Obj { if (other !is ObjSet) - context.raiseIllegalArgument("set operator - requires another set") + scope.raiseIllegalArgument("set operator - requires another set") return ObjSet(set.minus(other.set).toMutableSet()) } @@ -57,7 +57,7 @@ class ObjSet(val set: MutableSet = mutableSetOf()) : Obj() { return "Set(${set.joinToString(", ")})" } - override suspend fun compareTo(context: Context, other: Obj): Int { + override suspend fun compareTo(scope: Scope, other: Obj): Int { return if (other !is ObjSet) -1 else { if (set == other.set) 0 @@ -69,8 +69,8 @@ class ObjSet(val set: MutableSet = mutableSetOf()) : Obj() { val type = object : ObjClass("Set", ObjCollection) { - override suspend fun callOn(context: Context): Obj { - return ObjSet(context.args.list.toMutableSet()) + override suspend fun callOn(scope: Scope): Obj { + return ObjSet(scope.args.list.toMutableSet()) } }.apply { addFn("size") { diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjString.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjString.kt index dfefc3b..7833c29 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjString.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ObjString.kt @@ -16,7 +16,7 @@ data class ObjString(val value: String) : Obj() { // } - override suspend fun compareTo(context: Context, other: Obj): Int { + override suspend fun compareTo(scope: Scope, other: Obj): Int { if (other !is ObjString) return -2 return this.value.compareTo(other.value) } @@ -32,11 +32,11 @@ data class ObjString(val value: String) : Obj() { override val objClass: ObjClass get() = type - override suspend fun plus(context: Context, other: Obj): Obj { + override suspend fun plus(scope: Scope, other: Obj): Obj { return ObjString(value + other.asStr.value) } - override suspend fun getAt(context: Context, index: Obj): Obj { + override suspend fun getAt(scope: Scope, index: Obj): Obj { if( index is ObjInt ) return ObjChar(value[index.toInt()]) if( index is ObjRange ) { val start = if(index.start == null || index.start.isNull) 0 else index.start.toInt() @@ -46,23 +46,23 @@ data class ObjString(val value: String) : Obj() { } return ObjString(value.substring(start, end)) } - context.raiseIllegalArgument("String index must be Int or Range") + scope.raiseIllegalArgument("String index must be Int or Range") } override fun hashCode(): Int { return value.hashCode() } - override suspend fun callOn(context: Context): Obj { - return ObjString(this.value.sprintf(*context.args.toKotlinList(context).toTypedArray())) + override suspend fun callOn(scope: Scope): Obj { + return ObjString(this.value.sprintf(*scope.args.toKotlinList(scope).toTypedArray())) } - override suspend fun contains(context: Context, other: Obj): Boolean { + override suspend fun contains(scope: Scope, other: Obj): Boolean { return if (other is ObjString) value.contains(other.value) else if (other is ObjChar) value.contains(other.value) - else context.raiseIllegalArgument("String.contains can't take $other") + else scope.raiseIllegalArgument("String.contains can't take $other") } override fun equals(other: Any?): Boolean { diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Context.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Scope.kt similarity index 88% rename from lynglib/src/commonMain/kotlin/net/sergeych/lyng/Context.kt rename to lynglib/src/commonMain/kotlin/net/sergeych/lyng/Scope.kt index d5e874c..54c734f 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Context.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Scope.kt @@ -1,17 +1,17 @@ package net.sergeych.lyng -open class Context( - val parent: Context?, +open class Scope( + val parent: Scope?, val args: Arguments = Arguments.EMPTY, var pos: Pos = Pos.builtIn, var thisObj: Obj = ObjVoid, - var skipContextCreation: Boolean = false, + var skipScopeCreation: Boolean = false, ) { constructor( args: Arguments = Arguments.EMPTY, pos: Pos = Pos.builtIn, ) - : this(Script.defaultContext, args, pos) + : this(Script.defaultScope, args, pos) fun raiseNotImplemented(what: String = "operation"): Nothing = raiseError("$what is not implemented") @@ -75,13 +75,13 @@ open class Context( ?: thisObj.objClass.getInstanceMemberOrNull(name) } - fun copy(pos: Pos, args: Arguments = Arguments.EMPTY, newThisObj: Obj? = null): Context = - Context(this, args, pos, newThisObj ?: thisObj) + fun copy(pos: Pos, args: Arguments = Arguments.EMPTY, newThisObj: Obj? = null): Scope = + Scope(this, args, pos, newThisObj ?: thisObj) - fun copy(args: Arguments = Arguments.EMPTY, newThisObj: Obj? = null): Context = - Context(this, args, pos, newThisObj ?: thisObj) + fun copy(args: Arguments = Arguments.EMPTY, newThisObj: Obj? = null): Scope = + Scope(this, args, pos, newThisObj ?: thisObj) - fun copy() = Context(this, args, pos, thisObj) + fun copy() = Scope(this, args, pos, thisObj) fun addItem( name: String, @@ -97,18 +97,18 @@ open class Context( return ns.objClass } - inline fun addVoidFn(vararg names: String, crossinline fn: suspend Context.() -> Unit) { + inline fun addVoidFn(vararg names: String, crossinline fn: suspend Scope.() -> Unit) { addFn(*names) { fn(this) ObjVoid } } - inline fun addFn(vararg names: String, crossinline fn: suspend Context.() -> T) { + inline fun addFn(vararg names: String, crossinline fn: suspend Scope.() -> T) { val newFn = object : Statement() { override val pos: Pos = Pos.builtIn - override suspend fun execute(context: Context): Obj = context.fn() + override suspend fun execute(scope: Scope): Obj = scope.fn() } for (name in names) { diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt index ebcbc5b..52f1113 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt @@ -9,18 +9,18 @@ class Script( // private val catchReturn: Boolean = false, ) : Statement() { - override suspend fun execute(context: Context): Obj { + override suspend fun execute(scope: Scope): Obj { var lastResult: Obj = ObjVoid for (s in statements) { - lastResult = s.execute(context) + lastResult = s.execute(scope) } return lastResult } - suspend fun execute() = execute(defaultContext.copy(pos = pos)) + suspend fun execute() = execute(defaultScope.copy(pos = pos)) companion object { - val defaultContext: Context = Context().apply { + val defaultScope: Scope = Scope().apply { ObjException.addExceptionsToContext(this) addFn("println") { for ((i, a) in args.withIndex()) { diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ScriptError.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ScriptError.kt index 14d6b14..b60732b 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ScriptError.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/ScriptError.kt @@ -12,4 +12,4 @@ open class ScriptError(val pos: Pos, val errorMessage: String,cause: Throwable?= cause ) -class ExecutionError(val errorObject: ObjException) : ScriptError(errorObject.context.pos, errorObject.message) +class ExecutionError(val errorObject: ObjException) : ScriptError(errorObject.scope.pos, errorObject.message) diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/statements.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/statements.kt index 97d8aac..d1bcf58 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/statements.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/statements.kt @@ -18,14 +18,14 @@ abstract class Statement( override val objClass: ObjClass = type abstract val pos: Pos - abstract suspend fun execute(context: Context): Obj + abstract suspend fun execute(scope: Scope): Obj - override suspend fun compareTo(context: Context,other: Obj): Int { + override suspend fun compareTo(scope: Scope, other: Obj): Int { throw UnsupportedOperationException("not comparable") } - override suspend fun callOn(context: Context): Obj { - return execute(context) + override suspend fun callOn(scope: Scope): Obj { + return execute(scope) } override fun toString(): String = "Callable@${this.hashCode()}" @@ -34,7 +34,7 @@ abstract class Statement( val type = ObjClass("Callable") } - suspend fun call(context: Context,vararg args: Obj) = execute(context.copy(args = Arguments(*args))) + suspend fun call(scope: Scope, vararg args: Obj) = execute(scope.copy(args = Arguments(*args))) } @@ -47,16 +47,16 @@ fun Statement.require(cond: Boolean, message: () -> String) { if (!cond) raise(message()) } -fun statement(pos: Pos, isStaticConst: Boolean = false, isConst: Boolean = false, f: suspend (Context) -> Obj): Statement = +fun statement(pos: Pos, isStaticConst: Boolean = false, isConst: Boolean = false, f: suspend (Scope) -> Obj): Statement = object : Statement(isStaticConst, isConst) { override val pos: Pos = pos - override suspend fun execute(context: Context): Obj = f(context) + override suspend fun execute(scope: Scope): Obj = f(scope) } -fun statement(isStaticConst: Boolean = false, isConst: Boolean = false, f: suspend Context.() -> Obj): Statement = +fun statement(isStaticConst: Boolean = false, isConst: Boolean = false, f: suspend Scope.() -> Obj): Statement = object : Statement(isStaticConst, isConst) { override val pos: Pos = Pos.builtIn - override suspend fun execute(context: Context): Obj = f(context) + override suspend fun execute(scope: Scope): Obj = f(scope) } diff --git a/lynglib/src/commonTest/kotlin/ScriptTest.kt b/lynglib/src/commonTest/kotlin/ScriptTest.kt index 2455bd9..e770d42 100644 --- a/lynglib/src/commonTest/kotlin/ScriptTest.kt +++ b/lynglib/src/commonTest/kotlin/ScriptTest.kt @@ -173,55 +173,55 @@ class ScriptTest { @Test fun varsAndConstsTest() = runTest { - val context = Context(pos = Pos.builtIn) + val scope = Scope(pos = Pos.builtIn) assertEquals( - ObjInt(3L), context.eval( + ObjInt(3L), scope.eval( """ val a = 17 var b = 3 """.trimIndent() ) ) - assertEquals(17, context.eval("a").toInt()) - assertEquals(20, context.eval("b + a").toInt()) + assertEquals(17, scope.eval("a").toInt()) + assertEquals(20, scope.eval("b + a").toInt()) assertFailsWith { - context.eval("a = 10") + scope.eval("a = 10") } - assertEquals(17, context.eval("a").toInt()) - assertEquals(5, context.eval("b = a - 7 - 5").toInt()) - assertEquals(5, context.eval("b").toInt()) + assertEquals(17, scope.eval("a").toInt()) + assertEquals(5, scope.eval("b = a - 7 - 5").toInt()) + assertEquals(5, scope.eval("b").toInt()) } @Test fun functionTest() = runTest { - val context = Context(pos = Pos.builtIn) - context.eval( + val scope = Scope(pos = Pos.builtIn) + scope.eval( """ fun foo(a, b) { a + b } """.trimIndent() ) - assertEquals(17, context.eval("foo(3,14)").toInt()) + assertEquals(17, scope.eval("foo(3,14)").toInt()) assertFailsWith { - assertEquals(17, context.eval("foo(3)").toInt()) + assertEquals(17, scope.eval("foo(3)").toInt()) } - context.eval( + scope.eval( """ fn bar(a, b=10) { a + b + 1 } """.trimIndent() ) - assertEquals(10, context.eval("bar(3, 6)").toInt()) - assertEquals(14, context.eval("bar(3)").toInt()) + assertEquals(10, scope.eval("bar(3, 6)").toInt()) + assertEquals(14, scope.eval("bar(3)").toInt()) } @Test fun simpleClosureTest() = runTest { - val context = Context(pos = Pos.builtIn) - context.eval( + val scope = Scope(pos = Pos.builtIn) + scope.eval( """ var global = 10 @@ -230,16 +230,16 @@ class ScriptTest { } """.trimIndent() ) - assertEquals(27, context.eval("foo(3,14)").toInt()) - context.eval("global = 20") - assertEquals(37, context.eval("foo(3,14)").toInt()) + assertEquals(27, scope.eval("foo(3,14)").toInt()) + scope.eval("global = 20") + assertEquals(37, scope.eval("foo(3,14)").toInt()) } @Test fun nullAndVoidTest() = runTest { - val context = Context(pos = Pos.builtIn) - assertEquals(ObjVoid, context.eval("void")) - assertEquals(ObjNull, context.eval("null")) + val scope = Scope(pos = Pos.builtIn) + assertEquals(ObjVoid, scope.eval("void")) + assertEquals(ObjNull, scope.eval("null")) } @Test @@ -346,8 +346,8 @@ class ScriptTest { @Test fun ifTest() = runTest { // if - single line - var context = Context(pos = Pos.builtIn) - context.eval( + var scope = Scope(pos = Pos.builtIn) + scope.eval( """ fn test1(n) { var result = "more" @@ -357,12 +357,12 @@ class ScriptTest { } """.trimIndent() ) - assertEquals("enough", context.eval("test1(11)").toString()) - assertEquals("more", context.eval("test1(1)").toString()) + assertEquals("enough", scope.eval("test1(11)").toString()) + assertEquals("more", scope.eval("test1(1)").toString()) // if - multiline (block) - context = Context(pos = Pos.builtIn) - context.eval( + scope = Scope(pos = Pos.builtIn) + scope.eval( """ fn test1(n) { var prefix = "answer: " @@ -376,12 +376,12 @@ class ScriptTest { } """.trimIndent() ) - assertEquals("answer: enough", context.eval("test1(11)").toString()) - assertEquals("answer: more", context.eval("test1(1)").toString()) + assertEquals("answer: enough", scope.eval("test1(11)").toString()) + assertEquals("answer: more", scope.eval("test1(1)").toString()) // else single line1 - context = Context(pos = Pos.builtIn) - context.eval( + scope = Scope(pos = Pos.builtIn) + scope.eval( """ fn test1(n) { if( n >= 10 ) @@ -391,12 +391,12 @@ class ScriptTest { } """.trimIndent() ) - assertEquals("enough", context.eval("test1(11)").toString()) - assertEquals("more", context.eval("test1(1)").toString()) + assertEquals("enough", scope.eval("test1(11)").toString()) + assertEquals("more", scope.eval("test1(1)").toString()) // if/else with blocks - context = Context(pos = Pos.builtIn) - context.eval( + scope = Scope(pos = Pos.builtIn) + scope.eval( """ fn test1(n) { if( n > 20 ) { @@ -410,9 +410,9 @@ class ScriptTest { } """.trimIndent() ) - assertEquals("enough", context.eval("test1(11)").toString()) - assertEquals("more", context.eval("test1(1)").toString()) - assertEquals("too much", context.eval("test1(100)").toString()) + assertEquals("enough", scope.eval("test1(11)").toString()) + assertEquals("more", scope.eval("test1(1)").toString()) + assertEquals("too much", scope.eval("test1(100)").toString()) } @Test @@ -512,13 +512,13 @@ class ScriptTest { ArgsDeclaration.Item("c"), ), ttEnd ) - var c = Context(pos = Pos.builtIn, args = Arguments.from(listOf(1, 2, 3).map { it.toObj() })) + var c = Scope(pos = Pos.builtIn, args = Arguments.from(listOf(1, 2, 3).map { it.toObj() })) pa.assignToContext(c) assertEquals(ObjInt(1), c["a"]?.value) assertEquals(ObjInt(2), c["b"]?.value) assertEquals(ObjInt(3), c["c"]?.value) // less args: error - c = Context(pos = Pos.builtIn, args = Arguments.from(listOf(1, 2).map { it.toObj() })) + c = Scope(pos = Pos.builtIn, args = Arguments.from(listOf(1, 2).map { it.toObj() })) assertFailsWith { pa.assignToContext(c) } @@ -535,7 +535,7 @@ class ScriptTest { assertEquals(ObjInt(2), c["b"]?.value) assertEquals(ObjInt(100), c["c"]?.value) // enough args. default value is ignored: - c = Context(pos = Pos.builtIn, args = Arguments.from(listOf(10, 2, 5).map { it.toObj() })) + c = Scope(pos = Pos.builtIn, args = Arguments.from(listOf(10, 2, 5).map { it.toObj() })) pa.assignToContext(c) assertEquals(ObjInt(10), c["a"]?.value) assertEquals(ObjInt(2), c["b"]?.value) @@ -553,17 +553,17 @@ class ScriptTest { ArgsDeclaration.Item("b", isEllipsis = true), ), ttEnd ) - var c = Context(args = Arguments.from(listOf(1, 2, 3).map { it.toObj() })) + var c = Scope(args = Arguments.from(listOf(1, 2, 3).map { it.toObj() })) pa.assignToContext(c) c.eval("assert( a == 1 ); println(b)") c.eval("assert( b == [2,3] )") - c = Context(args = Arguments.from(listOf(1, 2).map { it.toObj() })) + c = Scope(args = Arguments.from(listOf(1, 2).map { it.toObj() })) pa.assignToContext(c) c.eval("assertEquals( a, 1 ); println(b)") c.eval("assertEquals( b, [2] )") - c = Context(args = Arguments.from(listOf(1).map { it.toObj() })) + c = Scope(args = Arguments.from(listOf(1).map { it.toObj() })) pa.assignToContext(c) c.eval("assert( a == 1 ); println(b)") c.eval("assert( b == [] )") @@ -579,25 +579,25 @@ class ScriptTest { ArgsDeclaration.Item("c"), ), ttEnd ) - var c = Context(args = Arguments.from(listOf(0, 1, 2, 3).map { it.toObj() })) + var c = Scope(args = Arguments.from(listOf(0, 1, 2, 3).map { it.toObj() })) pa.assignToContext(c) c.eval("assertEquals( a,[0,1] )") c.eval("assertEquals( b, 2 )") c.eval("assertEquals( c, 3 )") - c = Context(args = Arguments.from(listOf(1, 2, 3).map { it.toObj() })) + c = Scope(args = Arguments.from(listOf(1, 2, 3).map { it.toObj() })) pa.assignToContext(c) c.eval("assertEquals( a,[1] )") c.eval("assertEquals( b, 2 )") c.eval("assertEquals( c, 3 )") - c = Context(args = Arguments.from(listOf(2, 3).map { it.toObj() })) + c = Scope(args = Arguments.from(listOf(2, 3).map { it.toObj() })) pa.assignToContext(c) c.eval("assertEquals( a,[] )") c.eval("assertEquals( b, 2 )") c.eval("assertEquals( c, 3 )") - c = Context(args = Arguments.from(listOf(3).map { it.toObj() })) + c = Scope(args = Arguments.from(listOf(3).map { it.toObj() })) assertFailsWith { pa.assignToContext(c) } @@ -614,28 +614,28 @@ class ScriptTest { ArgsDeclaration.Item("c"), ), ttEnd ) - var c = Context(args = Arguments.from(listOf(-1, 0, 1, 2, 3).map { it.toObj() })) + var c = Scope(args = Arguments.from(listOf(-1, 0, 1, 2, 3).map { it.toObj() })) pa.assignToContext(c) c.eval("assertEquals( i, -1 )") c.eval("assertEquals( a,[0,1] )") c.eval("assertEquals( b, 2 )") c.eval("assertEquals( c, 3 )") - c = Context(args = Arguments.from(listOf(0, 1, 2, 3).map { it.toObj() })) + c = Scope(args = Arguments.from(listOf(0, 1, 2, 3).map { it.toObj() })) pa.assignToContext(c) c.eval("assertEquals( i, 0 )") c.eval("assertEquals( a,[1] )") c.eval("assertEquals( b, 2 )") c.eval("assertEquals( c, 3 )") - c = Context(args = Arguments.from(listOf(1, 2, 3).map { it.toObj() })) + c = Scope(args = Arguments.from(listOf(1, 2, 3).map { it.toObj() })) pa.assignToContext(c) c.eval("assertEquals( i, 1)") c.eval("assertEquals( a,[] )") c.eval("assertEquals( b, 2 )") c.eval("assertEquals( c, 3 )") - c = Context(args = Arguments.from(listOf(2, 3).map { it.toObj() })) + c = Scope(args = Arguments.from(listOf(2, 3).map { it.toObj() })) assertFailsWith { pa.assignToContext(c) } @@ -756,7 +756,7 @@ class ScriptTest { @Test fun testIncr() = runTest { - val c = Context() + val c = Scope() c.eval("var x = 10") assertEquals(10, c.eval("x++").toInt()) assertEquals(11, c.eval("x++").toInt()) @@ -768,7 +768,7 @@ class ScriptTest { @Test fun testDecr() = runTest { - val c = Context() + val c = Scope() c.eval("var x = 9") assertEquals(9, c.eval("x--").toInt()) assertEquals(8, c.eval("x--").toInt()) @@ -779,7 +779,7 @@ class ScriptTest { @Test fun testDecrIncr() = runTest { - val c = Context() + val c = Scope() c.eval("var x = 9") assertEquals(9, c.eval("x++").toInt()) assertEquals(10, c.eval("x++").toInt()) @@ -793,7 +793,7 @@ class ScriptTest { @Test fun testDecrIncr2() = runTest { - val c = Context() + val c = Scope() c.eval("var x = 9") assertEquals(9, c.eval("x--").toInt()) assertEquals(8, c.eval("x--").toInt()) @@ -810,7 +810,7 @@ class ScriptTest { @Test fun testDecrIncr3() = runTest { - val c = Context() + val c = Scope() c.eval("var x = 9") assertEquals(9, c.eval("x++").toInt()) assertEquals(10, c.eval("x++").toInt()) @@ -822,7 +822,7 @@ class ScriptTest { @Test fun testIncrAndDecr() = runTest { - val c = Context() + val c = Scope() assertEquals( "8", c.eval( """ @@ -857,7 +857,7 @@ class ScriptTest { @Test fun testAssign1() = runTest { assertEquals(10, eval("var x = 5; x=10; x").toInt()) - val ctx = Context() + val ctx = Scope() ctx.eval( """ var a = 1 @@ -871,7 +871,7 @@ class ScriptTest { @Test fun testAssign2() = runTest { - val ctx = Context() + val ctx = Scope() ctx.eval("var x = 10") assertEquals(14, ctx.eval("x += 4").toInt()) assertEquals(14, ctx.eval("x").toInt()) @@ -889,7 +889,7 @@ class ScriptTest { @Test fun testVals() = runTest { - val cxt = Context() + val cxt = Scope() cxt.eval("val x = 11") assertEquals(11, cxt.eval("x").toInt()) assertFails { cxt.eval("x = 12") } @@ -1436,7 +1436,7 @@ class ScriptTest { @Test fun testSimpleStruct() = runTest { - val c = Context() + val c = Scope() c.eval( """ class Point(x,y) @@ -1457,7 +1457,7 @@ class ScriptTest { @Test fun testNonAssignalbeFieldInStruct() = runTest { - val c = Context() + val c = Scope() c.eval( """ class Point(x,y) @@ -1474,7 +1474,7 @@ class ScriptTest { @Test fun testStructBodyVal() = runTest { - val c = Context() + val c = Scope() c.eval( """ class Point(x,y) { @@ -1496,7 +1496,7 @@ class ScriptTest { @Test fun testStructBodyFun() = runTest { - val c = Context() + val c = Scope() c.eval( """ class Point(x,y) { @@ -1516,7 +1516,7 @@ class ScriptTest { @Test fun testPrivateConstructorParams() = runTest { - val c = Context() + val c = Scope() c.eval( """ class Point(private var x,y) @@ -1871,7 +1871,7 @@ class ScriptTest { @Test fun testTryFinally() = runTest { - val c = Context() + val c = Scope() assertFails { c.eval( """ @@ -1894,7 +1894,7 @@ class ScriptTest { @Test fun testThrowFromKotlin() = runTest { - val c = Context() + val c = Scope() c.addFn("callThrow") { raiseIllegalArgument("fromKotlin") } @@ -2316,7 +2316,7 @@ class ScriptTest { @Test fun testToFlow() = runTest() { - val c = Context() + val c = Scope() val arr = c.eval("[1,2,3]") // array is iterable so we can: assertEquals(listOf(1,2,3), arr.toFlow(c).map { it.toInt() }.toList()) diff --git a/lynglib/src/jvmTest/kotlin/BookTest.kt b/lynglib/src/jvmTest/kotlin/BookTest.kt index d7000b0..4c0a460 100644 --- a/lynglib/src/jvmTest/kotlin/BookTest.kt +++ b/lynglib/src/jvmTest/kotlin/BookTest.kt @@ -3,8 +3,8 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.test.runTest -import net.sergeych.lyng.Context import net.sergeych.lyng.ObjVoid +import net.sergeych.lyng.Scope import java.nio.file.Files import java.nio.file.Files.readAllLines import java.nio.file.Paths @@ -158,10 +158,10 @@ fun parseDocTests(fileName: String, bookMode: Boolean = false): Flow = } .flowOn(Dispatchers.IO) -suspend fun DocTest.test(context: Context = Context()) { +suspend fun DocTest.test(scope: Scope = Scope()) { val collectedOutput = StringBuilder() val currentTest = this - context.apply { + scope.apply { addFn("println") { if( bookMode ) { println("${currentTest.fileNamePart}:${currentTest.line}> ${args.joinToString(" "){it.asStr.value}}") @@ -177,7 +177,7 @@ suspend fun DocTest.test(context: Context = Context()) { } var error: Throwable? = null val result = try { - context.eval(code) + scope.eval(code) } catch (e: Throwable) { error = e null @@ -204,10 +204,10 @@ suspend fun DocTest.test(context: Context = Context()) { } suspend fun runDocTests(fileName: String, bookMode: Boolean = false) { - val bookContext = Context() + val bookScope = Scope() var count = 0 parseDocTests(fileName, bookMode).collect { dt -> - if (bookMode) dt.test(bookContext) + if (bookMode) dt.test(bookScope) else dt.test() count++ } diff --git a/lynglib/src/jvmTest/kotlin/SamplesTest.kt b/lynglib/src/jvmTest/kotlin/SamplesTest.kt index 1165242..726c549 100644 --- a/lynglib/src/jvmTest/kotlin/SamplesTest.kt +++ b/lynglib/src/jvmTest/kotlin/SamplesTest.kt @@ -2,7 +2,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext import kotlinx.datetime.Clock -import net.sergeych.lyng.Context +import net.sergeych.lyng.Scope import java.nio.file.Files import java.nio.file.Paths import kotlin.io.path.extension @@ -13,7 +13,7 @@ suspend fun executeSampleTests(fileName: String) { Files.readString(Paths.get(fileName)) } runBlocking { - val c = Context() + val c = Scope() val start = Clock.System.now() c.eval(sample) val time = Clock.System.now() - start