@@ -9,6 +9,12 @@ import scala.scalanative.cli.options._
9
9
import scala .scalanative .nir .Global
10
10
import scala .scalanative .build .Config
11
11
import 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
12
18
13
19
object ScalaNativeP extends CaseApp [POptions ] {
14
20
@@ -19,7 +25,10 @@ object ScalaNativeP extends CaseApp[POptions] {
19
25
}
20
26
21
27
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." )
23
32
exit(1 )
24
33
}
25
34
@@ -32,29 +41,81 @@ object ScalaNativeP extends CaseApp[POptions] {
32
41
System .err.println(s " Ignoring non existing path: $path" )
33
42
}
34
43
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 = {
35
52
Scope { implicit scope =>
36
53
val classLoader =
37
54
ClassLoader .fromDisk {
38
55
Config .empty.withClassPath(classpath)
39
56
}
40
57
41
58
for {
42
- fileName <- args.all
59
+ className <- args
43
60
} {
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}` " )
53
64
}
54
65
}
55
66
}
56
67
}
57
68
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
+
58
119
private def fail (msg : String ): Nothing = {
59
120
Console .err.println(msg)
60
121
exit(1 )
0 commit comments