completed
This commit is contained in:
@@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,6 +225,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'
|
||||||
@@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user