done
This commit is contained in:
@@ -190,8 +190,8 @@ class StackInterpreter extends Interpreter with BugReporter {
|
||||
* TODO: Implement the appropriate code as defined in the handout.
|
||||
*/
|
||||
def evalUn(op: String)(sp: Loc) = op match {
|
||||
case "+" => memory(sp)
|
||||
case "-" => -memory(sp)
|
||||
case "+" => ()
|
||||
case "-" => memory(sp) = -memory(sp)
|
||||
case _ => BUG(s"Unary operator $op undefined")
|
||||
}
|
||||
|
||||
@@ -279,6 +279,7 @@ class StackInterpreter extends Interpreter with BugReporter {
|
||||
case VarDec(x, rhs, body) =>
|
||||
eval(rhs, sp)(env)
|
||||
eval(body, sp + 1)(env.withVal(x, sp))
|
||||
memory(sp) = memory(sp + 1)
|
||||
case VarAssign(x, rhs) =>
|
||||
eval(rhs, sp)(env)
|
||||
memory(env.apply(x)) = memory(sp)
|
||||
|
||||
@@ -434,7 +434,7 @@ class ArithParser(in: Scanner) extends Parser(in) {
|
||||
isInfixOp(min)(in.peek)
|
||||
) {
|
||||
val (op, pos) = getOperator
|
||||
res = Prim(op, res, parseExpression(prec(op))).withPos(pos)
|
||||
res = Prim(op, res, parseExpression(prec(op) + assoc(op))).withPos(pos)
|
||||
}
|
||||
res
|
||||
}
|
||||
@@ -541,9 +541,7 @@ class BranchParser(in: Scanner) extends LetParser(in) {
|
||||
}
|
||||
|
||||
// TODO: remove ??? and complete the implementation.
|
||||
override def parseSimpleExpression: Exp = {
|
||||
print(in.peek)
|
||||
in.peek match {
|
||||
override def parseSimpleExpression: Exp = in.peek match {
|
||||
case Keyword("if") =>
|
||||
val pos = in.next().pos
|
||||
accept('(')
|
||||
@@ -557,7 +555,6 @@ class BranchParser(in: Scanner) extends LetParser(in) {
|
||||
}
|
||||
else expected("missing else statement")
|
||||
case _ => super.parseSimpleExpression
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -120,19 +120,19 @@ class SemanticAnalyzer(parser: Parser) extends Reporter {
|
||||
error("undefined unary operator", exp.pos)
|
||||
analyze(v)(env)
|
||||
case Prim(op, lop, rop) => // Done
|
||||
if(!(isOperator(op) || isBOperator(op)))
|
||||
if(!isOperator(op))
|
||||
error("undefined primitive operator", exp.pos)
|
||||
analyze(lop)(env)
|
||||
analyze(rop)(env)
|
||||
case Let(x, a, b) => // val x = a; b
|
||||
// Done: check variable reuse
|
||||
if(env.vars.contains(x))
|
||||
error(s"cannot assign variable $x", exp.pos)
|
||||
warn(s"redifinition of ${if(env.vars(x))"variable"else"value"} $x", exp.pos)
|
||||
analyze(a)(env)
|
||||
analyze(b)(env.withVal(x))
|
||||
case Ref(x) =>
|
||||
if (!env.vars.contains(x))
|
||||
error(s"symbol $x not defined", exp.pos)
|
||||
error(s"symbol $x is undefined", exp.pos)
|
||||
// Done
|
||||
case Cond(op, l, r) =>
|
||||
if (!isBOperator(op))
|
||||
@@ -146,20 +146,20 @@ class SemanticAnalyzer(parser: Parser) extends Reporter {
|
||||
analyze(eBranch)(env)
|
||||
case VarDec(x, rhs, body) => // var x = rhs; body
|
||||
if (env.vars.contains(x))
|
||||
error(s"symbol $x already defined", exp.pos)
|
||||
warn(s"redifinition of ${if(env.vars(x))"variable"else"value"} $x", exp.pos)
|
||||
analyze(rhs)(env)
|
||||
analyze(body)(env.withVar(x))
|
||||
// TODO
|
||||
// Done
|
||||
case VarAssign(x, rhs) => // x = rhs
|
||||
if (!(env.vars.contains(x) && env.vars(x)))
|
||||
error(s"cannot assign $x: ${if(env.vars.contains(x))"immutable"else"undefined"}", exp.pos)
|
||||
analyze(rhs)(env)
|
||||
// TODO
|
||||
// Done
|
||||
case While(cond, lBody, body) =>
|
||||
analyze(cond)(env)
|
||||
analyze(lBody)(env)
|
||||
analyze(body)(env)
|
||||
// TODO
|
||||
// Done
|
||||
case _ => abort(s"unknown AST node $exp")
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,40 @@ class CompilerTest extends TimedSuite {
|
||||
|
||||
test("arithm") {
|
||||
testCompiler(Lit(-21), -21)
|
||||
testCompiler(Unary("-", Lit(23)), -23)
|
||||
testCompiler(Unary("+", Lit(22)), 22)
|
||||
testCompiler(Prim("-", Lit(10), Lit(2)), 8)
|
||||
testCompiler(Prim("+", Prim("+", Prim("-", Lit(1), Lit(2)), Lit(3)), Lit(4)), 6)
|
||||
testCompiler(Prim("*", Lit(2), Lit(-3)), -6)
|
||||
testCompiler(Prim("+", Prim("+", Prim("-", Unary("-", Lit(5)), Prim("/", Lit(8), Lit(3))),Lit(2)), Lit(3)), -2)
|
||||
}
|
||||
|
||||
test("let&ref") {
|
||||
testCompiler(Let("x", Lit(2), Ref("x")), 2)
|
||||
testCompiler(Let("x", Prim("*", Lit(2), Unary("-", Lit(5))), Ref("x")), -10)
|
||||
}
|
||||
|
||||
test("if&cond") {
|
||||
testCompiler(Let("x",Lit(5), Let("y", Lit(5), If(Cond("==", Ref("x"), Ref("y")),Lit(5), Lit(10)))), 5)
|
||||
testCompiler(If(Cond(">", Lit(3), Lit(1)), Lit(10), Lit(5)), 10)
|
||||
testCompiler(If(Cond("==", Lit(1), Lit(2)), Lit(1), Lit(2)), 2)
|
||||
testCompiler(VarDec("x",Lit(5),If(Cond("==",Ref("x"),Lit(5)),Lit(7),Lit(6))), 7)
|
||||
testCompiler(VarDec("x",Lit(5),If(Cond("!=",Ref("x"),Lit(5)),Lit(7),Lit(6))), 6)
|
||||
}
|
||||
|
||||
test("varassign") {
|
||||
testCompiler(VarDec("x", Lit(5), VarAssign("x", Prim("-", Ref("x"), Lit(15)))), -10)
|
||||
testCompiler(VarDec("x",Lit(5),VarAssign("x",Lit(3))), 3)
|
||||
}
|
||||
|
||||
test("vardec") {
|
||||
testCompiler(VarDec("x",Lit(5),Ref("x")), 5)
|
||||
testCompiler(VarDec("x",Unary("-",Lit(5)),Ref("x")), -5)
|
||||
}
|
||||
|
||||
test("while") {
|
||||
testCompiler(While(Cond("!=",Lit(5),Lit(5)),Lit(3),Lit(5)), 5)
|
||||
testCompiler(VarDec("x",Lit(2),VarDec("y",Lit(0),While(Cond("<",Ref("y"),Lit(3)),Let("dummy",VarAssign("x",Prim("*",Ref("x"),Ref("x"))),VarAssign("y",Prim("+",Ref("y"),Lit(1)))),Ref("x")))), 256)
|
||||
testCompiler(VarDec("x",Lit(0),While(Cond("!=",Ref("x"),Lit(5)),VarAssign("x",Prim("+",Ref("x"),Lit(1))),Ref("x"))), 5)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,41 @@ class InterpretTest extends TimedSuite {
|
||||
|
||||
test("arithm") {
|
||||
testInterpreter(Lit(-21), -21)
|
||||
testInterpreter(Unary("-", Lit(23)), -23)
|
||||
testInterpreter(Unary("+", Lit(22)), 22)
|
||||
testInterpreter(Prim("-", Lit(10), Lit(2)), 8)
|
||||
testInterpreter(Prim("+", Prim("+", Prim("-", Lit(1), Lit(2)), Lit(3)), Lit(4)), 6)
|
||||
testInterpreter(Prim("*", Lit(2), Lit(-3)), -6)
|
||||
testInterpreter(Prim("+", Prim("+", Prim("-", Unary("-", Lit(5)), Prim("/", Lit(8), Lit(3))),Lit(2)), Lit(3)), -2)
|
||||
}
|
||||
|
||||
test("let&ref") {
|
||||
testInterpreter(Let("x", Lit(2), Ref("x")), 2)
|
||||
testInterpreter(Let("x", Prim("*", Lit(2), Unary("-", Lit(5))), Ref("x")), -10)
|
||||
}
|
||||
|
||||
test("if&cond") {
|
||||
testInterpreter(Let("x",Lit(5), Let("y", Lit(5), If(Cond("==", Ref("x"), Ref("y")),Lit(5), Lit(10)))), 5)
|
||||
testInterpreter(If(Cond(">", Lit(3), Lit(1)), Lit(10), Lit(5)), 10)
|
||||
testInterpreter(If(Cond("==", Lit(1), Lit(2)), Lit(1), Lit(2)), 2)
|
||||
testInterpreter(VarDec("x",Lit(5),If(Cond("==",Ref("x"),Lit(5)),Lit(7),Lit(6))), 7)
|
||||
testInterpreter(VarDec("x",Lit(5),If(Cond("!=",Ref("x"),Lit(5)),Lit(7),Lit(6))), 6)
|
||||
}
|
||||
|
||||
test("varassign") {
|
||||
testInterpreter(VarDec("x", Lit(5), VarAssign("x", Prim("-", Ref("x"), Lit(15)))), -10)
|
||||
testInterpreter(VarDec("x",Lit(5),VarAssign("x",Lit(3))), 3)
|
||||
}
|
||||
|
||||
test("vardec") {
|
||||
testInterpreter(VarDec("x",Lit(5),Ref("x")), 5)
|
||||
testInterpreter(VarDec("x",Unary("-",Lit(5)),Ref("x")), -5)
|
||||
}
|
||||
|
||||
test("while") {
|
||||
testInterpreter(While(Cond("!=",Lit(5),Lit(5)),Lit(3),Lit(5)), 5)
|
||||
testInterpreter(VarDec("x",Lit(2),VarDec("y",Lit(0),While(Cond("<",Ref("y"),Lit(3)),Let("dummy",VarAssign("x",Prim("*",Ref("x"),Ref("x"))),VarAssign("y",Prim("+",Ref("y"),Lit(1)))),Ref("x")))), 256)
|
||||
testInterpreter(VarDec("x",Lit(0),While(Cond("!=",Ref("x"),Lit(5)),VarAssign("x",Prim("+",Ref("x"),Lit(1))),Ref("x"))), 5)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,13 +42,67 @@ class ParserTest extends TimedSuite {
|
||||
assert(ast == res, "Invalid result")
|
||||
}
|
||||
|
||||
/*test("SingleDigit") {
|
||||
test("SingleDigit") {
|
||||
testGenericPrecedence("1", Lit(1))
|
||||
}
|
||||
|
||||
test("GenericPrecedence") {
|
||||
testGenericPrecedence("2-4*3", Prim("-", Lit(2), Prim("*", Lit(4), Lit(3))))
|
||||
}*/
|
||||
testGenericPrecedence("1+ -2", Prim("+",Lit(1),Unary("-",Lit(2))))
|
||||
testGenericPrecedence("1+2*3/4", Prim("+",Lit(1),Prim("/",Prim("*",Lit(2),Lit(3)),Lit(4))))
|
||||
testGenericPrecedence("1+(-1)", Prim("+",Lit(1), Unary("-",Lit(1))))
|
||||
testGenericPrecedence("(1-2*3/4-5)*6",
|
||||
Prim("*",Prim("-",Prim("-",Lit(1),Prim("/",Prim("*",Lit(2),Lit(3)),Lit(4))),Lit(5)),Lit(6)))
|
||||
}
|
||||
|
||||
test("testLetParser") {
|
||||
testLetParser("val x=1;x", Let("x", Lit(1), Ref("x")))
|
||||
testLetParser("val x = 1; val y = 2; x - y",
|
||||
Let("x", Lit(1), Let("y", Lit(2), Prim("-", Ref("x"), Ref("y")))))
|
||||
testLetParser("val x = 1; val y = 2; x*3 - y",
|
||||
Let("x", Lit(1), Let("y", Lit(2), Prim("-", Prim("*", Ref("x"), Lit(3)), Ref("y")))))
|
||||
}
|
||||
|
||||
test("testBranchParser") {
|
||||
testBranchParser("if(1==2)3 else 4", If(Cond("==",Lit(1), Lit(2)), Lit(3), Lit(4)))
|
||||
testBranchParser("val x = 5; if (x == 5) x else 5",
|
||||
Let("x",Lit(5),If(Cond("==",Ref("x"),Lit(5)),Ref("x"),Lit(5))))
|
||||
testBranchParser("if(3>5){1}else{2}", If(Cond(">", Lit(3), Lit(5)), Lit(1), Lit(2)))
|
||||
testBranchParser("if(3>5){if(9<0){1}else{2}}else{4}",
|
||||
If(Cond(">", Lit(3), Lit(5)), If(Cond("<", Lit(9), Lit(0)), Lit(1), Lit(2)), Lit(4)))
|
||||
assertThrows[Exception] {
|
||||
testBranchParser("if(1>2)1", Lit(0))
|
||||
}
|
||||
}
|
||||
|
||||
test("testVariableParser"){
|
||||
testVariableParser("var x = 1; var y = 2; x = y = 3",
|
||||
VarDec("x", Lit(1), VarDec("y", Lit(2), VarAssign("x", VarAssign("y", Lit(3))))))
|
||||
assertThrows[Exception] {
|
||||
testVariableParser("var x = 1 1", Lit(0))
|
||||
}
|
||||
}
|
||||
|
||||
//Loop Parser
|
||||
test("testLoopParser"){
|
||||
testLoopParser("var x = 1; var y = 1; while(x <= 0) {val t = x + y; if(t > y) x = t else y = (-x - 1)};x",
|
||||
VarDec("x", Lit(1),
|
||||
VarDec("y", Lit(1),
|
||||
While(Cond("<=", Ref("x"), Lit(0)),
|
||||
Let("t", Prim("+", Ref("x"), Ref("y")),
|
||||
If(Cond(">", Ref("t"), Ref("y")),
|
||||
VarAssign("x", Ref("t")),
|
||||
VarAssign("y",Prim("-", Unary("-", Ref("x")), Lit(1))))),
|
||||
Ref("x")))))
|
||||
assertThrows[Exception] {
|
||||
testLoopParser("while(1){};", Lit(0))
|
||||
}
|
||||
assertThrows[Exception] {
|
||||
testLoopParser("while(1 == 1) { val x = 2; }", Lit(0))
|
||||
}
|
||||
testLoopParser("while(1 == 1) { val x = 2; 2 }; 1", While(Cond("==", Lit(1), Lit(1)), Let("x", Lit(2), Lit(2)), Lit(1)))
|
||||
}
|
||||
|
||||
test("1") {
|
||||
testGenericPrecedence(s"${(1 << 31) - 1}", Lit({
|
||||
(1 << 31) - 1
|
||||
@@ -86,12 +140,12 @@ class ParserTest extends TimedSuite {
|
||||
Prim("*", Prim("*", Prim("*", Lit(2), Lit(9)), Lit(5)), Lit(3)),
|
||||
Prim("/", Prim("/", Lit(18), Lit(6)), Lit(3))))
|
||||
}
|
||||
/*test("rt") {
|
||||
test("rt") {
|
||||
testGenericPrecedence("18/6/3",Prim("/",Prim("/",Lit(18),Lit(6)),Lit(3)))
|
||||
}
|
||||
test("go"){
|
||||
testGenericPrecedence("2*9*5*3",Prim("*",Prim("*",Prim("*",Lit(2),Lit(9)),Lit(5)), Lit(3)))
|
||||
}*/
|
||||
}
|
||||
test("8") {
|
||||
0
|
||||
}
|
||||
|
||||
@@ -31,11 +31,23 @@ class SemanticAnalyzerTest extends TimedSuite {
|
||||
test("32"){
|
||||
testSemanticAnalyzer(VarDec("x",Lit(1),Let("x",Lit(5),Lit(4))), 1 ,0)
|
||||
}
|
||||
/*test("3"){
|
||||
test("3"){
|
||||
testSemanticAnalyzer(Prim("%",Lit(1),Lit(5)),0,1)
|
||||
}
|
||||
test("3134"){
|
||||
testSemanticAnalyzer(Prim("%",Lit(1),Lit(5)),0,1)
|
||||
}*/
|
||||
}
|
||||
|
||||
test("more tests"){
|
||||
testSemanticAnalyzer(Let("x", Lit(1), VarAssign("x", Lit(2))), 0, 1) // assign to imm
|
||||
testSemanticAnalyzer(Let("x", Lit(1), Let("x", Lit(2), Ref("x"))), 1, 0) // redef imm -> imm
|
||||
testSemanticAnalyzer(VarDec("x", Lit(1), VarDec("x", Lit(2), Ref("x"))), 1, 0) // redef mut -> mut
|
||||
testSemanticAnalyzer(Let("x", Lit(1), VarDec("x", Lit(2), VarAssign("x", Lit(3)))), 1, 0) // redef imm -> mut
|
||||
testSemanticAnalyzer(Let("x", Lit(1), Let("x", Lit(2), VarAssign("x", Lit(3)))), 1, 1) // warn + err
|
||||
testSemanticAnalyzer(Prim("+", Unary("/", Lit(1)), Lit(2)), 0, 1) // invalid unary op
|
||||
testSemanticAnalyzer(Prim("++", Lit(1), Lit(2)), 0, 1) // invalid op
|
||||
testSemanticAnalyzer(If(Cond("<>", Lit(1), Lit(2)), Lit(3), Lit(4)), 0, 1) // invalid boolean op
|
||||
testSemanticAnalyzer(If(Cond("==", Ref("x"), Lit(1)), Lit(2), Lit(3)), 0, 1) // undefined sym
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@ import org.scalatest.time.{Span, Millis}
|
||||
|
||||
class TimedSuite extends FunSuite with TimeLimitedTests {
|
||||
|
||||
val timeLimit = Span(1000, Millis)
|
||||
val timeLimit = Span(10000, Millis)
|
||||
override val defaultTestSignaler: Signaler = ThreadSignaler
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user