fix #16 last-block argument now can be combined with defaults and ellipsis
This commit is contained in:
parent
382532e0e1
commit
194fc8aca6
@ -5,7 +5,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
|
||||
group = "net.sergeych"
|
||||
version = "0.3.0-SNAPSHOT"
|
||||
version = "0.3.1-SNAPSHOT"
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
|
@ -23,7 +23,7 @@ data class ArgsDeclaration(val params: List<Item>, val endTokenType: Token.Type)
|
||||
*/
|
||||
suspend fun assignToContext(
|
||||
context: Context,
|
||||
_fromArgs: Arguments = context.args,
|
||||
arguments: Arguments = context.args,
|
||||
defaultAccessType: AccessType = AccessType.Var,
|
||||
defaultVisibility: Visibility = Visibility.Public
|
||||
) {
|
||||
@ -33,15 +33,25 @@ data class ArgsDeclaration(val params: List<Item>, val endTokenType: Token.Type)
|
||||
}
|
||||
|
||||
// will be used with last lambda arg fix
|
||||
val fromArgs = _fromArgs
|
||||
val callArgs: List<Obj>
|
||||
val paramsSize: Int
|
||||
|
||||
if( arguments.tailBlockMode ) {
|
||||
paramsSize = params.size - 1
|
||||
assign(params.last(), arguments.list.last())
|
||||
callArgs = arguments.list.dropLast(1)
|
||||
} else {
|
||||
paramsSize = params.size
|
||||
callArgs = arguments.list
|
||||
}
|
||||
|
||||
suspend fun processHead(index: Int): Int {
|
||||
var i = index
|
||||
while (i != params.size) {
|
||||
while (i != paramsSize) {
|
||||
val a = params[i]
|
||||
if (a.isEllipsis) break
|
||||
val value = when {
|
||||
i < fromArgs.size -> fromArgs[i]
|
||||
i < callArgs.size -> callArgs[i]
|
||||
a.defaultValue != null -> a.defaultValue.execute(context)
|
||||
else -> context.raiseArgumentError("too few arguments for the call")
|
||||
}
|
||||
@ -52,14 +62,14 @@ data class ArgsDeclaration(val params: List<Item>, val endTokenType: Token.Type)
|
||||
}
|
||||
|
||||
suspend fun processTail(index: Int): Int {
|
||||
var i = params.size - 1
|
||||
var j = fromArgs.size - 1
|
||||
var i = paramsSize - 1
|
||||
var j = callArgs.size - 1
|
||||
while (i > index) {
|
||||
val a = params[i]
|
||||
if (a.isEllipsis) break
|
||||
val value = when {
|
||||
j >= index -> {
|
||||
fromArgs[j--]
|
||||
callArgs[j--]
|
||||
}
|
||||
|
||||
a.defaultValue != null -> a.defaultValue.execute(context)
|
||||
@ -74,16 +84,16 @@ data class ArgsDeclaration(val params: List<Item>, val endTokenType: Token.Type)
|
||||
fun processEllipsis(index: Int, toFromIndex: Int) {
|
||||
val a = params[index]
|
||||
val l = if (index > toFromIndex) ObjList()
|
||||
else ObjList(fromArgs.list.subList(index, toFromIndex + 1).toMutableList())
|
||||
else ObjList(callArgs.subList(index, toFromIndex + 1).toMutableList())
|
||||
assign(a, l)
|
||||
}
|
||||
|
||||
val leftIndex = processHead(0)
|
||||
if (leftIndex < params.size) {
|
||||
if (leftIndex < paramsSize) {
|
||||
val end = processTail(leftIndex)
|
||||
processEllipsis(leftIndex, end)
|
||||
} else {
|
||||
if (leftIndex < fromArgs.size)
|
||||
if (leftIndex < callArgs.size)
|
||||
context.raiseArgumentError("too many arguments for the call")
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package net.sergeych.lyng
|
||||
|
||||
data class ParsedArgument(val value: Statement, val pos: Pos, val isSplat: Boolean = false)
|
||||
|
||||
suspend fun Collection<ParsedArgument>.toArguments(context: Context): Arguments {
|
||||
suspend fun Collection<ParsedArgument>.toArguments(context: Context,tailBlockMode: Boolean): Arguments {
|
||||
val list = mutableListOf<Obj>()
|
||||
|
||||
for (x in this) {
|
||||
@ -23,10 +23,10 @@ suspend fun Collection<ParsedArgument>.toArguments(context: Context): Arguments
|
||||
} else
|
||||
list.add(value)
|
||||
}
|
||||
return Arguments(list)
|
||||
return Arguments(list,tailBlockMode)
|
||||
}
|
||||
|
||||
data class Arguments(val list: List<Obj>) : List<Obj> by list {
|
||||
data class Arguments(val list: List<Obj>,val tailBlockMode: Boolean = false) : List<Obj> by list {
|
||||
|
||||
fun firstAndOnly(pos: Pos = Pos.UNKNOWN): Obj {
|
||||
if (list.size != 1) throw ScriptError(pos, "expected one argument, got ${list.size}")
|
||||
|
@ -149,7 +149,7 @@ class Compiler(
|
||||
v.invokeInstanceMethod(
|
||||
context,
|
||||
next.value,
|
||||
args.toArguments(context)
|
||||
args.toArguments(context,false)
|
||||
), isMutable = false
|
||||
)
|
||||
}
|
||||
@ -157,7 +157,7 @@ class Compiler(
|
||||
|
||||
Token.Type.LBRACE -> {
|
||||
// single lambda arg, like assertTrows { ... }
|
||||
cc.next()
|
||||
cc.next()
|
||||
isCall = true
|
||||
val lambda =
|
||||
parseExpression(cc) ?: throw ScriptError(t.pos, "expected valid lambda here")
|
||||
@ -170,7 +170,7 @@ class Compiler(
|
||||
v.invokeInstanceMethod(
|
||||
context,
|
||||
next.value,
|
||||
Arguments(listOf(lambda))
|
||||
Arguments(listOf(lambda),true)
|
||||
), isMutable = false
|
||||
)
|
||||
}
|
||||
@ -611,7 +611,7 @@ class Compiler(
|
||||
v.value.callOn(
|
||||
context.copy(
|
||||
context.pos,
|
||||
args.toArguments(context)
|
||||
args.toArguments(context, blockArgument)
|
||||
// Arguments(
|
||||
// args.map { Arguments.Info((it.value as Statement).execute(context), it.pos) }
|
||||
// ),
|
||||
|
@ -1585,16 +1585,59 @@ class ScriptTest {
|
||||
assertEquals("1.0E-6", eval("1e-6").toString())
|
||||
}
|
||||
|
||||
// @Test
|
||||
// fun testLambdaLastArgAfterDetault() = runTest {
|
||||
// val c = Context()
|
||||
// eval("""
|
||||
// // this means last is lambda:
|
||||
// fun f(e=1, f) {
|
||||
// "e="+e+"f="+f()
|
||||
// }
|
||||
// assertEquals("e=1f=xx", f { "xx" })
|
||||
// """.trimIndent())
|
||||
//
|
||||
// }
|
||||
@Test
|
||||
fun testCallLastBlockAfterDetault() = runTest {
|
||||
eval("""
|
||||
// this means last is lambda:
|
||||
fun f(e=1, f) {
|
||||
"e="+e+"f="+f()
|
||||
}
|
||||
assertEquals("e=1f=xx", f { "xx" })
|
||||
""".trimIndent())
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCallLastBlockWithEllipsis() = runTest {
|
||||
eval("""
|
||||
// this means last is lambda:
|
||||
fun f(e..., f) {
|
||||
"e="+e+"f="+f()
|
||||
}
|
||||
assertEquals("e=[]f=xx", f { "xx" })
|
||||
assertEquals("e=[1, 2]f=xx", f(1,2) { "xx" })
|
||||
""".trimIndent())
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMethodCallLastBlockAfterDefault() = runTest {
|
||||
eval("""
|
||||
class Foo {
|
||||
// this means last is lambda:
|
||||
fun f(e=1, f) {
|
||||
"e="+e+"f="+f()
|
||||
}
|
||||
}
|
||||
val f = Foo()
|
||||
assertEquals("e=1f=xx", f.f { "xx" })
|
||||
""".trimIndent())
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMethodCallLastBlockWithEllipsis() = runTest {
|
||||
eval("""
|
||||
class Foo {
|
||||
// this means last is lambda:
|
||||
fun f(e..., f) {
|
||||
"e="+e+"f="+f()
|
||||
}
|
||||
}
|
||||
val f = Foo()
|
||||
assertEquals("e=[]f=xx", f.f { "xx" })
|
||||
assertEquals("e=[1, 2]f=xx", f.f(1,2) { "xx" })
|
||||
""".trimIndent())
|
||||
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user