master
billsun 1 year ago
parent 8e8c90ec38
commit 4a2fbdaa22

@ -199,6 +199,8 @@ abstract class X86Compiler extends BugReporter with Codegen {
* TODO: Fill in transUn with the appropriate code. * TODO: Fill in transUn with the appropriate code.
*/ */
def transUn(op: String)(sp: Loc) = op match { def transUn(op: String)(sp: Loc) = op match {
case "-" => emitln(s"neg ${regs(sp)}")
case "+" => ()
case _ => BUG(s"Unary operator $op undefined") case _ => BUG(s"Unary operator $op undefined")
} }
@ -224,6 +226,7 @@ abstract class X86Compiler extends BugReporter with Codegen {
var nLabel = 0 var nLabel = 0
def freshLabel(pref: String) = { nLabel += 1; s"$pref$nLabel" } def freshLabel(pref: String) = { nLabel += 1; s"$pref$nLabel" }
/* /*
* Generate code that jumps to the label 'label' * Generate code that jumps to the label 'label'
* if the CPU flags are verifying the operator * if the CPU flags are verifying the operator
@ -260,18 +263,48 @@ abstract class X86Compiler extends BugReporter with Codegen {
def trans(exp: Exp, sp: Loc)(env: LocationEnv): Unit = exp match { def trans(exp: Exp, sp: Loc)(env: LocationEnv): Unit = exp match {
case Lit(x) => case Lit(x) =>
emitln(s"movq $$$x, ${regs(sp)}") emitln(s"movq $$$x, ${regs(sp)}")
case Unary(op, v) => () case Unary(op, v) =>
case Prim(op, lop, rop) => () trans(v, sp)(env)
case Let(x, a, b) => () transUn(op)(sp)
case Ref(x) => () case Prim(op, lop, rop) =>
case Cond(op, l, r) => () trans(lop, sp)(env)
case If(cond, tBranch, eBranch) => () trans(rop, sp + 1)(env)
case VarDec(x, rhs, body) => () transBin(op)(sp, sp + 1)
case VarAssign(x, rhs) => () case Let(x, a, b) =>
trans(a, sp)(env)
trans(b, sp + 1)(env.withVal(x, sp))
emitln(s"movq ${regs(sp + 1)}, ${regs(sp)}")
case Ref(x) =>
emitln(s"movq ${regs(env.apply(x))}, ${regs(sp)}")
case Cond(op, l, r) =>
trans(l, sp)(env)
trans(r, sp + 1)(env)
emitln(s"cmpq ${regs(sp + 1)}, ${regs(sp)}")
case If(cond, tBranch, eBranch) =>
trans(cond, sp)(env)
val lab = freshLabel("if")
transJumpIf(cond.op)(lab)
trans(eBranch, sp)(env)
emitln(s"jmp ${lab}_skip")
emitln(s"${lab}:", 0)
trans(tBranch, sp)(env)
emitln(s"${lab}_skip:", 0)
case VarDec(x, rhs, body) =>
trans(rhs, sp)(env)
trans(body, sp + 1)(env.withVal(x, sp))
emitln(s"movq ${regs(sp + 1)}, ${regs(sp)}")
case VarAssign(x, rhs) =>
trans(rhs, sp)(env)
emitln(s"movq ${regs(sp)}, ${regs(env.apply(x))}")
case While(cond, lBody, body) => case While(cond, lBody, body) =>
val lab = freshLabel("loop") val lab = freshLabel("loop")
emitln(s"jmp ${lab}_cond") emitln(s"jmp ${lab}_cond")
emitln(s"${lab}_body:", 0) emitln(s"${lab}_body:", 0)
() // TODO: continue ... trans(lBody, sp)(env)
emitln(s"${lab}_cond:", 0)
trans(cond, sp)(env)
transJumpIf(cond.op)(s"${lab}_body")
trans(body, sp)(env)
// TODO: continue ... Done
} }
} }

@ -190,6 +190,8 @@ class StackInterpreter extends Interpreter with BugReporter {
* TODO: Implement the appropriate code as defined in the handout. * TODO: Implement the appropriate code as defined in the handout.
*/ */
def evalUn(op: String)(sp: Loc) = op match { def evalUn(op: String)(sp: Loc) = op match {
case "+" => memory(sp)
case "-" => -memory(sp)
case _ => BUG(s"Unary operator $op undefined") case _ => BUG(s"Unary operator $op undefined")
} }
@ -218,6 +220,11 @@ class StackInterpreter extends Interpreter with BugReporter {
def evalCond(op: String)(sp: Loc, sp1: Loc) = { def evalCond(op: String)(sp: Loc, sp1: Loc) = {
flag = op match { flag = op match {
case "==" => memory(sp) == memory(sp1) case "==" => memory(sp) == memory(sp1)
case "!=" => memory(sp) != memory(sp1)
case ">=" => memory(sp) >= memory(sp1)
case "<=" => memory(sp) <= memory(sp1)
case ">" => memory(sp) > memory(sp1)
case "<" => memory(sp) < memory(sp1)
case _ => BUG(s"Binary operator $op undefined") case _ => BUG(s"Binary operator $op undefined")
} }
} }
@ -249,14 +256,32 @@ class StackInterpreter extends Interpreter with BugReporter {
def eval(exp: Exp, sp: Loc)(env: LocationEnv): Unit = exp match { def eval(exp: Exp, sp: Loc)(env: LocationEnv): Unit = exp match {
case Lit(x) => case Lit(x) =>
memory(sp) = x memory(sp) = x
case Unary(op, v) => ??? case Unary(op, v) =>
case Prim(op, lop, rop) => ??? eval(v, sp)(env)
case Let(x, a, b) => ??? evalUn(op)(sp)
case Ref(x) => ??? case Prim(op, lop, rop) =>
case Cond(op, l, r) => ??? eval(a, sp)(env)
case If(cond, tBranch, eBranch) => ??? eval(b, sp + 1)(env)
case VarDec(x, rhs, body) => ??? evalBin(sp, sp + 1)
case VarAssign(x, rhs) => ??? case Let(x, a, b) =>
eval(a, sp)(env)
eval(b, sp + 1)(env.withVal(x, sp))
memory(sp) = memory(sp + 1)
case Ref(x) =>
memory(sp) = memory(env.apply(x))
case Cond(op, l, r) =>
eval(l, sp)(env)
eval(r, sp + 1)(env)
evalCond(op)(sp, sp + 1)
case If(cond, tBranch, eBranch) =>
eval(cond, sp)(env)
eval(if(flag)tBranch else eBranch, sp)
case VarDec(x, rhs, body) =>
eval(rhs, sp)(env)
eval(body, sp + 1)(env.withVal(x, sp))
case VarAssign(x, rhs) =>
eval(rhs, sp)(env)
memory(env.apply(x)) = memory(sp)
case While(cond, lbody, body) => case While(cond, lbody, body) =>
eval(cond, sp)(env) eval(cond, sp)(env)
while (flag) { while (flag) {

@ -1,5 +1,7 @@
package project2 package project2
import java.awt.RenderingHints.Key
// Class used to carry position information within the source code // Class used to carry position information within the source code
case class Position(gapLine: Int, gapCol: Int, startLine: Int, startCol: Int, endLine: Int, endCol: Int) case class Position(gapLine: Int, gapCol: Int, startLine: Int, startCol: Int, endLine: Int, endCol: Int)
@ -426,7 +428,11 @@ class ArithParser(in: Scanner) extends Parser(in) {
def parseExpression: Exp = parseExpression(0) def parseExpression: Exp = parseExpression(0)
def parseExpression(min: Int): Exp = { def parseExpression(min: Int): Exp = {
var res = parseUAtom var res = parseUAtom
// TODO: complete // TODO: complete DONE?
if (in.hasNext(isOperator)) {
val (op, pos) = getOperator
Prim(op, res, parseUAtom).withPos(pos)
}
res res
} }
} }
@ -469,7 +475,7 @@ class LetParser(in: Scanner) extends ArithParser(in) {
case Ident(x) => case Ident(x) =>
val (_, pos) = getName val (_, pos) = getName
Ref(x).withPos(pos) Ref(x).withPos(pos)
// TODO: remove ??? and add the implementation for this case // TODO: remove ??? and add the implementation for this case DONE
case _ => abort(s"Illegal start of simple expression") case _ => abort(s"Illegal start of simple expression")
} }
@ -532,7 +538,20 @@ class BranchParser(in: Scanner) extends LetParser(in) {
} }
// TODO: remove ??? and complete the implementation. // TODO: remove ??? and complete the implementation.
override def parseSimpleExpression = ??? override def parseSimpleExpression: Exp = in.peek match {
case Keyword("if") =>
val pos = in.next().pos
accept('(')
val cond = parseCondition
accept(')')
val if_stmt = parseSimpleExpression
if (in.hasNext(_ == Keyword("else"))) {
val else_stmt = parseSimpleExpression
If(cond, if_stmt, else_stmt).withPos(pos)
}
else expected("missing else statement")
case _ => super.parseSimpleExpression
}
} }
/* /*
@ -562,12 +581,24 @@ class VariableParser(in: Scanner) extends BranchParser(in) {
// TODO: remove ??? and complete the implementation. // TODO: remove ??? and complete the implementation.
override def parseExpression = in.peek match { override def parseExpression = in.peek match {
case _ => ??? case Keyword("val") => super.parseExpression
case Keyword("var") =>
in.next()
val (name, pos) = getName
accept('=')
val rhs = parseSimpleExpression
accept(';')
val body = parseExpression
Var(name, rhs, body).withPos(pos)
case _ => parseSimpleExpression
} }
// TODO: remove ??? and complete the implementation. // TODO: remove ??? and complete the implementation.
override def parseSimpleExpression = (in.peek, in.peek1) match { override def parseSimpleExpression = (in.peek, in.peek1) match {
case _ => ??? case (Ident(x), Delim('=')) =>
val pos = in.pos
VarAssign(x, parseSimpleExpression).withPos(pos)
case _ => super.parseExpression
} }
} }
@ -597,5 +628,16 @@ class LoopParser(in: Scanner) extends VariableParser(in) {
import Tokens._ import Tokens._
// TODO: remove ??? and complete the implementation. // TODO: remove ??? and complete the implementation.
override def parseExpression = ??? override def parseExpression = in.peek match {
case Keyword("while") =>
val pos = in.next().pos
accept('(')
val cond = parseCondition
accept(')')
val simp = parseSimpleExpression
val body = parseExpression
While(cond, simp, body).withPos(pos)
case _ =>
super.parseExpression
}
} }

@ -124,33 +124,43 @@ class SemanticAnalyzer(parser: Parser) extends Reporter {
error("undefined primitive operator") error("undefined primitive operator")
analyze(lop) analyze(lop)
analyze(rop) analyze(rop)
case Let(x, a, b) => case Let(x, a, b) => // val x = a; b
// Done: check variable reuse // Done: check variable reuse
if(!(env.vars.contains(x) && env.vars[x])) if(!env.vars.contains(x))
error(s"cannot assign variable $x") error(s"cannot assign variable $x")
analyze(a)(env) analyze(a)(env)
analyze(b)(env.withVal(x)) analyze(b)(env.withVal(x))
case Ref(x) => case Ref(x) =>
if (!env.vars.contains(x)) if (!env.vars.contains(x))
error(s"symbol $x not found") error(s"symbol $x not defined")
()// Done // Done
case Cond(op, l, r) => case Cond(op, l, r) =>
// if (!isBOperator(op)) if (!isBOperator(op))
// error(s"$op is not a boolean operator") error(s"$op is not a boolean operator")
analyze(op) analyze(op)
analyze(l) analyze(l)
analyze(r) analyze(r)
() // Done // Done
case If(cond, tBranch, eBranch) => case If(cond, tBranch, eBranch) =>
analyze(cond)(env) analyze(cond)(env)
analyze(tBranch)(env) analyze(tBranch)(env)
analyze(eBranch)(env) analyze(eBranch)(env)
case VarDec(x, rhs, body) => case VarDec(x, rhs, body) => // var x = rhs; body
() // TODO if (env.vars.contains(x))
case VarAssign(x, rhs) => //diff w/ LET?? error(s"symbol $x already defined")
() // TODO analyze(rhs)(env)
analyze(body)(env)
// TODO
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"}")
analyze(rhs)
// TODO
case While(cond, lBody, body) => case While(cond, lBody, body) =>
() // TODO analyze(cond)
analyze(lBody)
analyze(body)
// TODO
case _ => abort(s"unknown AST node $exp") case _ => abort(s"unknown AST node $exp")
} }

Loading…
Cancel
Save