blob: bbbbf40508c65ee3fcec536c17ccc03f252fb7f7 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
/*
* System.Reflection.Emit-like API for writing .NET assemblies in MSIL
*/
package ch.epfl.lamp.compiler.msil.emit
import java.io.File
import java.io.FileWriter
import java.io.BufferedWriter
import java.io.PrintWriter
import java.io.IOException
import java.util.Iterator
import java.util.Arrays
import ch.epfl.lamp.compiler.msil._
import ch.epfl.lamp.compiler.msil.emit
import ch.epfl.lamp.compiler.msil.util.Table
/**
* The MSIL printer Visitor. It prints a complete
* assembly into separate files. Then these files can be compiled by ilasm.
*
* @author Nikolay Mihaylov
* @author Daniel Lorch
* @version 1.0
*/
final class MultipleFilesILPrinterVisitor(destPath: String, sourceFilesPath: String) extends ILPrinterVisitor {
/**
* Visit an AssemblyBuilder
*/
@throws(classOf[IOException])
def caseAssemblyBuilder(assemblyBuilder: AssemblyBuilder) {
ILPrinterVisitor.currAssembly = assemblyBuilder
// first get the entryPoint
this.entryPoint = assemblyBuilder.EntryPoint
// all external assemblies
as = assemblyBuilder.getExternAssemblies()
scala.util.Sorting.quickSort(as)(assemblyNameComparator) // Arrays.sort(as, assemblyNameComparator)
// print each module
val m: Array[Module] = assemblyBuilder.GetModules()
nomembers = true
for(i <- 0 until m.length) {
print(m(i).asInstanceOf[ModuleBuilder])
}
nomembers = false
for(i <- 0 until m.length) {
print(m(i).asInstanceOf[ModuleBuilder])
}
ILPrinterVisitor.currAssembly = null
}
/**
* Visit a ModuleBuilder
*/
@throws(classOf[IOException])
def caseModuleBuilder(module: ModuleBuilder) {
val assemblyBuilder = ILPrinterVisitor.currAssembly.asInstanceOf[AssemblyBuilder]
// print module declaration
currentModule = module
// global methods typically contain the main method
if (!module.globalsCreated)
module.CreateGlobalFunctions()
val m: Array[MethodInfo] = module.GetMethods()
// "Types" contain all the classes
val t: Array[Type] = module.GetTypes()
for(i <- 0 until t.length) {
val tBuilder = t(i).asInstanceOf[TypeBuilder]
val sourceFilename = tBuilder.sourceFilename
val sourceFilepath = new File(tBuilder.sourceFilepath).getCanonicalPath
val sourcePath = new File(sourceFilesPath).getCanonicalPath
var append = false
if(!sourceFilepath.startsWith(sourcePath)) {
throw new IOException("Source file " + sourceFilename + " must lie inside sourcepath " + sourcePath)
}
assert(sourceFilepath.endsWith(".scala"), "Source file doesn't end with .scala")
val relativeFilename = sourceFilepath.substring(sourcePath.length, sourceFilepath.length() - 6) + ".msil"
val fileName = new File(destPath, relativeFilename)
if(assemblyBuilder.generatedFiles.contains(fileName.getPath)) {
append = true
} else {
fileName.getParentFile().mkdirs()
assemblyBuilder.generatedFiles += (fileName.getPath)
}
out = new PrintWriter(new BufferedWriter(new FileWriter(fileName, append)))
// only write assembly boilerplate and class prototypes
if (!append && nomembers) {
printAssemblyBoilerplate()
print(".module \'"); print(module.Name); println("\'")
printAttributes(module)
}
print(t(i).asInstanceOf[TypeBuilder])
out.close()
}
// now write the global methods (typically contains the "main" method)
if(!nomembers) {
val globalMethods: File = new File(destPath, ILPrinterVisitor.currAssembly.GetName().Name + ".msil")
val append = assemblyBuilder.generatedFiles.contains(globalMethods.getPath)
out = new PrintWriter(new BufferedWriter(new FileWriter(globalMethods, append)))
// make sure we're the first in the list (ilasm uses the first file name to guess the output file name)
assemblyBuilder.generatedFiles.insert(0, globalMethods.getPath)
// if this file hasn't been created by one of the classes, write boilerplate
if(!append) {
printAssemblyBoilerplate()
print(".module \'"); print(module.Name); println("\'")
printAttributes(module)
}
for(i <- 0 until m.length) {
print(m(i).asInstanceOf[MethodBuilder])
}
out.close()
}
currentModule = null
}
} // class MultipleFilesILPrinterVisitor
|