Initial code:
private tailrec fun parseRecursively(contents: List<String>, filename: String, tablesAcc: List<Table> = emptyList()): List<Table> {
for (line in contents) {
if (isHeader(line)) {
val tableBlock = parseTableBlock(line, contents.subList(contents.indexOf(line) + 1, contents.size))
return parseRecursively(contents.subList(tableBlock.linesRead + 1, contents.size), filename, tablesAcc + tableBlock.table)
}
}
return tablesAcc
}
Which I converted to
private tailrec fun parseRecursively(contents: List<String>, filename: String, tablesAcc: List<Table> = emptyList()): List<Table> {
contents.firstOrNull { line -> isHeader(line) }
?.let { header ->
val tableBlock = parseTableBlock(header, contents.subList(contents.indexOf(header) + 1, contents.size))
return parseRecursively(contents.subList(tableBlock.linesRead + 1, contents.size), filename, tablesAcc + tableBlock.table)
}
return tablesAcc
}
The new code causes a Couldn't inline method call 'let' into ...
My guess is I’m doing something wrong or ambiguous, for example this works:
private fun parseRecursively(contents: List<String>, filename: String, tablesAcc: List<Table> = emptyList()): List<Table> {
return contents.firstOrNull { line -> isHeader(line) }
?.let { header ->
val tableBlock = parseTableBlock(header, contents.subList(contents.indexOf(header) + 1, contents.size))
parseRecursively(contents.subList(tableBlock.linesRead + 1, contents.size), filename, tablesAcc + tableBlock.table)
} ?: tablesAcc
}
But now I’m no longer tailrecursive. It’s not so bad because my recursive calls are usually very small, but I’m wondering what exactly I’m doing wrong :o
Here’s more of the error (Pastebin link for the full log) for funsies:
Error:Kotlin: [Internal Error] java.lang.IllegalStateException: Backend Internal error: Exception during code generation
Cause: Back-end (JVM) Internal error: Couldn't inline method call 'let' into
private final tailrec fun parseRecursively(contents: kotlin.collections.List<kotlin.String>, filename: kotlin.String, tablesAcc: kotlin.collections.List<com.christian.dnd.d100.model.Table> = ...): kotlin.collections.List<com.christian.dnd.d100.model.Table> defined in com.christian.dnd.d100.parsers.block.StructuredTableBlockParser
private tailrec fun parseRecursively(contents: List<String>, filename: String, tablesAcc: List<Table> = emptyList()): List<Table> {
contents.firstOrNull { line -> isHeader(line) }
?.let { header ->
val tableBlock = parseTableBlock(header, contents.subList(contents.indexOf(header) + 1, contents.size))
return parseRecursively(contents.subList(tableBlock.linesRead + 1, contents.size), filename, tablesAcc + tableBlock.table)
}
return tablesAcc
}
Cause: let (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;:
@Lkotlin/internal/InlineOnly;() // invisible
L0
LINENUMBER 97 L0
NOP
L1
LINENUMBER 100 L1
ALOAD 1
ALOAD 0
INVOKEINTERFACE kotlin/jvm/functions/Function1.invoke (Ljava/lang/Object;)Ljava/lang/Object; (itf)
ARETURN
L2
LOCALVARIABLE $receiver Ljava/lang/Object; L0 L2 0
LOCALVARIABLE block Lkotlin/jvm/functions/Function1; L0 L2 1
LOCALVARIABLE $i$f$let I L0 L2 2
MAXSTACK = 2
MAXLOCALS = 3
Cause: Failed to obtain parameter index: value-parameter tablesAcc: kotlin.collections.List<com.christian.dnd.d100.model.Table> = ... defined in com.christian.dnd.d100.parsers.block.StructuredTableBlockParser.parseRecursively[ValueParameterDescriptorImpl@4c040327]
File being compiled at position: (24,15) in /Users/christianbroomfield/Projects/Github/d100/src/main/kotlin/com/christian/dnd/d100/parsers/block/StructuredTableBlockParser.kt
The root cause was thrown at: TailRecursionCodegen.java:153
File being compiled at position: file:///Users/christianbroomfield/Projects/Github/d100/src/main/kotlin/com/christian/dnd/d100/parsers/block/StructuredTableBlockParser.kt
The root cause was thrown at: InlineCodegen.kt:128