master
Chiyoda Sumika 9 months ago
parent 9562517e28
commit 30280816c4

@ -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
}

Loading…
Cancel
Save