@@ -9,6 +9,12 @@ import scala.scalanative.cli.options._
99import scala .scalanative .nir .Global
1010import scala .scalanative .build .Config
1111import scala .scalanative .linker .ClassLoader
12+ import java .nio .file .Path
13+ import scala .scalanative .io .VirtualDirectory
14+ import scala .scalanative .nir .serialization .deserializeBinary
15+ import scala .scalanative .nir .Defn
16+ import scala .annotation .tailrec
17+ import java .nio .ByteBuffer
1218
1319object ScalaNativeP extends CaseApp [POptions ] {
1420
@@ -19,7 +25,10 @@ object ScalaNativeP extends CaseApp[POptions] {
1925 }
2026
2127 if (args.all.isEmpty) {
22- System .err.println(" Required NIR file not specified." )
28+ if (options.fromPath)
29+ System .err.println(" Required NIR file not specified." )
30+ else
31+ System .err.println(" Required class/object not specified." )
2332 exit(1 )
2433 }
2534
@@ -32,29 +41,81 @@ object ScalaNativeP extends CaseApp[POptions] {
3241 System .err.println(s " Ignoring non existing path: $path" )
3342 }
3443
44+ if (options.fromPath) printFromFiles(classpath, args.all)
45+ else printFromNames(classpath, args.all)
46+ }
47+
48+ private def printFromNames (
49+ classpath : List [Path ],
50+ args : Seq [String ]
51+ ): Unit = {
3552 Scope { implicit scope =>
3653 val classLoader =
3754 ClassLoader .fromDisk {
3855 Config .empty.withClassPath(classpath)
3956 }
4057
4158 for {
42- fileName <- args.all
59+ className <- args
4360 } {
44- classLoader.load(Global .Top (fileName)) match {
45- case Some (defns) =>
46- defns
47- .sortBy(_.name.mangle)
48- .foreach { d =>
49- println(d.show)
50- println()
51- }
52- case None => fail(s " Not found class/object with name ` ${fileName}` " )
61+ classLoader.load(Global .Top (className)) match {
62+ case Some (defns) => printNIR(defns)
63+ case None => fail(s " Not found class/object with name ` ${className}` " )
5364 }
5465 }
5566 }
5667 }
5768
69+ private def printFromFiles (
70+ classpath : List [Path ],
71+ args : Seq [String ]
72+ ): Unit = {
73+
74+ Scope { implicit scope =>
75+ val cp = classpath.toStream.map(VirtualDirectory .real(_))
76+ def virtualDirPathMatches (
77+ virtualPath : Path ,
78+ regularPath : Path
79+ ): Boolean = {
80+ // Paths in jars are always using Unix path denotation
81+ val relativeInJar = virtualPath.toString().stripPrefix(" /" )
82+ relativeInJar == regularPath.toString()
83+ }
84+ @ tailrec
85+ def findAndRead (
86+ classpath : Stream [VirtualDirectory ],
87+ path : Path
88+ ): Option [ByteBuffer ] = {
89+ classpath match {
90+ case Stream .Empty => None
91+ case dir #:: tail =>
92+ val found = dir.files
93+ .find(virtualDirPathMatches(_, path))
94+ .map(dir.read(_))
95+ if (found.isEmpty) findAndRead(tail, path)
96+ else found
97+ }
98+ }
99+ for {
100+ fileName <- args
101+ path = Paths .get(fileName).normalize()
102+ content <- findAndRead(cp, path)
103+ .orElse(fail(s " Not found file with name ` ${fileName}` " ))
104+ } {
105+ val defns = deserializeBinary(content, fileName)
106+ printNIR(defns)
107+ }
108+ }
109+ }
110+
111+ private def printNIR (defns : Seq [Defn ]) =
112+ defns
113+ .sortBy(_.name.mangle)
114+ .foreach { d =>
115+ println(d.show)
116+ println()
117+ }
118+
58119 private def fail (msg : String ): Nothing = {
59120 Console .err.println(msg)
60121 exit(1 )
0 commit comments