squash all the things
This commit is contained in:
parent
5f28f80c4e
commit
a1c15f0461
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
**/*.asm
|
||||
classes
|
28
.vscode/launch.json
vendored
28
.vscode/launch.json
vendored
@ -1,28 +0,0 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Main",
|
||||
"request": "launch",
|
||||
"mainClass": "main.Main",
|
||||
"projectName": "p5-compiler_25e45799"
|
||||
},
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Main",
|
||||
"request": "launch",
|
||||
"mainClass": "Main",
|
||||
"projectName": "p5-compiler_25e45799"
|
||||
},
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Current File",
|
||||
"request": "launch",
|
||||
"mainClass": "${file}"
|
||||
}
|
||||
]
|
||||
}
|
8
.vscode/settings.json
vendored
8
.vscode/settings.json
vendored
@ -1,8 +0,0 @@
|
||||
{
|
||||
"java.project.referencedLibraries": [
|
||||
"lib/**/*.jar",
|
||||
"antlr-4.9.1-complete.jar"
|
||||
],
|
||||
"rpc.enabled": false,
|
||||
"java.debug.settings.onBuildFailureProceed": true
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
# All program code is placed after the
|
||||
# .text assembler directive
|
||||
.text
|
||||
|
||||
# Declare main as a global function
|
||||
.globl main
|
||||
|
||||
j main
|
||||
|
||||
# All memory structures are placed after the
|
||||
# .data assembler directive
|
||||
.data
|
||||
|
@ -1,3 +1,5 @@
|
||||
void main() {
|
||||
void main()
|
||||
{
|
||||
println("Hello world");
|
||||
println(7 % 3, "hi");
|
||||
}
|
||||
|
@ -1,20 +1,22 @@
|
||||
int fib(int i) {
|
||||
if (i == 0) return 1;
|
||||
if (i == 1) return 1;
|
||||
return fib(i-1) + fib(i-2);
|
||||
if (i == 0)
|
||||
return 1;
|
||||
if (i == 1)
|
||||
return 1;
|
||||
return fib(i - 1) + fib(i - 2);
|
||||
}
|
||||
|
||||
void main() {
|
||||
println("This program prints the first 11 numbers of the Fibonacci sequence");
|
||||
println(fib(0)); // 1
|
||||
println(fib(1)); // 1
|
||||
println(fib(2)); // 2
|
||||
println(fib(3)); // 3
|
||||
println(fib(4)); // 5
|
||||
println(fib(5)); // 8
|
||||
println(fib(6)); // 13
|
||||
println(fib(7)); // 21
|
||||
println(fib(8)); // 34
|
||||
println(fib(9)); // 55
|
||||
println(fib(0)); // 1
|
||||
println(fib(1)); // 1
|
||||
println(fib(2)); // 2
|
||||
println(fib(3)); // 3
|
||||
println(fib(4)); // 5
|
||||
println(fib(5)); // 8
|
||||
println(fib(6)); // 13
|
||||
println(fib(7)); // 21
|
||||
println(fib(8)); // 34
|
||||
println(fib(9)); // 55
|
||||
println(fib(10)); // 89
|
||||
}
|
||||
|
11
data/test2.c
11
data/test2.c
@ -1,8 +1,9 @@
|
||||
void main() {
|
||||
void main()
|
||||
{
|
||||
println("This program prints 7 7 7 7 7 (separated by newlines)");
|
||||
println(7);
|
||||
println(3+4);
|
||||
println(14/2);
|
||||
println(7*1);
|
||||
println((7*2)/2);
|
||||
println(3 + 4);
|
||||
println(14 / 2);
|
||||
println(7 * 1);
|
||||
println((7 * 2) / 2);
|
||||
}
|
||||
|
12
data/test4.c
12
data/test4.c
@ -8,14 +8,14 @@ void main() {
|
||||
{
|
||||
int a;
|
||||
a = 5;
|
||||
println(a+b);
|
||||
println(a + b);
|
||||
{
|
||||
int b;
|
||||
b = 9;
|
||||
a = -2;
|
||||
println(a+b);
|
||||
int b;
|
||||
b = 9;
|
||||
a = -2;
|
||||
println(a + b);
|
||||
}
|
||||
b = 4;
|
||||
}
|
||||
println(a+b);
|
||||
println(a + b);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ void main() {
|
||||
if (a == 3) {
|
||||
println("4 correct");
|
||||
}
|
||||
if (a >= 4) {
|
||||
if (a != 4) {
|
||||
println("5 not correct");
|
||||
} else {
|
||||
println("5 correct");
|
||||
|
@ -1,304 +1,342 @@
|
||||
package submit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
import parser.CminusBaseVisitor;
|
||||
import parser.CminusParser;
|
||||
import submit.ast.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class ASTVisitor extends CminusBaseVisitor<Node> {
|
||||
private final Logger LOGGER;
|
||||
private SymbolTable symbolTable;
|
||||
private final Logger LOGGER;
|
||||
private SymbolTable symbolTable;
|
||||
|
||||
public ASTVisitor(Logger LOGGER) {
|
||||
this.LOGGER = LOGGER;
|
||||
public ASTVisitor(Logger LOGGER) { this.LOGGER = LOGGER; }
|
||||
|
||||
public SymbolTable getSymbolTable() { return symbolTable; }
|
||||
|
||||
private VarType getVarType(CminusParser.TypeSpecifierContext ctx) {
|
||||
final String t = ctx.getText();
|
||||
return (t.equals("int")) ? VarType.INT
|
||||
: (t.equals("bool")) ? VarType.BOOL
|
||||
: VarType.CHAR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitProgram(CminusParser.ProgramContext ctx) {
|
||||
symbolTable = new SymbolTable();
|
||||
List<Declaration> decls = new ArrayList<>();
|
||||
for (CminusParser.DeclarationContext d : ctx.declaration()) {
|
||||
decls.add((Declaration)visitDeclaration(d));
|
||||
}
|
||||
return new Program(decls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitVarDeclaration(CminusParser.VarDeclarationContext ctx) {
|
||||
VarType type = getVarType(ctx.typeSpecifier());
|
||||
List<String> ids = new ArrayList<>();
|
||||
List<Integer> arraySizes = new ArrayList<>();
|
||||
for (CminusParser.VarDeclIdContext v : ctx.varDeclId()) {
|
||||
String id = v.ID().getText();
|
||||
ids.add(id);
|
||||
// symbolTable.addSymbol(id, new SymbolInfo(id, type, false));
|
||||
if (v.NUMCONST() != null) {
|
||||
arraySizes.add(Integer.parseInt(v.NUMCONST().getText()));
|
||||
} else {
|
||||
int offset = symbolTable.addOffset(1);
|
||||
|
||||
SymbolInfo symbol = new SymbolInfo(id, type, false, offset);
|
||||
symbolTable.addSymbol(id, symbol);
|
||||
|
||||
arraySizes.add(-1);
|
||||
}
|
||||
}
|
||||
final boolean isStatic = false;
|
||||
return new VarDeclaration(type, ids, arraySizes, isStatic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitFunDeclaration(CminusParser.FunDeclarationContext ctx) {
|
||||
VarType returnType = null;
|
||||
if (ctx.typeSpecifier() != null) {
|
||||
returnType = getVarType(ctx.typeSpecifier());
|
||||
}
|
||||
String id = ctx.ID().getText();
|
||||
symbolTable.addSymbol(id, new SymbolInfo(id, returnType, true));
|
||||
|
||||
List<Param> params = new ArrayList<>();
|
||||
|
||||
SymbolTable newTable = symbolTable.createChild();
|
||||
symbolTable = newTable;
|
||||
|
||||
if (returnType != null) {
|
||||
symbolTable.addSymbol("return",
|
||||
new SymbolInfo("return", returnType, false,
|
||||
symbolTable.addOffset(1)));
|
||||
}
|
||||
|
||||
public SymbolTable getSymbolTable() {
|
||||
return symbolTable;
|
||||
for (CminusParser.ParamContext p : ctx.param()) {
|
||||
params.add((Param)visitParam(p));
|
||||
}
|
||||
|
||||
private VarType getVarType(CminusParser.TypeSpecifierContext ctx) {
|
||||
final String t = ctx.getText();
|
||||
return (t.equals("int")) ? VarType.INT : (t.equals("bool")) ? VarType.BOOL : VarType.CHAR;
|
||||
}
|
||||
CompoundStatement statement =
|
||||
(CompoundStatement)visitStatement(ctx.statement());
|
||||
|
||||
@Override
|
||||
public Node visitProgram(CminusParser.ProgramContext ctx) {
|
||||
symbolTable = new SymbolTable();
|
||||
List<Declaration> decls = new ArrayList<>();
|
||||
for (CminusParser.DeclarationContext d : ctx.declaration()) {
|
||||
decls.add((Declaration) visitDeclaration(d));
|
||||
}
|
||||
return new Program(decls);
|
||||
}
|
||||
statement.getSymbolTable().addOtherTableBefore(newTable);
|
||||
symbolTable = newTable.getParent();
|
||||
|
||||
@Override
|
||||
public Node visitVarDeclaration(CminusParser.VarDeclarationContext ctx) {
|
||||
VarType type = getVarType(ctx.typeSpecifier());
|
||||
List<String> ids = new ArrayList<>();
|
||||
List<Integer> arraySizes = new ArrayList<>();
|
||||
for (CminusParser.VarDeclIdContext v : ctx.varDeclId()) {
|
||||
String id = v.ID().getText();
|
||||
ids.add(id);
|
||||
symbolTable.addSymbol(id, new SymbolInfo(id, type, false));
|
||||
if (v.NUMCONST() != null) {
|
||||
arraySizes.add(Integer.parseInt(v.NUMCONST().getText()));
|
||||
} else {
|
||||
arraySizes.add(-1);
|
||||
}
|
||||
}
|
||||
final boolean isStatic = false;
|
||||
return new VarDeclaration(type, ids, arraySizes, isStatic);
|
||||
}
|
||||
return new FunDeclaration(returnType, id, params, statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitFunDeclaration(CminusParser.FunDeclarationContext ctx) {
|
||||
VarType returnType = null;
|
||||
if (ctx.typeSpecifier() != null) {
|
||||
returnType = getVarType(ctx.typeSpecifier());
|
||||
}
|
||||
String id = ctx.ID().getText();
|
||||
List<Param> params = new ArrayList<>();
|
||||
for (CminusParser.ParamContext p : ctx.param()) {
|
||||
params.add((Param) visitParam(p));
|
||||
}
|
||||
Statement statement = (Statement) visitStatement(ctx.statement());
|
||||
symbolTable.addSymbol(id, new SymbolInfo(id, returnType, true));
|
||||
return new FunDeclaration(returnType, id, params, statement);
|
||||
}
|
||||
@Override
|
||||
public Node visitParam(CminusParser.ParamContext ctx) {
|
||||
VarType type = getVarType(ctx.typeSpecifier());
|
||||
String id = ctx.paramId().ID().getText();
|
||||
symbolTable.addSymbol(
|
||||
id, new SymbolInfo(id, type, false, symbolTable.addOffset(1)));
|
||||
|
||||
@Override
|
||||
public Node visitParam(CminusParser.ParamContext ctx) {
|
||||
VarType type = getVarType(ctx.typeSpecifier());
|
||||
String id = ctx.paramId().ID().getText();
|
||||
symbolTable.addSymbol(id, new SymbolInfo(id, type, false));
|
||||
return new Param(type, id, ctx.paramId().children.size() > 1);
|
||||
}
|
||||
return new Param(type, id, ctx.paramId().children.size() > 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitCompoundStmt(CminusParser.CompoundStmtContext ctx) {
|
||||
symbolTable = symbolTable.createChild();
|
||||
List<Statement> statements = new ArrayList<>();
|
||||
for (CminusParser.VarDeclarationContext d : ctx.varDeclaration()) {
|
||||
statements.add((VarDeclaration) visitVarDeclaration(d));
|
||||
}
|
||||
for (CminusParser.StatementContext d : ctx.statement()) {
|
||||
statements.add((Statement) visitStatement(d));
|
||||
}
|
||||
symbolTable = symbolTable.getParent();
|
||||
return new CompoundStatement(statements);
|
||||
}
|
||||
@Override
|
||||
public Node visitCompoundStmt(CminusParser.CompoundStmtContext ctx) {
|
||||
SymbolTable child = symbolTable.createChild();
|
||||
symbolTable = child;
|
||||
|
||||
@Override
|
||||
public Node visitExpressionStmt(CminusParser.ExpressionStmtContext ctx) {
|
||||
if (ctx.expression() == null) {
|
||||
return Statement.empty();
|
||||
}
|
||||
return new ExpressionStatement((Expression) visitExpression(ctx.expression()));
|
||||
List<Statement> statements = new ArrayList<>();
|
||||
for (CminusParser.VarDeclarationContext d : ctx.varDeclaration()) {
|
||||
statements.add((VarDeclaration)visitVarDeclaration(d));
|
||||
}
|
||||
for (CminusParser.StatementContext d : ctx.statement()) {
|
||||
statements.add((Statement)visitStatement(d));
|
||||
}
|
||||
symbolTable = child.getParent();
|
||||
|
||||
@Override
|
||||
public Node visitIfStmt(CminusParser.IfStmtContext ctx) {
|
||||
Expression expression = (Expression) visitSimpleExpression(ctx.simpleExpression());
|
||||
Statement trueStatement = (Statement) visitStatement(ctx.statement(0));
|
||||
Statement falseStatement = null;
|
||||
if (ctx.statement().size() > 1) {
|
||||
falseStatement = (Statement) visitStatement(ctx.statement(1));
|
||||
}
|
||||
return new If(expression, trueStatement, falseStatement);
|
||||
}
|
||||
return new CompoundStatement(statements, child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitWhileStmt(CminusParser.WhileStmtContext ctx) {
|
||||
Expression expression = (Expression) visitSimpleExpression(ctx.simpleExpression());
|
||||
Statement statement = (Statement) visitStatement(ctx.statement());
|
||||
return new While(expression, statement);
|
||||
@Override
|
||||
public Node visitExpressionStmt(CminusParser.ExpressionStmtContext ctx) {
|
||||
if (ctx.expression() == null) {
|
||||
return Statement.empty();
|
||||
}
|
||||
return new ExpressionStatement(
|
||||
(Expression)visitExpression(ctx.expression()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitReturnStmt(CminusParser.ReturnStmtContext ctx) {
|
||||
if (ctx.expression() != null) {
|
||||
return new Return((Expression) visitExpression(ctx.expression()));
|
||||
}
|
||||
return new Return(null);
|
||||
@Override
|
||||
public Node visitIfStmt(CminusParser.IfStmtContext ctx) {
|
||||
Expression expression =
|
||||
(Expression)visitSimpleExpression(ctx.simpleExpression());
|
||||
Statement trueStatement = (Statement)visitStatement(ctx.statement(0));
|
||||
Statement falseStatement = null;
|
||||
if (ctx.statement().size() > 1) {
|
||||
falseStatement = (Statement)visitStatement(ctx.statement(1));
|
||||
}
|
||||
return new If(expression, trueStatement, falseStatement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitBreakStmt(CminusParser.BreakStmtContext ctx) {
|
||||
return new Break();
|
||||
}
|
||||
@Override
|
||||
public Node visitWhileStmt(CminusParser.WhileStmtContext ctx) {
|
||||
Expression expression =
|
||||
(Expression)visitSimpleExpression(ctx.simpleExpression());
|
||||
Statement statement = (Statement)visitStatement(ctx.statement());
|
||||
return new While(expression, statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitExpression(CminusParser.ExpressionContext ctx) {
|
||||
final Node ret;
|
||||
CminusParser.MutableContext mutable = ctx.mutable();
|
||||
CminusParser.ExpressionContext expression = ctx.expression();
|
||||
if (mutable != null) {
|
||||
// Assignment
|
||||
ParseTree operator = ctx.getChild(1);
|
||||
Mutable lhs = (Mutable) visitMutable(mutable);// new Mutable(mutable.ID().getText(), (Expression)
|
||||
// visitExpression(mutable.expression()));
|
||||
Expression rhs = null;
|
||||
if (expression != null) {
|
||||
rhs = (Expression) visitExpression(expression);
|
||||
}
|
||||
ret = new Assignment(lhs, operator.getText(), rhs);
|
||||
} else {
|
||||
ret = visitSimpleExpression(ctx.simpleExpression());
|
||||
}
|
||||
return ret;
|
||||
@Override
|
||||
public Node visitReturnStmt(CminusParser.ReturnStmtContext ctx) {
|
||||
if (ctx.expression() != null) {
|
||||
return new Return((Expression)visitExpression(ctx.expression()));
|
||||
}
|
||||
return new Return(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitOrExpression(CminusParser.OrExpressionContext ctx) {
|
||||
List<Node> ands = new ArrayList<>();
|
||||
for (CminusParser.AndExpressionContext and : ctx.andExpression()) {
|
||||
ands.add(visitAndExpression(and));
|
||||
}
|
||||
if (ands.size() == 1) {
|
||||
return ands.get(0);
|
||||
}
|
||||
BinaryOperator op = new BinaryOperator((Expression) ands.get(0), "||", (Expression) ands.get(1));
|
||||
for (int i = 2; i < ands.size(); ++i) {
|
||||
op = new BinaryOperator(op, "||", (Expression) ands.get(i));
|
||||
}
|
||||
return op;
|
||||
}
|
||||
@Override
|
||||
public Node visitBreakStmt(CminusParser.BreakStmtContext ctx) {
|
||||
return new Break();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitAndExpression(CminusParser.AndExpressionContext ctx) {
|
||||
List<Node> uns = new ArrayList<>();
|
||||
for (CminusParser.UnaryRelExpressionContext un : ctx.unaryRelExpression()) {
|
||||
uns.add(visitUnaryRelExpression(un));
|
||||
}
|
||||
if (uns.size() == 1) {
|
||||
return uns.get(0);
|
||||
}
|
||||
BinaryOperator op = new BinaryOperator((Expression) uns.get(0), "&&", (Expression) uns.get(1));
|
||||
for (int i = 2; i < uns.size(); ++i) {
|
||||
op = new BinaryOperator(op, "&&", (Expression) uns.get(i));
|
||||
}
|
||||
return op;
|
||||
@Override
|
||||
public Node visitExpression(CminusParser.ExpressionContext ctx) {
|
||||
final Node ret;
|
||||
CminusParser.MutableContext mutable = ctx.mutable();
|
||||
CminusParser.ExpressionContext expression = ctx.expression();
|
||||
if (mutable != null) {
|
||||
// Assignment
|
||||
ParseTree operator = ctx.getChild(1);
|
||||
Mutable lhs = (Mutable)visitMutable(
|
||||
mutable); // new Mutable(mutable.ID().getText(), (Expression)
|
||||
// visitExpression(mutable.expression()));
|
||||
Expression rhs = null;
|
||||
if (expression != null) {
|
||||
rhs = (Expression)visitExpression(expression);
|
||||
}
|
||||
ret = new Assignment(lhs, operator.getText(), rhs);
|
||||
} else {
|
||||
ret = visitSimpleExpression(ctx.simpleExpression());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitUnaryRelExpression(CminusParser.UnaryRelExpressionContext ctx) {
|
||||
Expression e = (Expression) visitRelExpression(ctx.relExpression());
|
||||
for (TerminalNode n : ctx.BANG()) {
|
||||
e = new UnaryOperator("!", e);
|
||||
}
|
||||
return e;
|
||||
@Override
|
||||
public Node visitOrExpression(CminusParser.OrExpressionContext ctx) {
|
||||
List<Node> ands = new ArrayList<>();
|
||||
for (CminusParser.AndExpressionContext and : ctx.andExpression()) {
|
||||
ands.add(visitAndExpression(and));
|
||||
}
|
||||
if (ands.size() == 1) {
|
||||
return ands.get(0);
|
||||
}
|
||||
BinaryOperator op = new BinaryOperator((Expression)ands.get(0), "||",
|
||||
(Expression)ands.get(1));
|
||||
for (int i = 2; i < ands.size(); ++i) {
|
||||
op = new BinaryOperator(op, "||", (Expression)ands.get(i));
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitRelExpression(CminusParser.RelExpressionContext ctx) {
|
||||
List<Node> uns = new ArrayList<>();
|
||||
for (CminusParser.SumExpressionContext un : ctx.sumExpression()) {
|
||||
uns.add(visitSumExpression(un));
|
||||
}
|
||||
if (uns.size() == 1) {
|
||||
return uns.get(0);
|
||||
}
|
||||
BinaryOperator op = new BinaryOperator((Expression) uns.get(0), ctx.relop(0).getText(),
|
||||
(Expression) uns.get(1));
|
||||
for (int i = 2; i < uns.size(); ++i) {
|
||||
op = new BinaryOperator(op, ctx.relop(i - 1).getText(), (Expression) uns.get(i));
|
||||
}
|
||||
return op;
|
||||
@Override
|
||||
public Node visitAndExpression(CminusParser.AndExpressionContext ctx) {
|
||||
List<Node> uns = new ArrayList<>();
|
||||
for (CminusParser.UnaryRelExpressionContext un : ctx.unaryRelExpression()) {
|
||||
uns.add(visitUnaryRelExpression(un));
|
||||
}
|
||||
if (uns.size() == 1) {
|
||||
return uns.get(0);
|
||||
}
|
||||
BinaryOperator op = new BinaryOperator((Expression)uns.get(0), "&&",
|
||||
(Expression)uns.get(1));
|
||||
for (int i = 2; i < uns.size(); ++i) {
|
||||
op = new BinaryOperator(op, "&&", (Expression)uns.get(i));
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitSumExpression(CminusParser.SumExpressionContext ctx) {
|
||||
List<Node> es = new ArrayList<>();
|
||||
for (CminusParser.TermExpressionContext e : ctx.termExpression()) {
|
||||
es.add(visitTermExpression(e));
|
||||
}
|
||||
if (es.size() == 1) {
|
||||
return es.get(0);
|
||||
}
|
||||
BinaryOperator op = new BinaryOperator((Expression) es.get(0), ctx.sumop(0).getText(), (Expression) es.get(1));
|
||||
for (int i = 2; i < es.size(); ++i) {
|
||||
op = new BinaryOperator(op, ctx.sumop(i - 1).getText(), (Expression) es.get(i));
|
||||
}
|
||||
return op;
|
||||
@Override
|
||||
public Node
|
||||
visitUnaryRelExpression(CminusParser.UnaryRelExpressionContext ctx) {
|
||||
Expression e = (Expression)visitRelExpression(ctx.relExpression());
|
||||
for (TerminalNode n : ctx.BANG()) {
|
||||
e = new UnaryOperator("!", e);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitTermExpression(CminusParser.TermExpressionContext ctx) {
|
||||
List<Node> es = new ArrayList<>();
|
||||
for (CminusParser.UnaryExpressionContext e : ctx.unaryExpression()) {
|
||||
es.add(visitUnaryExpression(e));
|
||||
}
|
||||
if (es.size() == 1) {
|
||||
return es.get(0);
|
||||
}
|
||||
BinaryOperator op = new BinaryOperator((Expression) es.get(0), ctx.mulop(0).getText(), (Expression) es.get(1));
|
||||
for (int i = 2; i < es.size(); ++i) {
|
||||
op = new BinaryOperator(op, ctx.mulop(i - 1).getText(), (Expression) es.get(i));
|
||||
}
|
||||
return op;
|
||||
@Override
|
||||
public Node visitRelExpression(CminusParser.RelExpressionContext ctx) {
|
||||
List<Node> uns = new ArrayList<>();
|
||||
for (CminusParser.SumExpressionContext un : ctx.sumExpression()) {
|
||||
uns.add(visitSumExpression(un));
|
||||
}
|
||||
if (uns.size() == 1) {
|
||||
return uns.get(0);
|
||||
}
|
||||
BinaryOperator op = new BinaryOperator(
|
||||
(Expression)uns.get(0), ctx.relop(0).getText(), (Expression)uns.get(1));
|
||||
for (int i = 2; i < uns.size(); ++i) {
|
||||
op = new BinaryOperator(op, ctx.relop(i - 1).getText(),
|
||||
(Expression)uns.get(i));
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitUnaryExpression(CminusParser.UnaryExpressionContext ctx) {
|
||||
Node ret = visitFactor(ctx.factor());
|
||||
for (int i = ctx.unaryop().size() - 1; i >= 0; i--) {
|
||||
ret = new UnaryOperator(ctx.unaryop(i).getText(), (Expression) ret);
|
||||
}
|
||||
return ret;
|
||||
@Override
|
||||
public Node visitSumExpression(CminusParser.SumExpressionContext ctx) {
|
||||
List<Node> es = new ArrayList<>();
|
||||
for (CminusParser.TermExpressionContext e : ctx.termExpression()) {
|
||||
es.add(visitTermExpression(e));
|
||||
}
|
||||
if (es.size() == 1) {
|
||||
return es.get(0);
|
||||
}
|
||||
BinaryOperator op = new BinaryOperator(
|
||||
(Expression)es.get(0), ctx.sumop(0).getText(), (Expression)es.get(1));
|
||||
for (int i = 2; i < es.size(); ++i) {
|
||||
op = new BinaryOperator(op, ctx.sumop(i - 1).getText(),
|
||||
(Expression)es.get(i));
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitMutable(CminusParser.MutableContext ctx) {
|
||||
Expression e = null;
|
||||
if (ctx.expression() != null) {
|
||||
e = (Expression) visitExpression(ctx.expression());
|
||||
}
|
||||
String id = ctx.ID().getText();
|
||||
if (symbolTable.find(id) == null) {
|
||||
LOGGER.warning("Undefined symbol on line " + ctx.getStart().getLine() + ": " + id);
|
||||
}
|
||||
return new Mutable(id, e);
|
||||
@Override
|
||||
public Node visitTermExpression(CminusParser.TermExpressionContext ctx) {
|
||||
List<Node> es = new ArrayList<>();
|
||||
for (CminusParser.UnaryExpressionContext e : ctx.unaryExpression()) {
|
||||
es.add(visitUnaryExpression(e));
|
||||
}
|
||||
if (es.size() == 1) {
|
||||
return es.get(0);
|
||||
}
|
||||
BinaryOperator op = new BinaryOperator(
|
||||
(Expression)es.get(0), ctx.mulop(0).getText(), (Expression)es.get(1));
|
||||
for (int i = 2; i < es.size(); ++i) {
|
||||
op = new BinaryOperator(op, ctx.mulop(i - 1).getText(),
|
||||
(Expression)es.get(i));
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitImmutable(CminusParser.ImmutableContext ctx) {
|
||||
if (ctx.expression() != null) {
|
||||
return new ParenExpression((Expression) visitExpression(ctx.expression()));
|
||||
}
|
||||
return visitChildren(ctx);
|
||||
@Override
|
||||
public Node visitUnaryExpression(CminusParser.UnaryExpressionContext ctx) {
|
||||
Node ret = visitFactor(ctx.factor());
|
||||
for (int i = ctx.unaryop().size() - 1; i >= 0; i--) {
|
||||
ret = new UnaryOperator(ctx.unaryop(i).getText(), (Expression)ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitCall(CminusParser.CallContext ctx) {
|
||||
final String id = ctx.ID().getText();
|
||||
final List<Expression> args = new ArrayList<>();
|
||||
for (CminusParser.ExpressionContext e : ctx.expression()) {
|
||||
args.add((Expression) visitExpression(e));
|
||||
}
|
||||
if (symbolTable.find(id) == null) {
|
||||
LOGGER.warning("Undefined symbol on line " + ctx.getStart().getLine() + ": " + id);
|
||||
}
|
||||
return new Call(id, args);
|
||||
@Override
|
||||
public Node visitMutable(CminusParser.MutableContext ctx) {
|
||||
Expression e = null;
|
||||
if (ctx.expression() != null) {
|
||||
e = (Expression)visitExpression(ctx.expression());
|
||||
}
|
||||
String id = ctx.ID().getText();
|
||||
if (symbolTable.find(id) == null) {
|
||||
LOGGER.warning("Undefined symbol on line " + ctx.getStart().getLine() +
|
||||
": " + id);
|
||||
}
|
||||
return new Mutable(id, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitConstant(CminusParser.ConstantContext ctx) {
|
||||
final Node node;
|
||||
if (ctx.NUMCONST() != null) {
|
||||
node = new NumConstant(Integer.parseInt(ctx.NUMCONST().getText()));
|
||||
} else if (ctx.CHARCONST() != null) {
|
||||
node = new CharConstant(ctx.CHARCONST().getText().charAt(0));
|
||||
} else if (ctx.STRINGCONST() != null) {
|
||||
node = new StringConstant(ctx.STRINGCONST().getText());
|
||||
} else {
|
||||
node = new BoolConstant(ctx.getText().equals("true"));
|
||||
}
|
||||
return node;
|
||||
@Override
|
||||
public Node visitImmutable(CminusParser.ImmutableContext ctx) {
|
||||
if (ctx.expression() != null) {
|
||||
return new ParenExpression((Expression)visitExpression(ctx.expression()));
|
||||
}
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitCall(CminusParser.CallContext ctx) {
|
||||
final String id = ctx.ID().getText();
|
||||
final List<Expression> args = new ArrayList<>();
|
||||
for (CminusParser.ExpressionContext e : ctx.expression()) {
|
||||
args.add((Expression)visitExpression(e));
|
||||
}
|
||||
if (symbolTable.find(id) == null) {
|
||||
LOGGER.warning("Undefined symbol on line " + ctx.getStart().getLine() +
|
||||
": " + id);
|
||||
}
|
||||
return new Call(id, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitConstant(CminusParser.ConstantContext ctx) {
|
||||
final Node node;
|
||||
if (ctx.NUMCONST() != null) {
|
||||
node = new NumConstant(Integer.parseInt(ctx.NUMCONST().getText()));
|
||||
} else if (ctx.CHARCONST() != null) {
|
||||
node = new CharConstant(ctx.CHARCONST().getText().charAt(0));
|
||||
} else if (ctx.STRINGCONST() != null) {
|
||||
node = new StringConstant(ctx.STRINGCONST().getText());
|
||||
} else {
|
||||
node = new BoolConstant(ctx.getText().equals("true"));
|
||||
}
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
@ -57,5 +57,4 @@ public class MIPSResult {
|
||||
public VarType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,112 +15,139 @@ import java.util.Set;
|
||||
*/
|
||||
public final class RegisterAllocator {
|
||||
|
||||
// True if t is used
|
||||
private final boolean[] t = new boolean[10];
|
||||
private final boolean[] s = new boolean[8];
|
||||
private final Set<String> used = new HashSet<>();
|
||||
// True if t is used
|
||||
private final boolean[] t = new boolean[10];
|
||||
private final boolean[] s = new boolean[8];
|
||||
private final Set<String> used = new HashSet<>();
|
||||
|
||||
public RegisterAllocator() {
|
||||
clearAll();
|
||||
public RegisterAllocator() { clearAll(); }
|
||||
|
||||
public String getRegisterOrLoadIntoRegister(MIPSResult result,
|
||||
StringBuilder code) {
|
||||
if (result.getRegister() != null) {
|
||||
return result.getRegister();
|
||||
}
|
||||
String reg = result.getAddress();
|
||||
return this.loadIntoRegister(result, code, reg);
|
||||
}
|
||||
|
||||
public String getT() {
|
||||
for (int i = 0; i < t.length; ++i) {
|
||||
if (!t[i]) {
|
||||
t[i] = true;
|
||||
String str = "$t" + i;
|
||||
used.add(str);
|
||||
return str;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
public String loadIntoRegister(MIPSResult result, StringBuilder code,
|
||||
String register) {
|
||||
return loadIntoRegisterWithOffset(result, code, register, 0);
|
||||
}
|
||||
|
||||
public String loadIntoRegisterWithOffset(MIPSResult result,
|
||||
StringBuilder code, String register,
|
||||
int offset) {
|
||||
code.append(
|
||||
String.format("lw %s %d(%s)\n", register, offset, result.getAddress()));
|
||||
|
||||
return register;
|
||||
}
|
||||
|
||||
public String getT() {
|
||||
for (int i = 0; i < t.length; ++i) {
|
||||
if (!t[i]) {
|
||||
t[i] = true;
|
||||
String str = "$t" + i;
|
||||
used.add(str);
|
||||
return str;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// public String getS() {
|
||||
// for (int i = 0; i < s.length; ++i) {
|
||||
// if (!s[i]) {
|
||||
// s[i] = true;
|
||||
// String str = "$s" + i;
|
||||
// used.add(str);
|
||||
// return str;
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
// public String getS() {
|
||||
// for (int i = 0; i < s.length; ++i) {
|
||||
// if (!s[i]) {
|
||||
// s[i] = true;
|
||||
// String str = "$s" + i;
|
||||
// used.add(str);
|
||||
// return str;
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// Returns the number of bytes used to save the registers
|
||||
public int saveRestore(StringBuilder code, int baseOffset, boolean s_or_t, boolean save) {
|
||||
boolean[] r = s;
|
||||
String prefix = "$s";
|
||||
if (!s_or_t) {
|
||||
r = t;
|
||||
prefix = "$t";
|
||||
}
|
||||
String instruction = "sw";
|
||||
if (!save) {
|
||||
instruction = "lw";
|
||||
}
|
||||
int offset = 0;
|
||||
for (int i = 0; i < r.length; ++i) {
|
||||
if (r[i]) {
|
||||
offset -= 4;
|
||||
String str = prefix + i;
|
||||
code.append(instruction).append(" ").append(str).append(" ").append(offset-baseOffset).append("($sp)\n");
|
||||
}
|
||||
}
|
||||
return -offset;
|
||||
// Returns the number of bytes used to save the registers
|
||||
public int saveRestore(StringBuilder code, int baseOffset, boolean s_or_t,
|
||||
boolean save) {
|
||||
boolean[] r = s;
|
||||
String prefix = "$s";
|
||||
if (!s_or_t) {
|
||||
r = t;
|
||||
prefix = "$t";
|
||||
}
|
||||
|
||||
// public int saveS(StringBuilder code, int baseOffset) {
|
||||
// return saveRestore(code, baseOffset, true, true);
|
||||
// }
|
||||
|
||||
public int saveT(StringBuilder code, int baseOffset) {
|
||||
return saveRestore(code, baseOffset, false, true);
|
||||
String instruction = "sw";
|
||||
if (!save) {
|
||||
instruction = "lw";
|
||||
}
|
||||
|
||||
// public int restoreS(StringBuilder code, int baseOffset) {
|
||||
// return saveRestore(code, baseOffset, true, false);
|
||||
// }
|
||||
|
||||
public int restoreT(StringBuilder code, int baseOffset) {
|
||||
return saveRestore(code, baseOffset, false, false);
|
||||
int offset = 0;
|
||||
for (int i = 0; i < r.length; ++i) {
|
||||
if (r[i]) {
|
||||
offset -= 4;
|
||||
String str = prefix + i;
|
||||
code.append(instruction)
|
||||
.append(" ")
|
||||
.append(str)
|
||||
.append(" ")
|
||||
.append(offset - baseOffset)
|
||||
.append("($sp)\n");
|
||||
}
|
||||
}
|
||||
return -offset;
|
||||
}
|
||||
|
||||
public List<String> getUsed() {
|
||||
return new ArrayList<>(used);
|
||||
}
|
||||
// public int saveS(StringBuilder code, int baseOffset) {
|
||||
// return saveRestore(code, baseOffset, true, true);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Any time you call this method you should seriously consider adding a
|
||||
* corresponding clear() call.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getAny() {
|
||||
// String availS = getS();
|
||||
// if (availS != null) {
|
||||
// return availS;
|
||||
// }
|
||||
String t = getT();
|
||||
if (t == null) {
|
||||
throw new RuntimeException("Out of registers");
|
||||
}
|
||||
return t;
|
||||
}
|
||||
public int saveT(StringBuilder code, int baseOffset) {
|
||||
return saveRestore(code, baseOffset, false, true);
|
||||
}
|
||||
|
||||
public void clear(String reg) {
|
||||
if (reg.charAt(1) == 's') {
|
||||
s[Integer.parseInt(reg.substring(2))] = false;
|
||||
} else if (reg.charAt(1) == 't') {
|
||||
t[Integer.parseInt(reg.substring(2))] = false;
|
||||
} else {
|
||||
throw new RuntimeException("Unexpected register in clear");
|
||||
}
|
||||
}
|
||||
// public int restoreS(StringBuilder code, int baseOffset) {
|
||||
// return saveRestore(code, baseOffset, true, false);
|
||||
// }
|
||||
|
||||
public void clearAll() {
|
||||
Arrays.fill(t, false);
|
||||
Arrays.fill(s, false);
|
||||
public int restoreT(StringBuilder code, int baseOffset) {
|
||||
return saveRestore(code, baseOffset, false, false);
|
||||
}
|
||||
|
||||
public List<String> getUsed() { return new ArrayList<>(used); }
|
||||
|
||||
/**
|
||||
* Any time you call this method you should seriously consider adding a
|
||||
* corresponding clear() call.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getAny() {
|
||||
// String availS = getS();
|
||||
// if (availS != null) {
|
||||
// return availS;
|
||||
// }
|
||||
String t = getT();
|
||||
if (t == null) {
|
||||
throw new RuntimeException("Out of registers");
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
public void clear(String reg) {
|
||||
if (reg == null)
|
||||
return;
|
||||
if (reg.charAt(1) == 's') {
|
||||
s[Integer.parseInt(reg.substring(2))] = false;
|
||||
} else if (reg.charAt(1) == 't') {
|
||||
t[Integer.parseInt(reg.substring(2))] = false;
|
||||
} else {
|
||||
throw new RuntimeException("Unexpected register in clear");
|
||||
}
|
||||
}
|
||||
|
||||
public void clearAll() {
|
||||
Arrays.fill(t, false);
|
||||
Arrays.fill(s, false);
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ public class SymbolInfo {
|
||||
// In the case of a function, type is the return type
|
||||
private final VarType type;
|
||||
private final boolean function;
|
||||
private int offset;
|
||||
|
||||
public SymbolInfo(String id, VarType type, boolean function) {
|
||||
this.id = id;
|
||||
@ -23,9 +24,20 @@ public class SymbolInfo {
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
public SymbolInfo(String id, VarType type, boolean function, int offset) {
|
||||
this(id, type, function);
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<" + id + ", " + type + '>';
|
||||
}
|
||||
|
||||
public VarType getType() { return type; }
|
||||
|
||||
public boolean isFunction() { return function; }
|
||||
|
||||
public int getOffset() { return offset; }
|
||||
public void setOffset(int offset) { this.offset = offset; }
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package submit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import submit.ast.VarType;
|
||||
|
||||
/*
|
||||
* Code formatter project
|
||||
@ -17,14 +18,71 @@ public class SymbolTable {
|
||||
private SymbolTable parent;
|
||||
private final List<SymbolTable> children;
|
||||
|
||||
private int offset;
|
||||
|
||||
public static int LABEL_IDENTIFIER = 0;
|
||||
|
||||
public static String nextId() {
|
||||
return Integer.toString(SymbolTable.LABEL_IDENTIFIER++);
|
||||
}
|
||||
|
||||
public SymbolTable() {
|
||||
offset = 0;
|
||||
table = new HashMap<>();
|
||||
parent = null;
|
||||
children = new ArrayList<>();
|
||||
|
||||
this.addGlobalSymbols();
|
||||
}
|
||||
|
||||
public void addSymbol(String id, SymbolInfo symbol) {
|
||||
table.put(id, symbol);
|
||||
public List<String> symbolNames() { return new ArrayList<>(table.keySet()); }
|
||||
|
||||
public void addGlobalSymbols() {
|
||||
SymbolInfo println = new SymbolInfo("println", null, true);
|
||||
this.addSymbol("println", println);
|
||||
}
|
||||
|
||||
public void addSymbol(String id, SymbolInfo symbol) { table.put(id, symbol); }
|
||||
|
||||
public int addOffset(int n) {
|
||||
offset -= 4 * n;
|
||||
return offset;
|
||||
}
|
||||
|
||||
public int getOffset() { return this.offset; }
|
||||
|
||||
// Add symbols in before and reorder offsets such that symbols in before have
|
||||
// a "higher" offset
|
||||
public void addOtherTableBefore(SymbolTable before) {
|
||||
offset = 0;
|
||||
List<String> thisSymbols = symbolNames();
|
||||
|
||||
for (String id : before.symbolNames()) {
|
||||
SymbolInfo symbol = before.find(id);
|
||||
if (!symbol.isFunction()) {
|
||||
addOffset(1);
|
||||
symbol.setOffset(offset);
|
||||
}
|
||||
addSymbol(id, symbol);
|
||||
}
|
||||
|
||||
for (String id : thisSymbols) {
|
||||
SymbolInfo symbol = table.get(id);
|
||||
if (!symbol.isFunction()) {
|
||||
addOffset(1);
|
||||
table.get(id).setOffset(offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int offsetOf(String id) {
|
||||
if (table.containsKey(id)) {
|
||||
return table.get(id).getOffset();
|
||||
}
|
||||
if (parent != null) {
|
||||
return -parent.getOffset() + parent.offsetOf(id);
|
||||
}
|
||||
return 0; // This shouldn't happen :D
|
||||
}
|
||||
|
||||
/**
|
||||
@ -56,8 +114,5 @@ public class SymbolTable {
|
||||
return child;
|
||||
}
|
||||
|
||||
public SymbolTable getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public SymbolTable getParent() { return parent; }
|
||||
}
|
||||
|
@ -10,6 +10,6 @@ public class AbstractNode implements Node {
|
||||
|
||||
public MIPSResult toMIPS(StringBuilder code, StringBuilder data, SymbolTable symbolTable,
|
||||
RegisterAllocator regAllocator) {
|
||||
return null;
|
||||
return MIPSResult.createVoidResult();
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,10 @@
|
||||
*/
|
||||
package submit.ast;
|
||||
|
||||
import submit.MIPSResult;
|
||||
import submit.RegisterAllocator;
|
||||
import submit.SymbolTable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author edwajohn
|
||||
@ -30,4 +34,25 @@ public class Assignment extends AbstractNode implements Expression {
|
||||
}
|
||||
}
|
||||
|
||||
public MIPSResult toMIPS(StringBuilder code, StringBuilder data,
|
||||
SymbolTable symbolTable,
|
||||
RegisterAllocator regAllocator) {
|
||||
MIPSResult mut = mutable.toMIPS(code, data, symbolTable, regAllocator);
|
||||
MIPSResult result = rhs.toMIPS(code, data, symbolTable, regAllocator);
|
||||
|
||||
String registerWithAddressOfMutable = mut.getAddress();
|
||||
|
||||
if (result.getRegister() != null) {
|
||||
code.append(String.format("sw %s 0(%s)\n", result.getRegister(),
|
||||
registerWithAddressOfMutable));
|
||||
regAllocator.clear(result.getRegister());
|
||||
} else if (result.getAddress() != null) {
|
||||
regAllocator.loadIntoRegister(result, code, result.getAddress());
|
||||
regAllocator.clear(result.getAddress());
|
||||
}
|
||||
|
||||
regAllocator.clear(registerWithAddressOfMutable);
|
||||
|
||||
return MIPSResult.createVoidResult();
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,10 @@
|
||||
*/
|
||||
package submit.ast;
|
||||
|
||||
import submit.MIPSResult;
|
||||
import submit.RegisterAllocator;
|
||||
import submit.SymbolTable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author edwajohn
|
||||
@ -13,7 +17,8 @@ public class BinaryOperator extends AbstractNode implements Expression {
|
||||
private final Expression lhs, rhs;
|
||||
private final BinaryOperatorType type;
|
||||
|
||||
public BinaryOperator(Expression lhs, BinaryOperatorType type, Expression rhs) {
|
||||
public BinaryOperator(Expression lhs, BinaryOperatorType type,
|
||||
Expression rhs) {
|
||||
this.lhs = lhs;
|
||||
this.type = type;
|
||||
this.rhs = rhs;
|
||||
@ -32,4 +37,86 @@ public class BinaryOperator extends AbstractNode implements Expression {
|
||||
rhs.toCminus(builder, prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MIPSResult toMIPS(StringBuilder code, StringBuilder data,
|
||||
SymbolTable symbolTable,
|
||||
RegisterAllocator regAllocator) {
|
||||
MIPSResult left = lhs.toMIPS(code, data, symbolTable, regAllocator);
|
||||
String leftRegister =
|
||||
regAllocator.getRegisterOrLoadIntoRegister(left, code);
|
||||
|
||||
MIPSResult right = rhs.toMIPS(code, data, symbolTable, regAllocator);
|
||||
String rightRegister =
|
||||
regAllocator.getRegisterOrLoadIntoRegister(right, code);
|
||||
String resultRegister = regAllocator.getAny();
|
||||
|
||||
switch (type) {
|
||||
case PLUS:
|
||||
code.append(String.format("add %s %s %s\n", resultRegister, leftRegister,
|
||||
rightRegister));
|
||||
break;
|
||||
case MINUS:
|
||||
code.append(String.format("sub %s %s %s\n", resultRegister, leftRegister,
|
||||
rightRegister));
|
||||
break;
|
||||
case TIMES:
|
||||
code.append(String.format("mult %s %s\n", leftRegister, rightRegister))
|
||||
.append(String.format("mflo %s\n", resultRegister));
|
||||
break;
|
||||
case DIVIDE:
|
||||
code.append(String.format("div %s %s\n", leftRegister, rightRegister))
|
||||
.append(String.format("mflo %s\n", resultRegister));
|
||||
break;
|
||||
case MOD:
|
||||
code.append(String.format("div %s %s\n", leftRegister, rightRegister))
|
||||
.append(String.format("mfhi %s\n", resultRegister));
|
||||
break;
|
||||
case LT:
|
||||