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("Hello world");
|
||||||
|
println(7 % 3, "hi");
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
int fib(int i) {
|
int fib(int i) {
|
||||||
if (i == 0) return 1;
|
if (i == 0)
|
||||||
if (i == 1) return 1;
|
return 1;
|
||||||
return fib(i-1) + fib(i-2);
|
if (i == 1)
|
||||||
|
return 1;
|
||||||
|
return fib(i - 1) + fib(i - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
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("This program prints 7 7 7 7 7 (separated by newlines)");
|
||||||
println(7);
|
println(7);
|
||||||
println(3+4);
|
println(3 + 4);
|
||||||
println(14/2);
|
println(14 / 2);
|
||||||
println(7*1);
|
println(7 * 1);
|
||||||
println((7*2)/2);
|
println((7 * 2) / 2);
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,14 @@ void main() {
|
|||||||
{
|
{
|
||||||
int a;
|
int a;
|
||||||
a = 5;
|
a = 5;
|
||||||
println(a+b);
|
println(a + b);
|
||||||
{
|
{
|
||||||
int b;
|
int b;
|
||||||
b = 9;
|
b = 9;
|
||||||
a = -2;
|
a = -2;
|
||||||
println(a+b);
|
println(a + b);
|
||||||
}
|
}
|
||||||
b = 4;
|
b = 4;
|
||||||
}
|
}
|
||||||
println(a+b);
|
println(a + b);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ void main() {
|
|||||||
if (a == 3) {
|
if (a == 3) {
|
||||||
println("4 correct");
|
println("4 correct");
|
||||||
}
|
}
|
||||||
if (a >= 4) {
|
if (a != 4) {
|
||||||
println("5 not correct");
|
println("5 not correct");
|
||||||
} else {
|
} else {
|
||||||
println("5 correct");
|
println("5 correct");
|
||||||
|
@ -1,30 +1,27 @@
|
|||||||
package submit;
|
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.ParseTree;
|
||||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||||
import parser.CminusBaseVisitor;
|
import parser.CminusBaseVisitor;
|
||||||
import parser.CminusParser;
|
import parser.CminusParser;
|
||||||
import submit.ast.*;
|
import submit.ast.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
public class ASTVisitor extends CminusBaseVisitor<Node> {
|
public class ASTVisitor extends CminusBaseVisitor<Node> {
|
||||||
private final Logger LOGGER;
|
private final Logger LOGGER;
|
||||||
private SymbolTable symbolTable;
|
private SymbolTable symbolTable;
|
||||||
|
|
||||||
public ASTVisitor(Logger LOGGER) {
|
public ASTVisitor(Logger LOGGER) { this.LOGGER = LOGGER; }
|
||||||
this.LOGGER = LOGGER;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SymbolTable getSymbolTable() {
|
public SymbolTable getSymbolTable() { return symbolTable; }
|
||||||
return symbolTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
private VarType getVarType(CminusParser.TypeSpecifierContext ctx) {
|
private VarType getVarType(CminusParser.TypeSpecifierContext ctx) {
|
||||||
final String t = ctx.getText();
|
final String t = ctx.getText();
|
||||||
return (t.equals("int")) ? VarType.INT : (t.equals("bool")) ? VarType.BOOL : VarType.CHAR;
|
return (t.equals("int")) ? VarType.INT
|
||||||
|
: (t.equals("bool")) ? VarType.BOOL
|
||||||
|
: VarType.CHAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -32,7 +29,7 @@ public class ASTVisitor extends CminusBaseVisitor<Node> {
|
|||||||
symbolTable = new SymbolTable();
|
symbolTable = new SymbolTable();
|
||||||
List<Declaration> decls = new ArrayList<>();
|
List<Declaration> decls = new ArrayList<>();
|
||||||
for (CminusParser.DeclarationContext d : ctx.declaration()) {
|
for (CminusParser.DeclarationContext d : ctx.declaration()) {
|
||||||
decls.add((Declaration) visitDeclaration(d));
|
decls.add((Declaration)visitDeclaration(d));
|
||||||
}
|
}
|
||||||
return new Program(decls);
|
return new Program(decls);
|
||||||
}
|
}
|
||||||
@ -45,10 +42,15 @@ public class ASTVisitor extends CminusBaseVisitor<Node> {
|
|||||||
for (CminusParser.VarDeclIdContext v : ctx.varDeclId()) {
|
for (CminusParser.VarDeclIdContext v : ctx.varDeclId()) {
|
||||||
String id = v.ID().getText();
|
String id = v.ID().getText();
|
||||||
ids.add(id);
|
ids.add(id);
|
||||||
symbolTable.addSymbol(id, new SymbolInfo(id, type, false));
|
// symbolTable.addSymbol(id, new SymbolInfo(id, type, false));
|
||||||
if (v.NUMCONST() != null) {
|
if (v.NUMCONST() != null) {
|
||||||
arraySizes.add(Integer.parseInt(v.NUMCONST().getText()));
|
arraySizes.add(Integer.parseInt(v.NUMCONST().getText()));
|
||||||
} else {
|
} else {
|
||||||
|
int offset = symbolTable.addOffset(1);
|
||||||
|
|
||||||
|
SymbolInfo symbol = new SymbolInfo(id, type, false, offset);
|
||||||
|
symbolTable.addSymbol(id, symbol);
|
||||||
|
|
||||||
arraySizes.add(-1);
|
arraySizes.add(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,12 +65,29 @@ public class ASTVisitor extends CminusBaseVisitor<Node> {
|
|||||||
returnType = getVarType(ctx.typeSpecifier());
|
returnType = getVarType(ctx.typeSpecifier());
|
||||||
}
|
}
|
||||||
String id = ctx.ID().getText();
|
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));
|
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)));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CminusParser.ParamContext p : ctx.param()) {
|
||||||
|
params.add((Param)visitParam(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
CompoundStatement statement =
|
||||||
|
(CompoundStatement)visitStatement(ctx.statement());
|
||||||
|
|
||||||
|
statement.getSymbolTable().addOtherTableBefore(newTable);
|
||||||
|
symbolTable = newTable.getParent();
|
||||||
|
|
||||||
return new FunDeclaration(returnType, id, params, statement);
|
return new FunDeclaration(returnType, id, params, statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,22 +95,27 @@ public class ASTVisitor extends CminusBaseVisitor<Node> {
|
|||||||
public Node visitParam(CminusParser.ParamContext ctx) {
|
public Node visitParam(CminusParser.ParamContext ctx) {
|
||||||
VarType type = getVarType(ctx.typeSpecifier());
|
VarType type = getVarType(ctx.typeSpecifier());
|
||||||
String id = ctx.paramId().ID().getText();
|
String id = ctx.paramId().ID().getText();
|
||||||
symbolTable.addSymbol(id, new SymbolInfo(id, type, false));
|
symbolTable.addSymbol(
|
||||||
|
id, new SymbolInfo(id, type, false, symbolTable.addOffset(1)));
|
||||||
|
|
||||||
return new Param(type, id, ctx.paramId().children.size() > 1);
|
return new Param(type, id, ctx.paramId().children.size() > 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node visitCompoundStmt(CminusParser.CompoundStmtContext ctx) {
|
public Node visitCompoundStmt(CminusParser.CompoundStmtContext ctx) {
|
||||||
symbolTable = symbolTable.createChild();
|
SymbolTable child = symbolTable.createChild();
|
||||||
|
symbolTable = child;
|
||||||
|
|
||||||
List<Statement> statements = new ArrayList<>();
|
List<Statement> statements = new ArrayList<>();
|
||||||
for (CminusParser.VarDeclarationContext d : ctx.varDeclaration()) {
|
for (CminusParser.VarDeclarationContext d : ctx.varDeclaration()) {
|
||||||
statements.add((VarDeclaration) visitVarDeclaration(d));
|
statements.add((VarDeclaration)visitVarDeclaration(d));
|
||||||
}
|
}
|
||||||
for (CminusParser.StatementContext d : ctx.statement()) {
|
for (CminusParser.StatementContext d : ctx.statement()) {
|
||||||
statements.add((Statement) visitStatement(d));
|
statements.add((Statement)visitStatement(d));
|
||||||
}
|
}
|
||||||
symbolTable = symbolTable.getParent();
|
symbolTable = child.getParent();
|
||||||
return new CompoundStatement(statements);
|
|
||||||
|
return new CompoundStatement(statements, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -99,31 +123,34 @@ public class ASTVisitor extends CminusBaseVisitor<Node> {
|
|||||||
if (ctx.expression() == null) {
|
if (ctx.expression() == null) {
|
||||||
return Statement.empty();
|
return Statement.empty();
|
||||||
}
|
}
|
||||||
return new ExpressionStatement((Expression) visitExpression(ctx.expression()));
|
return new ExpressionStatement(
|
||||||
|
(Expression)visitExpression(ctx.expression()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node visitIfStmt(CminusParser.IfStmtContext ctx) {
|
public Node visitIfStmt(CminusParser.IfStmtContext ctx) {
|
||||||
Expression expression = (Expression) visitSimpleExpression(ctx.simpleExpression());
|
Expression expression =
|
||||||
Statement trueStatement = (Statement) visitStatement(ctx.statement(0));
|
(Expression)visitSimpleExpression(ctx.simpleExpression());
|
||||||
|
Statement trueStatement = (Statement)visitStatement(ctx.statement(0));
|
||||||
Statement falseStatement = null;
|
Statement falseStatement = null;
|
||||||
if (ctx.statement().size() > 1) {
|
if (ctx.statement().size() > 1) {
|
||||||
falseStatement = (Statement) visitStatement(ctx.statement(1));
|
falseStatement = (Statement)visitStatement(ctx.statement(1));
|
||||||
}
|
}
|
||||||
return new If(expression, trueStatement, falseStatement);
|
return new If(expression, trueStatement, falseStatement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node visitWhileStmt(CminusParser.WhileStmtContext ctx) {
|
public Node visitWhileStmt(CminusParser.WhileStmtContext ctx) {
|
||||||
Expression expression = (Expression) visitSimpleExpression(ctx.simpleExpression());
|
Expression expression =
|
||||||
Statement statement = (Statement) visitStatement(ctx.statement());
|
(Expression)visitSimpleExpression(ctx.simpleExpression());
|
||||||
|
Statement statement = (Statement)visitStatement(ctx.statement());
|
||||||
return new While(expression, statement);
|
return new While(expression, statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node visitReturnStmt(CminusParser.ReturnStmtContext ctx) {
|
public Node visitReturnStmt(CminusParser.ReturnStmtContext ctx) {
|
||||||
if (ctx.expression() != null) {
|
if (ctx.expression() != null) {
|
||||||
return new Return((Expression) visitExpression(ctx.expression()));
|
return new Return((Expression)visitExpression(ctx.expression()));
|
||||||
}
|
}
|
||||||
return new Return(null);
|
return new Return(null);
|
||||||
}
|
}
|
||||||
@ -141,11 +168,12 @@ public class ASTVisitor extends CminusBaseVisitor<Node> {
|
|||||||
if (mutable != null) {
|
if (mutable != null) {
|
||||||
// Assignment
|
// Assignment
|
||||||
ParseTree operator = ctx.getChild(1);
|
ParseTree operator = ctx.getChild(1);
|
||||||
Mutable lhs = (Mutable) visitMutable(mutable);// new Mutable(mutable.ID().getText(), (Expression)
|
Mutable lhs = (Mutable)visitMutable(
|
||||||
|
mutable); // new Mutable(mutable.ID().getText(), (Expression)
|
||||||
// visitExpression(mutable.expression()));
|
// visitExpression(mutable.expression()));
|
||||||
Expression rhs = null;
|
Expression rhs = null;
|
||||||
if (expression != null) {
|
if (expression != null) {
|
||||||
rhs = (Expression) visitExpression(expression);
|
rhs = (Expression)visitExpression(expression);
|
||||||
}
|
}
|
||||||
ret = new Assignment(lhs, operator.getText(), rhs);
|
ret = new Assignment(lhs, operator.getText(), rhs);
|
||||||
} else {
|
} else {
|
||||||
@ -163,9 +191,10 @@ public class ASTVisitor extends CminusBaseVisitor<Node> {
|
|||||||
if (ands.size() == 1) {
|
if (ands.size() == 1) {
|
||||||
return ands.get(0);
|
return ands.get(0);
|
||||||
}
|
}
|
||||||
BinaryOperator op = new BinaryOperator((Expression) ands.get(0), "||", (Expression) ands.get(1));
|
BinaryOperator op = new BinaryOperator((Expression)ands.get(0), "||",
|
||||||
|
(Expression)ands.get(1));
|
||||||
for (int i = 2; i < ands.size(); ++i) {
|
for (int i = 2; i < ands.size(); ++i) {
|
||||||
op = new BinaryOperator(op, "||", (Expression) ands.get(i));
|
op = new BinaryOperator(op, "||", (Expression)ands.get(i));
|
||||||
}
|
}
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
@ -179,16 +208,18 @@ public class ASTVisitor extends CminusBaseVisitor<Node> {
|
|||||||
if (uns.size() == 1) {
|
if (uns.size() == 1) {
|
||||||
return uns.get(0);
|
return uns.get(0);
|
||||||
}
|
}
|
||||||
BinaryOperator op = new BinaryOperator((Expression) uns.get(0), "&&", (Expression) uns.get(1));
|
BinaryOperator op = new BinaryOperator((Expression)uns.get(0), "&&",
|
||||||
|
(Expression)uns.get(1));
|
||||||
for (int i = 2; i < uns.size(); ++i) {
|
for (int i = 2; i < uns.size(); ++i) {
|
||||||
op = new BinaryOperator(op, "&&", (Expression) uns.get(i));
|
op = new BinaryOperator(op, "&&", (Expression)uns.get(i));
|
||||||
}
|
}
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node visitUnaryRelExpression(CminusParser.UnaryRelExpressionContext ctx) {
|
public Node
|
||||||
Expression e = (Expression) visitRelExpression(ctx.relExpression());
|
visitUnaryRelExpression(CminusParser.UnaryRelExpressionContext ctx) {
|
||||||
|
Expression e = (Expression)visitRelExpression(ctx.relExpression());
|
||||||
for (TerminalNode n : ctx.BANG()) {
|
for (TerminalNode n : ctx.BANG()) {
|
||||||
e = new UnaryOperator("!", e);
|
e = new UnaryOperator("!", e);
|
||||||
}
|
}
|
||||||
@ -204,10 +235,11 @@ public class ASTVisitor extends CminusBaseVisitor<Node> {
|
|||||||
if (uns.size() == 1) {
|
if (uns.size() == 1) {
|
||||||
return uns.get(0);
|
return uns.get(0);
|
||||||
}
|
}
|
||||||
BinaryOperator op = new BinaryOperator((Expression) uns.get(0), ctx.relop(0).getText(),
|
BinaryOperator op = new BinaryOperator(
|
||||||
(Expression) uns.get(1));
|
(Expression)uns.get(0), ctx.relop(0).getText(), (Expression)uns.get(1));
|
||||||
for (int i = 2; i < uns.size(); ++i) {
|
for (int i = 2; i < uns.size(); ++i) {
|
||||||
op = new BinaryOperator(op, ctx.relop(i - 1).getText(), (Expression) uns.get(i));
|
op = new BinaryOperator(op, ctx.relop(i - 1).getText(),
|
||||||
|
(Expression)uns.get(i));
|
||||||
}
|
}
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
@ -221,9 +253,11 @@ public class ASTVisitor extends CminusBaseVisitor<Node> {
|
|||||||
if (es.size() == 1) {
|
if (es.size() == 1) {
|
||||||
return es.get(0);
|
return es.get(0);
|
||||||
}
|
}
|
||||||
BinaryOperator op = new BinaryOperator((Expression) es.get(0), ctx.sumop(0).getText(), (Expression) es.get(1));
|
BinaryOperator op = new BinaryOperator(
|
||||||
|
(Expression)es.get(0), ctx.sumop(0).getText(), (Expression)es.get(1));
|
||||||
for (int i = 2; i < es.size(); ++i) {
|
for (int i = 2; i < es.size(); ++i) {
|
||||||
op = new BinaryOperator(op, ctx.sumop(i - 1).getText(), (Expression) es.get(i));
|
op = new BinaryOperator(op, ctx.sumop(i - 1).getText(),
|
||||||
|
(Expression)es.get(i));
|
||||||
}
|
}
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
@ -237,9 +271,11 @@ public class ASTVisitor extends CminusBaseVisitor<Node> {
|
|||||||
if (es.size() == 1) {
|
if (es.size() == 1) {
|
||||||
return es.get(0);
|
return es.get(0);
|
||||||
}
|
}
|
||||||
BinaryOperator op = new BinaryOperator((Expression) es.get(0), ctx.mulop(0).getText(), (Expression) es.get(1));
|
BinaryOperator op = new BinaryOperator(
|
||||||
|
(Expression)es.get(0), ctx.mulop(0).getText(), (Expression)es.get(1));
|
||||||
for (int i = 2; i < es.size(); ++i) {
|
for (int i = 2; i < es.size(); ++i) {
|
||||||
op = new BinaryOperator(op, ctx.mulop(i - 1).getText(), (Expression) es.get(i));
|
op = new BinaryOperator(op, ctx.mulop(i - 1).getText(),
|
||||||
|
(Expression)es.get(i));
|
||||||
}
|
}
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
@ -248,7 +284,7 @@ public class ASTVisitor extends CminusBaseVisitor<Node> {
|
|||||||
public Node visitUnaryExpression(CminusParser.UnaryExpressionContext ctx) {
|
public Node visitUnaryExpression(CminusParser.UnaryExpressionContext ctx) {
|
||||||
Node ret = visitFactor(ctx.factor());
|
Node ret = visitFactor(ctx.factor());
|
||||||
for (int i = ctx.unaryop().size() - 1; i >= 0; i--) {
|
for (int i = ctx.unaryop().size() - 1; i >= 0; i--) {
|
||||||
ret = new UnaryOperator(ctx.unaryop(i).getText(), (Expression) ret);
|
ret = new UnaryOperator(ctx.unaryop(i).getText(), (Expression)ret);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -257,11 +293,12 @@ public class ASTVisitor extends CminusBaseVisitor<Node> {
|
|||||||
public Node visitMutable(CminusParser.MutableContext ctx) {
|
public Node visitMutable(CminusParser.MutableContext ctx) {
|
||||||
Expression e = null;
|
Expression e = null;
|
||||||
if (ctx.expression() != null) {
|
if (ctx.expression() != null) {
|
||||||
e = (Expression) visitExpression(ctx.expression());
|
e = (Expression)visitExpression(ctx.expression());
|
||||||
}
|
}
|
||||||
String id = ctx.ID().getText();
|
String id = ctx.ID().getText();
|
||||||
if (symbolTable.find(id) == null) {
|
if (symbolTable.find(id) == null) {
|
||||||
LOGGER.warning("Undefined symbol on line " + ctx.getStart().getLine() + ": " + id);
|
LOGGER.warning("Undefined symbol on line " + ctx.getStart().getLine() +
|
||||||
|
": " + id);
|
||||||
}
|
}
|
||||||
return new Mutable(id, e);
|
return new Mutable(id, e);
|
||||||
}
|
}
|
||||||
@ -269,7 +306,7 @@ public class ASTVisitor extends CminusBaseVisitor<Node> {
|
|||||||
@Override
|
@Override
|
||||||
public Node visitImmutable(CminusParser.ImmutableContext ctx) {
|
public Node visitImmutable(CminusParser.ImmutableContext ctx) {
|
||||||
if (ctx.expression() != null) {
|
if (ctx.expression() != null) {
|
||||||
return new ParenExpression((Expression) visitExpression(ctx.expression()));
|
return new ParenExpression((Expression)visitExpression(ctx.expression()));
|
||||||
}
|
}
|
||||||
return visitChildren(ctx);
|
return visitChildren(ctx);
|
||||||
}
|
}
|
||||||
@ -279,10 +316,11 @@ public class ASTVisitor extends CminusBaseVisitor<Node> {
|
|||||||
final String id = ctx.ID().getText();
|
final String id = ctx.ID().getText();
|
||||||
final List<Expression> args = new ArrayList<>();
|
final List<Expression> args = new ArrayList<>();
|
||||||
for (CminusParser.ExpressionContext e : ctx.expression()) {
|
for (CminusParser.ExpressionContext e : ctx.expression()) {
|
||||||
args.add((Expression) visitExpression(e));
|
args.add((Expression)visitExpression(e));
|
||||||
}
|
}
|
||||||
if (symbolTable.find(id) == null) {
|
if (symbolTable.find(id) == null) {
|
||||||
LOGGER.warning("Undefined symbol on line " + ctx.getStart().getLine() + ": " + id);
|
LOGGER.warning("Undefined symbol on line " + ctx.getStart().getLine() +
|
||||||
|
": " + id);
|
||||||
}
|
}
|
||||||
return new Call(id, args);
|
return new Call(id, args);
|
||||||
}
|
}
|
||||||
|
@ -57,5 +57,4 @@ public class MIPSResult {
|
|||||||
public VarType getType() {
|
public VarType getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,29 @@ public final class RegisterAllocator {
|
|||||||
private final boolean[] s = new boolean[8];
|
private final boolean[] s = new boolean[8];
|
||||||
private final Set<String> used = new HashSet<>();
|
private final Set<String> used = new HashSet<>();
|
||||||
|
|
||||||
public RegisterAllocator() {
|
public RegisterAllocator() { clearAll(); }
|
||||||
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 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() {
|
public String getT() {
|
||||||
@ -36,20 +57,21 @@ public final class RegisterAllocator {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public String getS() {
|
// public String getS() {
|
||||||
// for (int i = 0; i < s.length; ++i) {
|
// for (int i = 0; i < s.length; ++i) {
|
||||||
// if (!s[i]) {
|
// if (!s[i]) {
|
||||||
// s[i] = true;
|
// s[i] = true;
|
||||||
// String str = "$s" + i;
|
// String str = "$s" + i;
|
||||||
// used.add(str);
|
// used.add(str);
|
||||||
// return str;
|
// return str;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// return null;
|
// return null;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Returns the number of bytes used to save the registers
|
// Returns the number of bytes used to save the registers
|
||||||
public int saveRestore(StringBuilder code, int baseOffset, boolean s_or_t, boolean save) {
|
public int saveRestore(StringBuilder code, int baseOffset, boolean s_or_t,
|
||||||
|
boolean save) {
|
||||||
boolean[] r = s;
|
boolean[] r = s;
|
||||||
String prefix = "$s";
|
String prefix = "$s";
|
||||||
if (!s_or_t) {
|
if (!s_or_t) {
|
||||||
@ -65,31 +87,34 @@ public final class RegisterAllocator {
|
|||||||
if (r[i]) {
|
if (r[i]) {
|
||||||
offset -= 4;
|
offset -= 4;
|
||||||
String str = prefix + i;
|
String str = prefix + i;
|
||||||
code.append(instruction).append(" ").append(str).append(" ").append(offset-baseOffset).append("($sp)\n");
|
code.append(instruction)
|
||||||
|
.append(" ")
|
||||||
|
.append(str)
|
||||||
|
.append(" ")
|
||||||
|
.append(offset - baseOffset)
|
||||||
|
.append("($sp)\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -offset;
|
return -offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public int saveS(StringBuilder code, int baseOffset) {
|
// public int saveS(StringBuilder code, int baseOffset) {
|
||||||
// return saveRestore(code, baseOffset, true, true);
|
// return saveRestore(code, baseOffset, true, true);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public int saveT(StringBuilder code, int baseOffset) {
|
public int saveT(StringBuilder code, int baseOffset) {
|
||||||
return saveRestore(code, baseOffset, false, true);
|
return saveRestore(code, baseOffset, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public int restoreS(StringBuilder code, int baseOffset) {
|
// public int restoreS(StringBuilder code, int baseOffset) {
|
||||||
// return saveRestore(code, baseOffset, true, false);
|
// return saveRestore(code, baseOffset, true, false);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public int restoreT(StringBuilder code, int baseOffset) {
|
public int restoreT(StringBuilder code, int baseOffset) {
|
||||||
return saveRestore(code, baseOffset, false, false);
|
return saveRestore(code, baseOffset, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getUsed() {
|
public List<String> getUsed() { return new ArrayList<>(used); }
|
||||||
return new ArrayList<>(used);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Any time you call this method you should seriously consider adding a
|
* Any time you call this method you should seriously consider adding a
|
||||||
@ -98,10 +123,10 @@ public final class RegisterAllocator {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String getAny() {
|
public String getAny() {
|
||||||
// String availS = getS();
|
// String availS = getS();
|
||||||
// if (availS != null) {
|
// if (availS != null) {
|
||||||
// return availS;
|
// return availS;
|
||||||
// }
|
// }
|
||||||
String t = getT();
|
String t = getT();
|
||||||
if (t == null) {
|
if (t == null) {
|
||||||
throw new RuntimeException("Out of registers");
|
throw new RuntimeException("Out of registers");
|
||||||
@ -110,6 +135,8 @@ public final class RegisterAllocator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void clear(String reg) {
|
public void clear(String reg) {
|
||||||
|
if (reg == null)
|
||||||
|
return;
|
||||||
if (reg.charAt(1) == 's') {
|
if (reg.charAt(1) == 's') {
|
||||||
s[Integer.parseInt(reg.substring(2))] = false;
|
s[Integer.parseInt(reg.substring(2))] = false;
|
||||||
} else if (reg.charAt(1) == 't') {
|
} else if (reg.charAt(1) == 't') {
|
||||||
|
@ -16,6 +16,7 @@ public class SymbolInfo {
|
|||||||
// In the case of a function, type is the return type
|
// In the case of a function, type is the return type
|
||||||
private final VarType type;
|
private final VarType type;
|
||||||
private final boolean function;
|
private final boolean function;
|
||||||
|
private int offset;
|
||||||
|
|
||||||
public SymbolInfo(String id, VarType type, boolean function) {
|
public SymbolInfo(String id, VarType type, boolean function) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@ -23,9 +24,20 @@ public class SymbolInfo {
|
|||||||
this.function = function;
|
this.function = function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SymbolInfo(String id, VarType type, boolean function, int offset) {
|
||||||
|
this(id, type, function);
|
||||||
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "<" + id + ", " + type + '>';
|
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.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import submit.ast.VarType;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Code formatter project
|
* Code formatter project
|
||||||
@ -17,14 +18,71 @@ public class SymbolTable {
|
|||||||
private SymbolTable parent;
|
private SymbolTable parent;
|
||||||
private final List<SymbolTable> children;
|
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() {
|
public SymbolTable() {
|
||||||
|
offset = 0;
|
||||||
table = new HashMap<>();
|
table = new HashMap<>();
|
||||||
parent = null;
|
parent = null;
|
||||||
children = new ArrayList<>();
|
children = new ArrayList<>();
|
||||||
|
|
||||||
|
this.addGlobalSymbols();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addSymbol(String id, SymbolInfo symbol) {
|
public List<String> symbolNames() { return new ArrayList<>(table.keySet()); }
|
||||||
table.put(id, symbol);
|
|
||||||
|
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;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SymbolTable getParent() {
|
public SymbolTable getParent() { return parent; }
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,6 @@ public class AbstractNode implements Node {
|
|||||||
|
|
||||||
public MIPSResult toMIPS(StringBuilder code, StringBuilder data, SymbolTable symbolTable,
|
public MIPSResult toMIPS(StringBuilder code, StringBuilder data, SymbolTable symbolTable,
|
||||||
RegisterAllocator regAllocator) {
|
RegisterAllocator regAllocator) {
|
||||||
return null;
|
return MIPSResult.createVoidResult();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
*/
|
*/
|
||||||
package submit.ast;
|
package submit.ast;
|
||||||
|
|
||||||
|
import submit.MIPSResult;
|
||||||
|
import submit.RegisterAllocator;
|
||||||
|
import submit.SymbolTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author edwajohn
|
* @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;
|
package submit.ast;
|
||||||
|
|
||||||
|
import submit.MIPSResult;
|
||||||
|
import submit.RegisterAllocator;
|
||||||
|
import submit.SymbolTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
@ -13,7 +17,8 @@ public class BinaryOperator extends AbstractNode implements Expression {
|
|||||||
private final Expression lhs, rhs;
|
private final Expression lhs, rhs;
|
||||||
private final BinaryOperatorType type;
|
private final BinaryOperatorType type;
|
||||||
|
|
||||||
public BinaryOperator(Expression lhs, BinaryOperatorType type, Expression rhs) {
|
public BinaryOperator(Expression lhs, BinaryOperatorType type,
|
||||||
|
Expression rhs) {
|
||||||
this.lhs = lhs;
|
this.lhs = lhs;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.rhs = rhs;
|
this.rhs = rhs;
|
||||||
@ -32,4 +37,86 @@ public class BinaryOperator extends AbstractNode implements Expression {
|
|||||||
rhs.toCminus(builder, prefix);
|
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:
|
||||||
|
code.append(String.format("slt %s %s %s\n", resultRegister, leftRegister,
|
||||||
|
rightRegister))
|
||||||
|
.append(
|
||||||
|
String.format("subi %s %s 1\n", resultRegister, resultRegister));
|
||||||
|
break;
|
||||||
|
case GT:
|
||||||
|
code.append(String.format("slt %s %s %s\n", resultRegister, rightRegister,
|
||||||
|
leftRegister))
|
||||||
|
.append(
|
||||||
|
String.format("subi %s %s 1\n", resultRegister, resultRegister));
|
||||||
|
break;
|
||||||
|
case LE:
|
||||||
|
code.append(String.format("slt %s %s %s\n", resultRegister, rightRegister,
|
||||||
|
leftRegister));
|
||||||
|
break;
|
||||||
|
case GE:
|
||||||
|
code.append(String.format("slt %s %s %s\n", resultRegister, leftRegister,
|
||||||
|
rightRegister));
|
||||||
|
break;
|
||||||
|
case EQ:
|
||||||
|
code.append(String.format("sub %s %s %s\n", resultRegister, leftRegister,
|
||||||
|
rightRegister));
|
||||||
|
break;
|
||||||
|
case OR:
|
||||||
|
code.append(String.format("or %s %s %s\n", resultRegister, leftRegister,
|
||||||
|
rightRegister));
|
||||||
|
break;
|
||||||
|
case AND:
|
||||||
|
code.append(String.format("abs %s %s\n", leftRegister, leftRegister))
|
||||||
|
.append(String.format("abs %s %s\n", rightRegister, rightRegister))
|
||||||
|
.append(String.format("add %s %s %s\n", resultRegister, leftRegister,
|
||||||
|
rightRegister));
|
||||||
|
break;
|
||||||
|
case NE:
|
||||||
|
code.append(String.format("xor %s %s %s\n", resultRegister, leftRegister,
|
||||||
|
rightRegister))
|
||||||
|
.append(
|
||||||
|
String.format("sltiu %s %s 1\n", resultRegister, resultRegister));
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
regAllocator.clear(leftRegister);
|
||||||
|
regAllocator.clear(rightRegister);
|
||||||
|
|
||||||
|
return MIPSResult.createRegisterResult(resultRegister, VarType.INT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,15 +10,23 @@ package submit.ast;
|
|||||||
*/
|
*/
|
||||||
public enum BinaryOperatorType {
|
public enum BinaryOperatorType {
|
||||||
|
|
||||||
OR("||"), AND("&&"),
|
OR("||"),
|
||||||
LE("<="), LT("<"), GT(">"), GE(">="), EQ("=="), NE("!="),
|
AND("&&"),
|
||||||
PLUS("+"), MINUS("-"), TIMES("*"), DIVIDE("/"), MOD("%");
|
LE("<="),
|
||||||
|
LT("<"),
|
||||||
|
GT(">"),
|
||||||
|
GE(">="),
|
||||||
|
EQ("=="),
|
||||||
|
NE("!="),
|
||||||
|
PLUS("+"),
|
||||||
|
MINUS("-"),
|
||||||
|
TIMES("*"),
|
||||||
|
DIVIDE("/"),
|
||||||
|
MOD("%");
|
||||||
|
|
||||||
private final String value;
|
private final String value;
|
||||||
|
|
||||||
private BinaryOperatorType(String value) {
|
private BinaryOperatorType(String value) { this.value = value; }
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BinaryOperatorType fromString(String s) {
|
public static BinaryOperatorType fromString(String s) {
|
||||||
for (BinaryOperatorType at : BinaryOperatorType.values()) {
|
for (BinaryOperatorType at : BinaryOperatorType.values()) {
|
||||||
@ -26,12 +34,12 @@ public enum BinaryOperatorType {
|
|||||||
return at;
|
return at;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new RuntimeException("Illegal string in OperatorType.fromString(): " + s);
|
throw new RuntimeException("Illegal string in OperatorType.fromString(): " +
|
||||||
|
s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,9 @@ package submit.ast;
|
|||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
*/
|
*/
|
||||||
public class BoolConstant extends AbstractNode implements Expression {
|
public class BoolConstant extends AbstractNode implements Expression {
|
||||||
|
|
||||||
private final boolean value;
|
private final boolean value;
|
||||||
|
|
||||||
public BoolConstant(boolean value) {
|
public BoolConstant(boolean value) { this.value = value; }
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toCminus(StringBuilder builder, final String prefix) {
|
public void toCminus(StringBuilder builder, final String prefix) {
|
||||||
if (value) {
|
if (value) {
|
||||||
@ -23,5 +20,4 @@ public class BoolConstant extends AbstractNode implements Expression {
|
|||||||
builder.append("false");
|
builder.append("false");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,8 @@ package submit.ast;
|
|||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
*/
|
*/
|
||||||
public class Break extends AbstractNode implements Statement {
|
public class Break extends AbstractNode implements Statement {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toCminus(StringBuilder builder, String prefix) {
|
public void toCminus(StringBuilder builder, String prefix) {
|
||||||
builder.append(prefix).append("break;\n");
|
builder.append(prefix).append("break;\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,16 @@ package submit.ast;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import submit.MIPSResult;
|
||||||
|
import submit.RegisterAllocator;
|
||||||
|
import submit.SymbolTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
*/
|
*/
|
||||||
public class Call extends AbstractNode implements Expression {
|
public class Call implements Expression {
|
||||||
|
|
||||||
private final String id;
|
private final String id;
|
||||||
private final List<Expression> args;
|
private final List<Expression> args;
|
||||||
@ -21,6 +25,39 @@ public class Call extends AbstractNode implements Expression {
|
|||||||
this.args = new ArrayList<>(args);
|
this.args = new ArrayList<>(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void println(List<MIPSResult> mipsResults, StringBuilder code,
|
||||||
|
StringBuilder data, SymbolTable symbolTable,
|
||||||
|
RegisterAllocator regAllocator) {
|
||||||
|
code.append("# println\n");
|
||||||
|
|
||||||
|
for (MIPSResult result : mipsResults) {
|
||||||
|
if (result.getRegister() == null && result.getAddress() != null) {
|
||||||
|
if (result.getAddress().startsWith("$")) {
|
||||||
|
// Hack - might be a register
|
||||||
|
regAllocator.loadIntoRegister(result, code, "$a0");
|
||||||
|
} else {
|
||||||
|
code.append(String.format("la $a0 %s\n", result.getAddress()));
|
||||||
|
}
|
||||||
|
} else if (result.getRegister() != null) {
|
||||||
|
code.append(String.format("move $a0 %s\n", result.getRegister()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.getType() == VarType.INT) {
|
||||||
|
code.append("li $v0 1\n");
|
||||||
|
} else if (result.getType() == VarType.CHAR) {
|
||||||
|
code.append("li $v0 11\n");
|
||||||
|
} else {
|
||||||
|
code.append("li $v0 4\n");
|
||||||
|
}
|
||||||
|
code.append("syscall\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// End line with newline
|
||||||
|
code.append(String.format("la $a0 %s\n", "newline"));
|
||||||
|
code.append("li $v0 4\n");
|
||||||
|
code.append("syscall\n");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toCminus(StringBuilder builder, String prefix) {
|
public void toCminus(StringBuilder builder, String prefix) {
|
||||||
builder.append(id).append("(");
|
builder.append(id).append("(");
|
||||||
@ -34,4 +71,69 @@ public class Call extends AbstractNode implements Expression {
|
|||||||
builder.append(")");
|
builder.append(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MIPSResult toMIPS(StringBuilder code, StringBuilder data,
|
||||||
|
SymbolTable symbolTable,
|
||||||
|
RegisterAllocator regAllocator) {
|
||||||
|
List<MIPSResult> argMips;
|
||||||
|
String resultRegister = null;
|
||||||
|
|
||||||
|
if (this.id.equals("println")) {
|
||||||
|
argMips =
|
||||||
|
args.stream()
|
||||||
|
.map(e -> e.toMIPS(code, data, symbolTable, regAllocator))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
this.println(argMips, code, data, symbolTable, regAllocator);
|
||||||
|
} else {
|
||||||
|
argMips = new ArrayList<MIPSResult>();
|
||||||
|
String returnAddr = regAllocator.getAny();
|
||||||
|
code.append(String.format("move %s $ra\n", returnAddr));
|
||||||
|
int savedRegistersOffset = regAllocator.saveRestore(
|
||||||
|
code, -symbolTable.getOffset(), false, true);
|
||||||
|
|
||||||
|
int argsOffset = symbolTable.getOffset() - savedRegistersOffset;
|
||||||
|
int i = argsOffset;
|
||||||
|
for (Expression expression : args) {
|
||||||
|
MIPSResult mipsResult =
|
||||||
|
expression.toMIPS(code, data, symbolTable, regAllocator);
|
||||||
|
argMips.add(mipsResult);
|
||||||
|
i -= 4;
|
||||||
|
|
||||||
|
String reg =
|
||||||
|
regAllocator.getRegisterOrLoadIntoRegister(mipsResult, code);
|
||||||
|
code.append(String.format("sw %s %d($sp)\n", reg, i));
|
||||||
|
|
||||||
|
regAllocator.clear(reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
code.append(String.format("add $sp $sp %d\n", argsOffset));
|
||||||
|
|
||||||
|
code.append(String.format("jal %s\n", id));
|
||||||
|
|
||||||
|
code.append(String.format("add $sp $sp %d\n", -argsOffset));
|
||||||
|
|
||||||
|
regAllocator.saveRestore(code, -symbolTable.getOffset(), false,
|
||||||
|
false);
|
||||||
|
code.append(String.format("# symbol table size - %d\n", i));
|
||||||
|
|
||||||
|
resultRegister = regAllocator.getAny();
|
||||||
|
regAllocator.loadIntoRegisterWithOffset(
|
||||||
|
MIPSResult.createAddressResult("$sp", VarType.INT), code,
|
||||||
|
resultRegister, i - 4);
|
||||||
|
|
||||||
|
code.append(String.format("move $ra %s\n", returnAddr));
|
||||||
|
regAllocator.clear(returnAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MIPSResult arg : argMips)
|
||||||
|
if (arg.getRegister() != null)
|
||||||
|
regAllocator.clear(arg.getRegister());
|
||||||
|
|
||||||
|
if (resultRegister != null) {
|
||||||
|
VarType returnType = symbolTable.find(id).getType();
|
||||||
|
return MIPSResult.createRegisterResult(resultRegister, returnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MIPSResult.createVoidResult();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,15 +9,11 @@ package submit.ast;
|
|||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
*/
|
*/
|
||||||
public class CharConstant extends AbstractNode implements Expression {
|
public class CharConstant extends AbstractNode implements Expression {
|
||||||
|
|
||||||
private final char value;
|
private final char value;
|
||||||
|
|
||||||
public CharConstant(char value) {
|
public CharConstant(char value) { this.value = value; }
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toCminus(StringBuilder builder, final String prefix) {
|
public void toCminus(StringBuilder builder, final String prefix) {
|
||||||
builder.append("'").append(value).append("'");
|
builder.append("'").append(value).append("'");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
package submit.ast;
|
package submit.ast;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import submit.MIPSResult;
|
||||||
|
import submit.RegisterAllocator;
|
||||||
|
import submit.SymbolTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -13,11 +16,16 @@ import java.util.List;
|
|||||||
public class CompoundStatement extends AbstractNode implements Statement {
|
public class CompoundStatement extends AbstractNode implements Statement {
|
||||||
|
|
||||||
private final List<Statement> statements;
|
private final List<Statement> statements;
|
||||||
|
private SymbolTable symbolTable;
|
||||||
|
|
||||||
public CompoundStatement(List<Statement> statements) {
|
public CompoundStatement(List<Statement> statements,
|
||||||
|
SymbolTable symbolTable) {
|
||||||
this.statements = statements;
|
this.statements = statements;
|
||||||
|
this.symbolTable = symbolTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SymbolTable getSymbolTable() { return symbolTable; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toCminus(StringBuilder builder, String prefix) {
|
public void toCminus(StringBuilder builder, String prefix) {
|
||||||
builder.append(prefix).append("{\n");
|
builder.append(prefix).append("{\n");
|
||||||
@ -27,4 +35,25 @@ public class CompoundStatement extends AbstractNode implements Statement {
|
|||||||
builder.append(prefix).append("}\n");
|
builder.append(prefix).append("}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MIPSResult toMIPS(StringBuilder code, StringBuilder data,
|
||||||
|
SymbolTable symbolTable,
|
||||||
|
RegisterAllocator regAllocator) {
|
||||||
|
code.append("# Entering a new scope.\n");
|
||||||
|
code.append("# Symbols in symbol table:\n");
|
||||||
|
for (String name : this.symbolTable.symbolNames())
|
||||||
|
code.append(
|
||||||
|
String.format("# %s : %d\n", name, this.symbolTable.offsetOf(name)));
|
||||||
|
|
||||||
|
code.append("# Update the stack pointer.\n");
|
||||||
|
code.append(String.format("addi $sp $sp %d\n", symbolTable.getOffset()));
|
||||||
|
|
||||||
|
for (Statement statement : statements)
|
||||||
|
statement.toMIPS(code, data, this.symbolTable, regAllocator);
|
||||||
|
|
||||||
|
code.append("# Exit scope.\n");
|
||||||
|
code.append(String.format("addi $sp $sp %s\n", -symbolTable.getOffset()));
|
||||||
|
|
||||||
|
return MIPSResult.createVoidResult();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,4 @@ package submit.ast;
|
|||||||
*
|
*
|
||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
*/
|
*/
|
||||||
public interface Declaration extends Statement {
|
public interface Declaration extends Statement {}
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -8,6 +8,4 @@ package submit.ast;
|
|||||||
*
|
*
|
||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
*/
|
*/
|
||||||
public interface Expression extends Node {
|
public interface Expression extends Node {}
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
*/
|
*/
|
||||||
package submit.ast;
|
package submit.ast;
|
||||||
|
|
||||||
|
import submit.MIPSResult;
|
||||||
|
import submit.RegisterAllocator;
|
||||||
|
import submit.SymbolTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
@ -23,4 +27,11 @@ public class ExpressionStatement extends AbstractNode implements Statement {
|
|||||||
builder.append(";\n");
|
builder.append(";\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MIPSResult toMIPS(StringBuilder code, StringBuilder data,
|
||||||
|
SymbolTable symbolTable,
|
||||||
|
RegisterAllocator regAllocator) {
|
||||||
|
expression.toMIPS(code, data, symbolTable, regAllocator);
|
||||||
|
return MIPSResult.createVoidResult();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,9 @@ package submit.ast;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import submit.MIPSResult;
|
||||||
|
import submit.RegisterAllocator;
|
||||||
|
import submit.SymbolTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -43,4 +46,20 @@ public class FunDeclaration extends AbstractNode implements Declaration {
|
|||||||
statement.toCminus(builder, prefix);
|
statement.toCminus(builder, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MIPSResult toMIPS(StringBuilder code, StringBuilder data,
|
||||||
|
SymbolTable symbolTable,
|
||||||
|
RegisterAllocator regAllocator) {
|
||||||
|
code.append(id).append(":\n");
|
||||||
|
|
||||||
|
statement.toMIPS(code, data, symbolTable, regAllocator);
|
||||||
|
|
||||||
|
if (id.equals("main"))
|
||||||
|
code.append("li $v0 10\nsyscall\n");
|
||||||
|
else
|
||||||
|
code.append("jr $ra\n");
|
||||||
|
regAllocator.clearAll();
|
||||||
|
|
||||||
|
return MIPSResult.createVoidResult();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
*/
|
*/
|
||||||
package submit.ast;
|
package submit.ast;
|
||||||
|
|
||||||
|
import submit.MIPSResult;
|
||||||
|
import submit.RegisterAllocator;
|
||||||
|
import submit.SymbolTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
@ -14,7 +18,8 @@ public class If extends AbstractNode implements Statement {
|
|||||||
private final Statement trueStatement;
|
private final Statement trueStatement;
|
||||||
private final Statement falseStatement;
|
private final Statement falseStatement;
|
||||||
|
|
||||||
public If(Expression expression, Statement trueStatement, Statement falseStatement) {
|
public If(Expression expression, Statement trueStatement,
|
||||||
|
Statement falseStatement) {
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
this.trueStatement = trueStatement;
|
this.trueStatement = trueStatement;
|
||||||
this.falseStatement = falseStatement;
|
this.falseStatement = falseStatement;
|
||||||
@ -41,4 +46,37 @@ public class If extends AbstractNode implements Statement {
|
|||||||
}
|
}
|
||||||
// builder.append(prefix).append("}");
|
// builder.append(prefix).append("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MIPSResult toMIPS(StringBuilder code, StringBuilder data,
|
||||||
|
SymbolTable symbolTable,
|
||||||
|
RegisterAllocator regAllocator) {
|
||||||
|
String continueLabel = "if_" + SymbolTable.nextId();
|
||||||
|
String elseLabel = "else_" + SymbolTable.nextId();
|
||||||
|
|
||||||
|
MIPSResult expressionTruthiness =
|
||||||
|
expression.toMIPS(code, data, symbolTable, regAllocator);
|
||||||
|
|
||||||
|
code.append(String.format("bne %s $zero %s\n",
|
||||||
|
expressionTruthiness.getRegister(), elseLabel));
|
||||||
|
regAllocator.clear(expressionTruthiness.getRegister());
|
||||||
|
|
||||||
|
MIPSResult trueRes =
|
||||||
|
trueStatement.toMIPS(code, data, symbolTable, regAllocator);
|
||||||
|
regAllocator.clear(trueRes.getRegister());
|
||||||
|
|
||||||
|
code.append(String.format("j %s\n", continueLabel))
|
||||||
|
.append(String.format("%s:\n", elseLabel));
|
||||||
|
|
||||||
|
regAllocator.clear(expressionTruthiness.getRegister());
|
||||||
|
|
||||||
|
if (falseStatement != null) {
|
||||||
|
MIPSResult falseRes =
|
||||||
|
falseStatement.toMIPS(code, data, symbolTable, regAllocator);
|
||||||
|
regAllocator.clear(falseRes.getRegister());
|
||||||
|
}
|
||||||
|
code.append(String.format("%s:\n", continueLabel));
|
||||||
|
|
||||||
|
return MIPSResult.createVoidResult();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,15 @@
|
|||||||
*/
|
*/
|
||||||
package submit.ast;
|
package submit.ast;
|
||||||
|
|
||||||
|
import submit.MIPSResult;
|
||||||
|
import submit.RegisterAllocator;
|
||||||
|
import submit.SymbolTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
*/
|
*/
|
||||||
public class Mutable extends AbstractNode implements Expression {
|
public class Mutable implements Expression {
|
||||||
|
|
||||||
private final String id;
|
private final String id;
|
||||||
private final Expression index;
|
private final Expression index;
|
||||||
@ -28,4 +32,14 @@ public class Mutable extends AbstractNode implements Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MIPSResult toMIPS(StringBuilder code, StringBuilder data,
|
||||||
|
SymbolTable symbolTable,
|
||||||
|
RegisterAllocator regAllocator) {
|
||||||
|
String stackReg = regAllocator.getAny();
|
||||||
|
|
||||||
|
code.append(String.format("li %s %d\n", stackReg, symbolTable.offsetOf(id)))
|
||||||
|
.append(String.format("add %s %s $sp\n", stackReg, stackReg));
|
||||||
|
|
||||||
|
return MIPSResult.createAddressResult(stackReg, VarType.INT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,5 +7,6 @@ import submit.SymbolTable;
|
|||||||
public interface Node {
|
public interface Node {
|
||||||
void toCminus(StringBuilder builder, final String prefix);
|
void toCminus(StringBuilder builder, final String prefix);
|
||||||
|
|
||||||
MIPSResult toMIPS(StringBuilder code, StringBuilder data, SymbolTable symbolTable, RegisterAllocator regAllocator);
|
MIPSResult toMIPS(StringBuilder code, StringBuilder data,
|
||||||
|
SymbolTable symbolTable, RegisterAllocator regAllocator);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
*/
|
*/
|
||||||
package submit.ast;
|
package submit.ast;
|
||||||
|
|
||||||
|
import submit.MIPSResult;
|
||||||
|
import submit.RegisterAllocator;
|
||||||
|
import submit.SymbolTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
@ -12,12 +16,19 @@ public class NumConstant extends AbstractNode implements Expression {
|
|||||||
|
|
||||||
private final int value;
|
private final int value;
|
||||||
|
|
||||||
public NumConstant(int value) {
|
public NumConstant(int value) { this.value = value; }
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toCminus(StringBuilder builder, final String prefix) {
|
public void toCminus(StringBuilder builder, final String prefix) {
|
||||||
builder.append(Integer.toString(value));
|
builder.append(Integer.toString(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MIPSResult toMIPS(StringBuilder code, StringBuilder data,
|
||||||
|
SymbolTable symbolTable,
|
||||||
|
RegisterAllocator regAllocator) {
|
||||||
|
String register = regAllocator.getAny();
|
||||||
|
code.append(String.format("li %s %d\n", register, value));
|
||||||
|
|
||||||
|
return MIPSResult.createRegisterResult(register, VarType.INT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,17 +20,11 @@ public class Param extends AbstractNode implements Node {
|
|||||||
this.array = array;
|
this.array = array;
|
||||||
}
|
}
|
||||||
|
|
||||||
public VarType getType() {
|
public VarType getType() { return type; }
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getId() {
|
public String getId() { return id; }
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isArray() {
|
public boolean isArray() { return array; }
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toCminus(StringBuilder builder, final String prefix) {
|
public void toCminus(StringBuilder builder, final String prefix) {
|
||||||
if (isArray()) {
|
if (isArray()) {
|
||||||
@ -39,5 +33,4 @@ public class Param extends AbstractNode implements Node {
|
|||||||
builder.append(type).append(" ").append(id);
|
builder.append(type).append(" ").append(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
*/
|
*/
|
||||||
package submit.ast;
|
package submit.ast;
|
||||||
|
|
||||||
|
import submit.MIPSResult;
|
||||||
|
import submit.RegisterAllocator;
|
||||||
|
import submit.SymbolTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
@ -23,4 +27,10 @@ public class ParenExpression extends AbstractNode implements Expression {
|
|||||||
builder.append(")");
|
builder.append(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MIPSResult toMIPS(StringBuilder code, StringBuilder data,
|
||||||
|
SymbolTable symbolTable,
|
||||||
|
RegisterAllocator regAllocator) {
|
||||||
|
return expression.toMIPS(code, data, symbolTable, regAllocator);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,9 @@ package submit.ast;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import submit.MIPSResult;
|
||||||
|
import submit.RegisterAllocator;
|
||||||
|
import submit.SymbolTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -33,4 +36,14 @@ public class Program extends AbstractNode implements Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MIPSResult toMIPS(StringBuilder code, StringBuilder data,
|
||||||
|
SymbolTable symbolTable,
|
||||||
|
RegisterAllocator regAllocator) {
|
||||||
|
data.append("newline: .asciiz \"\\n\"\n");
|
||||||
|
|
||||||
|
for (Declaration declaration : declarations)
|
||||||
|
declaration.toMIPS(code, data, symbolTable, regAllocator);
|
||||||
|
return MIPSResult.createVoidResult();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,18 @@
|
|||||||
*/
|
*/
|
||||||
package submit.ast;
|
package submit.ast;
|
||||||
|
|
||||||
|
import submit.MIPSResult;
|
||||||
|
import submit.RegisterAllocator;
|
||||||
|
import submit.SymbolTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
*/
|
*/
|
||||||
public class Return extends AbstractNode implements Statement {
|
public class Return extends AbstractNode implements Statement {
|
||||||
|
|
||||||
private final Expression expr;
|
private final Expression expr;
|
||||||
|
|
||||||
public Return(Expression expr) {
|
public Return(Expression expr) { this.expr = expr; }
|
||||||
this.expr = expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toCminus(StringBuilder builder, String prefix) {
|
public void toCminus(StringBuilder builder, String prefix) {
|
||||||
@ -28,4 +29,19 @@ public class Return extends AbstractNode implements Statement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MIPSResult toMIPS(StringBuilder code, StringBuilder data,
|
||||||
|
SymbolTable symbolTable,
|
||||||
|
RegisterAllocator regAllocator) {
|
||||||
|
if (expr != null) {
|
||||||
|
String reg = regAllocator.getRegisterOrLoadIntoRegister(
|
||||||
|
expr.toMIPS(code, data, symbolTable, regAllocator), code);
|
||||||
|
code.append(
|
||||||
|
String.format("# symbol table size - %d\n", symbolTable.getOffset()));
|
||||||
|
code.append(
|
||||||
|
String.format("sw %s %d($sp)\n", reg, symbolTable.getOffset()));
|
||||||
|
code.append("jr $ra\n");
|
||||||
|
}
|
||||||
|
return MIPSResult.createVoidResult();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,8 @@ import java.util.ArrayList;
|
|||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
*/
|
*/
|
||||||
public interface Statement extends Node {
|
public interface Statement extends Node {
|
||||||
public static CompoundStatement empty() { return new CompoundStatement(new ArrayList<>()); }
|
public static CompoundStatement empty() {
|
||||||
|
submit.SymbolTable newTable = new submit.SymbolTable();
|
||||||
|
return new CompoundStatement(new ArrayList<>(), newTable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
*/
|
*/
|
||||||
package submit.ast;
|
package submit.ast;
|
||||||
|
|
||||||
|
import submit.MIPSResult;
|
||||||
|
import submit.RegisterAllocator;
|
||||||
|
import submit.SymbolTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
@ -12,12 +16,19 @@ public class StringConstant extends AbstractNode implements Expression {
|
|||||||
|
|
||||||
private final String value;
|
private final String value;
|
||||||
|
|
||||||
public StringConstant(String value) {
|
public StringConstant(String value) { this.value = value; }
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toCminus(StringBuilder builder, final String prefix) {
|
public void toCminus(StringBuilder builder, final String prefix) {
|
||||||
builder.append("\"").append(value).append("\"");
|
builder.append("\"").append(value).append("\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MIPSResult toMIPS(StringBuilder code, StringBuilder data,
|
||||||
|
SymbolTable symbolTable,
|
||||||
|
RegisterAllocator regAllocator) {
|
||||||
|
String label = String.format("string_%s", SymbolTable.nextId());
|
||||||
|
data.append(String.format("%s: .asciiz %s\n", label, value));
|
||||||
|
|
||||||
|
return MIPSResult.createAddressResult(label, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
*/
|
*/
|
||||||
package submit.ast;
|
package submit.ast;
|
||||||
|
|
||||||
|
import submit.MIPSResult;
|
||||||
|
import submit.RegisterAllocator;
|
||||||
|
import submit.SymbolTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
@ -23,5 +27,27 @@ public class UnaryOperator extends AbstractNode implements Expression {
|
|||||||
builder.append(type);
|
builder.append(type);
|
||||||
expression.toCminus(builder, prefix);
|
expression.toCminus(builder, prefix);
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public MIPSResult toMIPS(StringBuilder code, StringBuilder data,
|
||||||
|
SymbolTable symbolTable,
|
||||||
|
RegisterAllocator regAllocator) {
|
||||||
|
MIPSResult result =
|
||||||
|
expression.toMIPS(code, data, symbolTable, regAllocator);
|
||||||
|
|
||||||
|
String reg = regAllocator.getRegisterOrLoadIntoRegister(result, code);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case NEG:
|
||||||
|
code.append(String.format("sub %s $zero %s\n", reg, reg));
|
||||||
|
break;
|
||||||
|
case NOT:
|
||||||
|
code.append(String.format("sltu %s $zero %s\n", reg, reg))
|
||||||
|
.append(String.format("xori %s %s 1\n", reg, reg));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MIPSResult.createRegisterResult(reg, VarType.INT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,8 @@ public class VarDeclaration extends AbstractNode implements Declaration {
|
|||||||
private final List<Integer> arraySizes;
|
private final List<Integer> arraySizes;
|
||||||
private final boolean isStatic;
|
private final boolean isStatic;
|
||||||
|
|
||||||
public VarDeclaration(VarType type, List<String> ids, List<Integer> arraySizes, boolean isStatic) {
|
public VarDeclaration(VarType type, List<String> ids,
|
||||||
|
List<Integer> arraySizes, boolean isStatic) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.ids = new ArrayList<>(ids);
|
this.ids = new ArrayList<>(ids);
|
||||||
this.arraySizes = arraySizes;
|
this.arraySizes = arraySizes;
|
||||||
@ -35,7 +36,8 @@ public class VarDeclaration extends AbstractNode implements Declaration {
|
|||||||
final String id = ids.get(i);
|
final String id = ids.get(i);
|
||||||
final int arraySize = arraySizes.get(i);
|
final int arraySize = arraySizes.get(i);
|
||||||
if (arraySize >= 0) {
|
if (arraySize >= 0) {
|
||||||
builder.append(id).append("[").append(arraySize).append("]").append(", ");
|
builder.append(id).append("[").append(arraySize).append("]").append(
|
||||||
|
", ");
|
||||||
} else {
|
} else {
|
||||||
builder.append(id).append(", ");
|
builder.append(id).append(", ");
|
||||||
}
|
}
|
||||||
@ -43,5 +45,4 @@ public class VarDeclaration extends AbstractNode implements Declaration {
|
|||||||
builder.delete(builder.length() - 2, builder.length());
|
builder.delete(builder.length() - 2, builder.length());
|
||||||
builder.append(";\n");
|
builder.append(";\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,13 @@ package submit.ast;
|
|||||||
*/
|
*/
|
||||||
public enum VarType {
|
public enum VarType {
|
||||||
|
|
||||||
INT("int"), BOOL("bool"), CHAR("char");
|
INT("int"),
|
||||||
|
BOOL("bool"),
|
||||||
|
CHAR("char");
|
||||||
|
|
||||||
private final String value;
|
private final String value;
|
||||||
|
|
||||||
private VarType(String value) {
|
private VarType(String value) { this.value = value; }
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static VarType fromString(String s) {
|
public static VarType fromString(String s) {
|
||||||
for (VarType vt : VarType.values()) {
|
for (VarType vt : VarType.values()) {
|
||||||
@ -31,5 +31,4 @@ public enum VarType {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
*/
|
*/
|
||||||
package submit.ast;
|
package submit.ast;
|
||||||
|
|
||||||
|
import submit.MIPSResult;
|
||||||
|
import submit.RegisterAllocator;
|
||||||
|
import submit.SymbolTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author edwajohn
|
* @author edwajohn
|
||||||
@ -28,6 +32,29 @@ public class While extends AbstractNode implements Statement {
|
|||||||
} else {
|
} else {
|
||||||
statement.toCminus(builder, prefix + " ");
|
statement.toCminus(builder, prefix + " ");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MIPSResult toMIPS(StringBuilder code, StringBuilder data,
|
||||||
|
SymbolTable symbolTable,
|
||||||
|
RegisterAllocator regAllocator) {
|
||||||
|
String loopLabel = "while_truthy_" + SymbolTable.nextId();
|
||||||
|
String finishedLabel = "finished_while_" + SymbolTable.nextId();
|
||||||
|
|
||||||
|
code.append(String.format("%s:\n", loopLabel));
|
||||||
|
|
||||||
|
MIPSResult expressionTruthiness =
|
||||||
|
expression.toMIPS(code, data, symbolTable, regAllocator);
|
||||||
|
|
||||||
|
code.append(String.format("bne %s $zero %s\n",
|
||||||
|
expressionTruthiness.getRegister(),
|
||||||
|
finishedLabel));
|
||||||
|
|
||||||
|
MIPSResult inside = statement.toMIPS(code, data, symbolTable, regAllocator);
|
||||||
|
regAllocator.clear(inside.getRegister());
|
||||||
|
code.append(String.format("j %s\n", loopLabel))
|
||||||
|
.append(String.format("%s:\n", finishedLabel));
|
||||||
|
|
||||||
|
return MIPSResult.createVoidResult();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user