master
billsun 9 months ago
parent 8e8c90ec38
commit 4a2fbdaa22

@ -199,6 +199,8 @@ abstract class X86Compiler extends BugReporter with Codegen {
* TODO: Fill in transUn with the appropriate code.
*/
def transUn(op: String)(sp: Loc) = op match {
case "-" => emitln(s"neg ${regs(sp)}")
case "+" => ()
case _ => BUG(s"Unary operator $op undefined")
}
@ -223,6 +225,7 @@ abstract class X86Compiler extends BugReporter with Codegen {
var nLabel = 0
def freshLabel(pref: String) = { nLabel += 1; s"$pref$nLabel" }
/*
* Generate code that jumps to the label 'label'
@ -260,18 +263,48 @@ abstract class X86Compiler extends BugReporter with Codegen {
def trans(exp: Exp, sp: Loc)(env: LocationEnv): Unit = exp match {
case Lit(x) =>
emitln(s"movq $$$x, ${regs(sp)}")
case Unary(op, v) => ()
case Prim(op, lop, rop) => ()
case Let(x, a, b) => ()
case Ref(x) => ()
case Cond(op, l, r) => ()
case If(cond, tBranch, eBranch) => ()
case VarDec(x, rhs, body) => ()
case VarAssign(x, rhs) => ()
case Unary(op, v) =>
trans(v, sp)(env)
transUn(op)(sp)
case Prim(op, lop, rop) =>
trans(lop, sp)(env)
trans(rop, sp + 1)(env)
transBin(op)(sp, sp + 1)
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) =>
val lab = freshLabel("loop")
emitln(s"jmp ${lab}_cond")
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.
*/
def evalUn(op: String)(sp: Loc) = op match {
case "+" => memory(sp)
case "-" => -memory(sp)
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) = {
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 _ => 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 {
case Lit(x) =>
memory(sp) = x
case Unary(op, v) => ???
case Prim(op, lop, rop) => ???
case Let(x, a, b) => ???
case Ref(x) => ???
case Cond(op, l, r) => ???
case If(cond, tBranch, eBranch) => ???
case VarDec(x, rhs, body) => ???
case VarAssign(x, rhs) => ???
case Unary(op, v) =>
eval(v, sp)(env)
evalUn(op)(sp)
case Prim(op, lop, rop) =>
eval(a, sp)(env)
eval(b, sp + 1)(env)
evalBin(sp, sp + 1)
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) =>
eval(cond, sp)(env)
while (flag) {

@ -1,5 +1,7 @@
package project2
import java.awt.RenderingHints.Key
// 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)
@ -426,7 +428,11 @@ class ArithParser(in: Scanner) extends Parser(in) {
def parseExpression: Exp = parseExpression(0)
def parseExpression(min: Int): Exp = {
var res = parseUAtom
// TODO: complete
// TODO: complete DONE?
if (in.hasNext(isOperator)) {
val (op, pos) = getOperator
Prim(op, res, parseUAtom).withPos(pos)
}
res
}
}
@ -469,7 +475,7 @@ class LetParser(in: Scanner) extends ArithParser(in) {
case Ident(x) =>
val (_, pos) = getName
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")
}
@ -532,7 +538,20 @@ class BranchParser(in: Scanner) extends LetParser(in) {
}
// 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.
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.
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._
// 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")
analyze(lop)
analyze(rop)
case Let(x, a, b) =>
case Let(x, a, b) => // val x = a; b
// Done: check variable reuse
if(!(env.vars.contains(x) && env.vars[x]))
if(!env.vars.contains(x))
error(s"cannot assign variable $x")
analyze(a)(env)
analyze(b)(env.withVal(x))
case Ref(x) =>
if (!env.vars.contains(x))
error(s"symbol $x not found")
()// Done
error(s"symbol $x not defined")
// Done
case Cond(op, l, r) =>
// if (!isBOperator(op))
// error(s"$op is not a boolean operator")
if (!isBOperator(op))
error(s"$op is not a boolean operator")
analyze(op)
analyze(l)
analyze(r)
() // Done
// Done
case If(cond, tBranch, eBranch) =>
analyze(cond)(env)
analyze(tBranch)(env)
analyze(eBranch)(env)
case VarDec(x, rhs, body) =>
() // TODO
case VarAssign(x, rhs) => //diff w/ LET??
() // TODO
case VarDec(x, rhs, body) => // var x = rhs; body
if (env.vars.contains(x))
error(s"symbol $x already defined")
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) =>
() // TODO
analyze(cond)
analyze(lBody)
analyze(body)
// TODO
case _ => abort(s"unknown AST node $exp")
}

Loading…
Cancel
Save