Initial commit
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
package project3
|
||||
|
||||
import org.scalatest._
|
||||
import java.io.{ByteArrayOutputStream, PrintWriter}
|
||||
|
||||
// Define the stream method
|
||||
trait TestOutput {
|
||||
import Language._
|
||||
|
||||
val out = new ByteArrayOutputStream
|
||||
val pOut = new PrintWriter(out, true)
|
||||
def stream = pOut
|
||||
def emitCode(ast: Exp): Unit
|
||||
|
||||
def code(ast: Exp) = {
|
||||
emitCode(ast)
|
||||
out.toString.stripLineEnd
|
||||
}
|
||||
}
|
||||
|
||||
class CompilerTest extends TimedSuite {
|
||||
import Language._
|
||||
|
||||
def runner(src: String) = new ASMRunner(src)
|
||||
|
||||
def testCompiler(ast: Exp, res: Int) = {
|
||||
val interpreter = new X86Compiler with TestOutput
|
||||
|
||||
val code = interpreter.code(ast)
|
||||
val asm = runner(code)
|
||||
|
||||
assert(asm.assemble == 0, "Code generated couldn't be assembled")
|
||||
assert(asm.run == res, "Invalid result")
|
||||
}
|
||||
|
||||
test("arithm") {
|
||||
testCompiler(LetRec(Nil, Lit(-21)), -21)
|
||||
testCompiler(LetRec(Nil, Prim("-", List(Lit(10), Lit(2)))), 8)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package project3
|
||||
|
||||
import org.scalatest._
|
||||
|
||||
class InterpretTest extends TimedSuite {
|
||||
import Language._
|
||||
import StackVal._
|
||||
|
||||
def testInterpreter(ast: Exp, res: Any) = {
|
||||
val interpreter = new StackInterpreter
|
||||
|
||||
assert(res == interpreter.run(ast), "Interpreter does not return the correct value")
|
||||
}
|
||||
|
||||
test("arithm") {
|
||||
testInterpreter(Lit(-21), Cst(-21))
|
||||
testInterpreter(Prim("-", List(Lit(10), Lit(2))), Cst(8))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package project3
|
||||
|
||||
import java.io._
|
||||
import org.scalatest._
|
||||
|
||||
class ParserTest extends TimedSuite {
|
||||
import Language._
|
||||
|
||||
def scanner(src: String) = new Scanner(new BaseReader(src, '\u0000'))
|
||||
|
||||
def testBaseParser(op: String, res: Exp) = {
|
||||
val gen = new BaseParser(scanner(op))
|
||||
val ast = gen.parseCode
|
||||
|
||||
assert(ast == LetRec(Nil, res), "Invalid result")
|
||||
}
|
||||
|
||||
test("SingleDigit") {
|
||||
testBaseParser("1", Lit(1))
|
||||
}
|
||||
|
||||
test("GenericPrecedence") {
|
||||
testBaseParser("2-4*3", Prim("-", List(Lit(2), Prim("*", List(Lit(4), Lit(3))))))
|
||||
}
|
||||
|
||||
test("ParseType") {
|
||||
testBaseParser("val x: Int = 1; 2", Let("x", IntType, Lit(1), Lit(2)))
|
||||
}
|
||||
|
||||
test("ParseOptionalType") {
|
||||
testBaseParser("val x = 1; 2", Let("x", UnknownType, Lit(1), Lit(2)))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package project3
|
||||
|
||||
import org.scalatest._
|
||||
|
||||
class SemanticAnalyzerTest extends TimedSuite {
|
||||
import Language._
|
||||
|
||||
def astTypeEquals(ast: Exp, tsa: Exp): Boolean = ast == tsa && ast.tp == tsa.tp && { (ast, tsa) match {
|
||||
case (Prim(_, args), Prim(_, sgra))=>
|
||||
(args zip sgra) forall { case (arg, gra) => astTypeEquals(arg, gra) }
|
||||
case (Let(_, _, a, b), Let(_, _, c, d)) =>
|
||||
astTypeEquals(a, c) && astTypeEquals(b, d)
|
||||
case (If(cond, tBranch, eBranch), If(cond1, tBranch1, eBranch1)) =>
|
||||
astTypeEquals(cond, cond1) && astTypeEquals(tBranch, tBranch1) && astTypeEquals(eBranch, eBranch1)
|
||||
case (VarDec(_, _, a, b), VarDec(_, _, c, d)) =>
|
||||
astTypeEquals(a, c) && astTypeEquals(b, d)
|
||||
case (VarAssign(_, rhs), VarAssign(_, shr)) =>
|
||||
astTypeEquals(rhs, shr)
|
||||
case (While(cond, tBranch, eBranch), While(cond1, tBranch1, eBranch1)) =>
|
||||
astTypeEquals(cond, cond1) && astTypeEquals(tBranch, tBranch1) && astTypeEquals(eBranch, eBranch1)
|
||||
case (FunDef(_, _, _, fbody), FunDef(_, _, _, fbody1)) =>
|
||||
astTypeEquals(fbody, fbody1)
|
||||
case (LetRec(funs, body), LetRec(funs1, body1)) =>
|
||||
((funs zip funs1) forall { case (arg, gra) => astTypeEquals(arg, gra) }) && astTypeEquals(body, body1)
|
||||
case (App(fun, args), App(fun1, args1)) =>
|
||||
((args zip args1) forall { case (arg, gra) => astTypeEquals(arg, gra) }) && astTypeEquals(fun, fun1)
|
||||
case (ArrayDec(size, _), ArrayDec(size1, _)) =>
|
||||
astTypeEquals(size, size1)
|
||||
case _ => true
|
||||
}}
|
||||
|
||||
def testSemanticAnalyzer(ast: Exp, tsa: Exp, nWarning: Int, nError: Int) = {
|
||||
val fakeParser = new Parser(null) {
|
||||
override def error(msg: String, pos: Position) = {}
|
||||
override def warn(msg: String, pos: Position) = {}
|
||||
}
|
||||
|
||||
val analyzer = new SemanticAnalyzer(fakeParser)
|
||||
|
||||
val (tast, w, e) = analyzer.run(ast)
|
||||
assert(w == nWarning, "Incorrect number of Warnings")
|
||||
assert(e == nError, "Incorrect number of Errors")
|
||||
assert(astTypeEquals(tast, tsa), "AST does not have correct type")
|
||||
}
|
||||
|
||||
test("NoErrorNoWarning") {
|
||||
testSemanticAnalyzer(Lit(1), Lit(1).withType(IntType), 0, 0)
|
||||
testSemanticAnalyzer(Prim("+", List(Lit(1), Lit(2))), Prim("+", List(Lit(1).withType(IntType), Lit(2).withType(IntType))).withType(IntType), 0, 0)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package project3
|
||||
import org.scalatest._
|
||||
import org.scalatest.concurrent.{TimeLimitedTests, Signaler, ThreadSignaler}
|
||||
import org.scalatest.time.{Span, Millis}
|
||||
|
||||
class TimedSuite extends FunSuite with TimeLimitedTests {
|
||||
|
||||
val timeLimit = Span(1000, Millis)
|
||||
override val defaultTestSignaler: Signaler = ThreadSignaler
|
||||
}
|
||||
Reference in New Issue
Block a user