1 // A Small Compiler for a Simple Functional Language |
1 // A Small Compiler for a Simple Functional Language |
2 // (includes an external lexer and parser) |
2 // (includes an external lexer and parser) |
3 |
3 // |
4 import java.io._ |
4 // call with |
|
5 // |
|
6 // scala fun.scala fact |
|
7 // |
|
8 // scala fun.scala defs |
|
9 // |
|
10 // this will generate a .j file and run the jasmin |
|
11 // assembler (installed at jvm/jasmin-2.4/jasmin.jar) |
|
12 // it runs the resulting JVM file twice for timing |
|
13 // purposes. |
|
14 |
|
15 |
|
16 |
5 |
17 |
6 object Compiler { |
18 object Compiler { |
|
19 |
|
20 import java.io._ |
|
21 import scala.util._ |
|
22 import scala.sys.process._ |
7 |
23 |
8 // Abstract syntax trees for the Fun language |
24 // Abstract syntax trees for the Fun language |
9 abstract class Exp extends Serializable |
25 abstract class Exp extends Serializable |
10 abstract class BExp extends Serializable |
26 abstract class BExp extends Serializable |
11 abstract class Decl extends Serializable |
27 abstract class Decl extends Serializable |
163 for (j <- 1 to i) code |
179 for (j <- 1 to i) code |
164 val end = System.nanoTime() |
180 val end = System.nanoTime() |
165 (end - start)/(i * 1.0e9) |
181 (end - start)/(i * 1.0e9) |
166 } |
182 } |
167 |
183 |
168 def deserialise[T](fname: String) : T = { |
184 def deserialise[T](fname: String) : Try[T] = { |
169 val in = new ObjectInputStream(new FileInputStream(fname)) |
185 import scala.util.Using |
170 val data = in.readObject.asInstanceOf[T] |
186 Using(new ObjectInputStream(new FileInputStream(fname))) { |
171 in.close |
187 in => in.readObject.asInstanceOf[T] |
172 data |
188 } |
173 } |
189 } |
174 |
|
175 |
190 |
176 def compile(class_name: String) : String = { |
191 def compile(class_name: String) : String = { |
177 val ast = deserialise[List[Decl]](class_name ++ ".prs") |
192 val ast = deserialise[List[Decl]](class_name ++ ".prs").getOrElse(Nil) |
178 val instructions = ast.map(compile_decl).mkString |
193 val instructions = ast.map(compile_decl).mkString |
179 (library + instructions).replaceAllLiterally("XXX", class_name) |
194 (library + instructions).replaceAllLiterally("XXX", class_name) |
180 } |
195 } |
181 |
196 |
182 def compile_to_file(class_name: String) = { |
197 def compile_to_file(class_name: String) = { |
183 val output = compile(class_name) |
198 val output = compile(class_name) |
184 scala.tools.nsc.io.File(s"${class_name}.j").writeAll(output) |
199 scala.tools.nsc.io.File(s"${class_name}.j").writeAll(output) |
185 } |
200 } |
186 |
201 |
187 import scala.sys.process._ |
202 def compile_and_run(class_name: String) : Unit = { |
188 |
|
189 def compile_run(class_name: String) : Unit = { |
|
190 compile_to_file(class_name) |
203 compile_to_file(class_name) |
191 (s"java -jar jvm/jasmin-2.4/jasmin.jar ${class_name}.j").!! |
204 (s"java -jar jvm/jasmin-2.4/jasmin.jar ${class_name}.j").!! |
192 println("Time: " + time_needed(2, (s"java ${class_name}/${class_name}").!)) |
205 println("Time: " + time_needed(2, (s"java ${class_name}/${class_name}").!)) |
193 } |
206 } |
194 |
207 |
195 |
208 |
196 // some examples of .fun files |
209 // some examples of .fun files |
197 //compile_file("fact") |
210 //compile_to_file("fact") |
198 //compile_run("defs") |
211 //compile_and_run("fact") |
199 //compile_run("fact") |
212 //compile_and_run("defs") |
|
213 |
200 |
214 |
201 def main(args: Array[String]) = |
215 def main(args: Array[String]) = |
202 compile_run(args(0)) |
216 compile_and_run(args(0)) |
203 |
217 |
204 |
218 |
205 } |
219 } |