Beginning of name support for issue #17

This commit is contained in:
Chad Retz 2018-07-25 12:57:54 -05:00
parent 3c25b40c40
commit 96febbecd5
4 changed files with 39 additions and 5 deletions

View File

@ -15,6 +15,7 @@ sealed class Node {
val elems: List<Elem> = emptyList(),
val funcs: List<Func> = emptyList(),
val data: List<Data> = emptyList(),
val names: NameSection? = null,
val customSections: List<CustomSection> = emptyList()
) : Node()
@ -148,6 +149,12 @@ sealed class Node {
}
}
data class NameSection(
val moduleName: String,
val funcNames: Map<Int, String>,
val localNames: Map<Int, Map<Int, String>>
) : Node()
sealed class Instr : Node() {
fun op() = InstrOp.classToOpMap[this::class] ?: throw Exception("No op found for ${this::class}")

View File

@ -51,7 +51,7 @@ open class Compile : Command<Compile.Args>() {
val inFormat =
if (args.inFormat != "<use file extension>") args.inFormat
else args.inFile.substringAfterLast('.', "<unknown>")
val script = Translate.inToAst(args.inFile, inFormat)
val script = Translate().also { it.logger = logger }.inToAst(args.inFile, inFormat)
val mod = (script.commands.firstOrNull() as? Script.Cmd.Module) ?:
error("Only a single sexpr for (module) allowed")
val outStream = when (args.outFile) {

View File

@ -84,7 +84,7 @@ open class Translate : Command<Translate.Args>() {
}
}
"wasm" ->
Script(listOf(Script.Cmd.Module(BinaryToAst.toModule(
Script(listOf(Script.Cmd.Module(BinaryToAst(logger = logger).toModule(
ByteReader.InputStream(inBytes.inputStream())), null)))
else -> error("Unknown in format '$inFormat'")
}

View File

@ -2,11 +2,13 @@ package asmble.io
import asmble.ast.Node
import asmble.util.*
import java.io.ByteArrayInputStream
import java.nio.ByteBuffer
open class BinaryToAst(
val version: Long = 1L,
val logger: Logger = Logger.Print(Logger.Level.OFF)
val logger: Logger = Logger.Print(Logger.Level.OFF),
val includeNameSection: Boolean = true
) : Logger by logger {
fun toBlockType(b: ByteReader) = b.readVarInt7().toInt().let {
@ -19,6 +21,23 @@ open class BinaryToAst(
payload = b.readBytes()
)
fun toNameSection(b: ByteReader) = generateSequence {
if (b.isEof) null
else b.readVarUInt7().toInt() to b.read(b.readVarUInt32AsInt())
}.fold(Node.NameSection("", emptyMap(), emptyMap())) { sect, (type, b) ->
fun <T> indexMap(b: ByteReader, fn: (ByteReader) -> T) =
b.readList { it.readVarUInt32AsInt() to fn(it) }.let { pairs ->
pairs.toMap().also { require(it.size == pairs.size) { "Malformed names: duplicate indices" } }
}
fun nameMap(b: ByteReader) = indexMap(b) { it.readString() }
when (type) {
0 -> sect.copy(moduleName = b.readString())
1 -> sect.copy(funcNames = nameMap(b))
2 -> sect.copy(localNames = indexMap(b, ::nameMap))
else -> error("Malformed names: unrecognized type: $type")
}.also { require(b.isEof) }
}
fun toData(b: ByteReader) = Node.Data(
index = b.readVarUInt32AsInt(),
offset = toInitExpr(b),
@ -173,6 +192,7 @@ open class BinaryToAst(
sections.find { it.first == sectionId }?.second?.readList(fn) ?: emptyList()
val types = readSectionList(1, this::toFuncType)
val funcIndices = readSectionList(3) { it.readVarUInt32AsInt() }
var nameSection: Node.NameSection? = null
return Node.Module(
types = types,
imports = readSectionList(2, this::toImport),
@ -193,10 +213,17 @@ open class BinaryToAst(
val afterSectionId = if (index == 0) 0 else sections[index - 1].let { (prevSectionId, _) ->
if (prevSectionId == 0) customSections.last().afterSectionId else prevSectionId
}
customSections + toCustomSection(b, afterSectionId)
// Try to parse the name section
val section = toCustomSection(b, afterSectionId).takeIf { section ->
!includeNameSection && section.afterSectionId != 11 || section.name != "name" || try {
nameSection = toNameSection(ByteReader.InputStream(section.payload.inputStream()))
false
} catch (e: Exception) { warn { "Failed parsing name section: $e" }; true }
}
if (section == null) customSections else customSections + section
}
}
)
).copy(names = nameSection)
}
fun toResizableLimits(b: ByteReader) = b.readVarUInt1().let {