A bit of infrastructure for the klib pretty printer.

This commit is contained in:
Alexander Gorshenev
2017-06-08 13:25:43 +03:00
committed by alexander-gorshenev
parent 9e8ca0fa8d
commit a23c64012b
6 changed files with 77 additions and 30 deletions
+4 -4
View File
@@ -47,14 +47,14 @@ The **klib** library management utility allows one to inspect and install the li
The following commands are available. The following commands are available.
To list library contents:
$ klib contents foo
To ask the details of the library To ask the details of the library
$ klib info foo $ klib info foo
To list library contents:
$ klib list foo
To install the library to the default location use To install the library to the default location use
$ klib install foo $ klib install foo
@@ -50,15 +50,15 @@ abstract open class FileBasedLibraryReader(
override val moduleName: String override val moduleName: String
get() = namedModuleData.name get() = namedModuleData.name
protected val tableOfContentsAsString : String val tableOfContents : Base64
get() = namedModuleData.base64 get() = namedModuleData.base64
protected fun packageMetadata(fqName: String): Base64 = fun packageMetadata(fqName: String): Base64 =
reader.loadSerializedPackageFragment(fqName) reader.loadSerializedPackageFragment(fqName)
override fun moduleDescriptor(specifics: LanguageVersionSettings) override fun moduleDescriptor(specifics: LanguageVersionSettings)
= deserializeModule(specifics, {packageMetadata(it)}, = deserializeModule(specifics, {packageMetadata(it)},
tableOfContentsAsString, moduleName) tableOfContents, moduleName)
} }
// This scheme describes the Konan Library (klib) layout. // This scheme describes the Konan Library (klib) layout.
@@ -45,8 +45,8 @@ override fun loadSerializedModule(currentAbiVersion: Int): NamedModuleData {
throw Error("Expected ABI version ${currentAbiVersion}, but the binary is ${abiVersion}") throw Error("Expected ABI version ${currentAbiVersion}, but the binary is ${abiVersion}")
} }
val moduleName = string(nameNode) val moduleName = string(nameNode)
val tableOfContentsAsString = string(dataNode) val tableOfContents = string(dataNode)
return NamedModuleData(moduleName, tableOfContentsAsString) return NamedModuleData(moduleName, tableOfContents)
} }
override fun loadSerializedPackageFragment(fqName: String): String { override fun loadSerializedPackageFragment(fqName: String): String {
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer
import org.jetbrains.kotlin.serialization.KonanLinkData import org.jetbrains.kotlin.serialization.KonanLinkData
import org.jetbrains.kotlin.serialization.KonanLinkData.*
import org.jetbrains.kotlin.serialization.ProtoBuf import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.* import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
@@ -123,11 +124,13 @@ fun createKonanPackageFragmentProvider(
return provider return provider
} }
internal fun deserializePackageFragment(base64: Base64): KonanLinkData.PackageFragment { public fun parsePackageFragment(base64: Base64): PackageFragment =
return KonanLinkData.PackageFragment PackageFragment.parseFrom(base64ToStream(base64),
.parseFrom(base64ToStream(base64), KonanSerializerProtocol.extensionRegistry)
KonanSerializerProtocol.extensionRegistry)
} public fun parseModuleHeader(base64: Base64): Library =
Library.parseFrom(base64ToStream(base64),
KonanSerializerProtocol.extensionRegistry)
internal fun deserializeModule(languageVersionSettings: LanguageVersionSettings, internal fun deserializeModule(languageVersionSettings: LanguageVersionSettings,
packageLoader:(String)->Base64, library: Base64, moduleName: String): ModuleDescriptorImpl { packageLoader:(String)->Base64, library: Base64, moduleName: String): ModuleDescriptorImpl {
@@ -139,13 +142,11 @@ internal fun deserializeModule(languageVersionSettings: LanguageVersionSettings,
builtIns.builtInsModule = moduleDescriptor builtIns.builtInsModule = moduleDescriptor
val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings) val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings)
val libraryProto = KonanLinkData.Library val libraryProto = parseModuleHeader(library)
.parseFrom(base64ToStream(library),
KonanSerializerProtocol.extensionRegistry)
val provider = createKonanPackageFragmentProvider( val provider = createKonanPackageFragmentProvider(
libraryProto.packageFragmentNameList, libraryProto.packageFragmentNameList,
{it -> deserializePackageFragment(packageLoader(it))}, {it -> parsePackageFragment(packageLoader(it))},
storageManager, storageManager,
moduleDescriptor, deserializationConfiguration) moduleDescriptor, deserializationConfiguration)
@@ -0,0 +1,41 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.cli.klib
import org.jetbrains.kotlin.serialization.KonanLinkData
import org.jetbrains.kotlin.backend.konan.serialization.Base64
import org.jetbrains.kotlin.backend.konan.serialization.parseModuleHeader
import org.jetbrains.kotlin.backend.konan.serialization.parsePackageFragment
class PrettyPrinter(val library: Base64, val packageLoader: (String) -> Base64) {
private val moduleHeader: KonanLinkData.Library
get() = parseModuleHeader(library)
fun packageFragment(fqname: String): KonanLinkData.PackageFragment
= parsePackageFragment(packageLoader(fqname))
val packageFragmentNameList: List<String>
get() = moduleHeader.packageFragmentNameList
fun printPackageFragment(fqname: String) {
if (fqname.isNotEmpty()) println("package $fqname" )
println("\tHere goes the \"$fqname\" package body.\n\tIt is not implemented yet.\n")
// TODO: implement deserialized package protobuf print out.
}
}
@@ -13,7 +13,7 @@ fun printUsage() {
println("where the commands are:") println("where the commands are:")
println("\tinfo\tgeneral information about the library") println("\tinfo\tgeneral information about the library")
println("\tinstall\tinstall the library to the local repository") println("\tinstall\tinstall the library to the local repository")
println("\tlist\tcontents of the library") println("\tcontents\tlist contents of the library")
println("\tremove\tremove the library from the local repository") println("\tremove\tremove the library from the local repository")
println("and the options are:") println("and the options are:")
println("\t-repository <path>\twork with the specified repository") println("\t-repository <path>\twork with the specified repository")
@@ -66,8 +66,8 @@ class Library(val name: String, val repository: String, val target: String) {
// TODO: need to do something here. // TODO: need to do something here.
val currentAbiVersion = 1 val currentAbiVersion = 1
val splitLibrary = SplitLibraryReader(file, currentAbiVersion, target) val library = SplitLibraryReader(file, currentAbiVersion, target)
val manifestFile = splitLibrary.manifestFile val manifestFile = library.manifestFile
fun info() { fun info() {
val header = Properties() val header = Properties()
@@ -78,29 +78,34 @@ class Library(val name: String, val repository: String, val target: String) {
val moduleName = header.getProperty("module_name")!! val moduleName = header.getProperty("module_name")!!
println("Module name: $moduleName") println("Module name: $moduleName")
println("ABI version: $headerAbiVersion") println("ABI version: $headerAbiVersion")
val targets = splitLibrary.targetsDir.listFiles.map{it.name}.joinToString(", ") val targets = library.targetsDir.listFiles.map{it.name}.joinToString(", ")
print("Available targets: $targets\n") print("Available targets: $targets\n")
} }
fun install() { fun install() {
remove() remove()
val baseName = splitLibrary.klibFile.name val baseName = library.klibFile.name
val newKlibName = File(repositoryFile, baseName) val newKlibName = File(repositoryFile, baseName)
splitLibrary.klibFile.copyTo(newKlibName) library.klibFile.copyTo(newKlibName)
} }
fun remove() { fun remove() {
repositoryFile.mkdirs() repositoryFile.mkdirs()
val baseName = splitLibrary.klibFile.name val baseName = library.klibFile.name
val newDirName = File(repositoryFile, splitLibrary.libDir.name) val newDirName = File(repositoryFile, library.libDir.name)
val newKlibName = File(repositoryFile, baseName) val newKlibName = File(repositoryFile, baseName)
newKlibName.deleteRecursively() newKlibName.deleteRecursively()
newDirName.deleteRecursively() newDirName.deleteRecursively()
} }
fun list() { fun contents() {
// TODO: implement printing deserialized module protobuf. val moduleName = library.moduleName
println("Module listing not implemented yet.") val printer = PrettyPrinter(
library.tableOfContents, {name -> library.packageMetadata(name)})
printer.packageFragmentNameList.forEach{
printer.printPackageFragment(it)
}
} }
} }
@@ -122,9 +127,9 @@ fun main(args: Array<String>) {
warn("IMPORTANT: the library format is unstable now. It can change with any new git commit without warning!") warn("IMPORTANT: the library format is unstable now. It can change with any new git commit without warning!")
when (command.verb) { when (command.verb) {
"contents" -> library.contents()
"info" -> library.info() "info" -> library.info()
"install" -> library.install() "install" -> library.install()
"list" -> library.list()
"remove" -> library.remove() "remove" -> library.remove()
else -> error("Unknown command ${command.verb}.") else -> error("Unknown command ${command.verb}.")
} }