Initial commit

This commit is contained in:
2023-09-17 08:07:19 -04:00
commit acf15f81fe
29 changed files with 2406 additions and 0 deletions
@@ -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
}