mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-09-08 17:54:40 +00:00
Looking at function calls
This commit is contained in:
parent
2dedf8263b
commit
03ee43c3b7
@ -133,11 +133,11 @@ public class AsmFragment {
|
||||
signature.append("_then_");
|
||||
Label destination = conditionalJump.getDestination();
|
||||
ControlFlowBlock destinationBlock = graph.getBlock(destination);
|
||||
String destinationLabel = destination.getName();
|
||||
String destinationLabel = destination.getLocalName();
|
||||
if (destinationBlock.hasPhiStatements()) {
|
||||
destinationLabel = destination.getName() + "_from_" + block.getLabel().getName();
|
||||
destinationLabel = destination.getLocalName() + "_from_" + block.getLabel().getLocalName();
|
||||
}
|
||||
signature.append(bind(new Label(destinationLabel, false)));
|
||||
signature.append(bind(new Label(destinationLabel, destination.getScope(),false)));
|
||||
return signature.toString();
|
||||
}
|
||||
|
||||
@ -348,7 +348,7 @@ public class AsmFragment {
|
||||
bound = Integer.toString(boundInt.getNumber());
|
||||
}
|
||||
} else if (boundValue instanceof Label) {
|
||||
bound = ((Label) boundValue).getName().replace('@', 'B');
|
||||
bound = ((Label) boundValue).getLocalName().replace('@', 'B');
|
||||
} else {
|
||||
throw new RuntimeException("Bound Value Type not implemented " + boundValue);
|
||||
}
|
||||
|
@ -72,11 +72,11 @@ public class ControlFlowBlock {
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer out = new StringBuffer();
|
||||
out.append(label.getName() + ":" );
|
||||
out.append(label.getLocalName() + ":" );
|
||||
if(predecessors.size()>0) {
|
||||
out.append(" from");
|
||||
for (ControlFlowBlock predecessor : predecessors) {
|
||||
out.append(" " + predecessor.getLabel().getName());
|
||||
out.append(" " + predecessor.getLabel().getLocalName());
|
||||
}
|
||||
}
|
||||
out.append("\n");
|
||||
@ -85,7 +85,7 @@ public class ControlFlowBlock {
|
||||
}
|
||||
if(defaultSuccessor!=null) {
|
||||
out.append(" to:");
|
||||
out.append(defaultSuccessor.getLabel().getName());
|
||||
out.append(defaultSuccessor.getLabel().getLocalName());
|
||||
}
|
||||
out.append("\n");
|
||||
return out.toString();
|
||||
|
@ -27,8 +27,8 @@ public class ControlFlowGraphBaseVisitor<T> {
|
||||
return visitConditionalJump((StatementConditionalJump) statement);
|
||||
} else if(statement instanceof StatementJump) {
|
||||
return visitJump((StatementJump) statement);
|
||||
} else if(statement instanceof StatementJumpTarget) {
|
||||
return visitJumpTarget((StatementJumpTarget) statement);
|
||||
} else if(statement instanceof StatementLabel) {
|
||||
return visitJumpTarget((StatementLabel) statement);
|
||||
} else if(statement instanceof StatementPhi) {
|
||||
return visitPhi((StatementPhi) statement);
|
||||
} else {
|
||||
@ -48,7 +48,7 @@ public class ControlFlowGraphBaseVisitor<T> {
|
||||
return null;
|
||||
}
|
||||
|
||||
public T visitJumpTarget(StatementJumpTarget jumpTarget) {
|
||||
public T visitJumpTarget(StatementLabel jumpTarget) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1,22 +1,36 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/** A Symbol (variable, jump label, etc.) */
|
||||
/** A jump label */
|
||||
public class Label implements Symbol {
|
||||
|
||||
/** The name of the label. */
|
||||
private String name;
|
||||
|
||||
/** The name of the containing scope */
|
||||
private SymbolTable scope;
|
||||
|
||||
private boolean intermediate;
|
||||
|
||||
public Label(String name, boolean intermediate) {
|
||||
public Label(String name, SymbolTable scope, boolean intermediate) {
|
||||
this.name = name;
|
||||
this.scope = scope;
|
||||
this.intermediate = intermediate;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
public String getLocalName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolTable getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullName() {
|
||||
return SymbolTable.getFullName(this);
|
||||
}
|
||||
|
||||
public boolean isIntermediate() {
|
||||
return intermediate;
|
||||
}
|
||||
@ -25,27 +39,32 @@ public class Label implements Symbol {
|
||||
return SymbolTypeBasic.LABEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "("+getType().getTypeName() + ") "+name;
|
||||
public String getTypedName() {
|
||||
return "("+getType().getTypeName() + ") "+getFullName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Label that = (Label) o;
|
||||
Label label = (Label) o;
|
||||
|
||||
return name.equals(that.name);
|
||||
if (intermediate != label.intermediate) return false;
|
||||
if (!name.equals(label.name)) return false;
|
||||
return scope != null ? scope.equals(label.scope) : label.scope == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode();
|
||||
int result = name.hashCode();
|
||||
result = 31 * result + (scope != null ? scope.hashCode() : 0);
|
||||
result = 31 * result + (intermediate ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getTypedName();
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** Pass that generates a control flow graph for the program */
|
||||
@ -20,13 +18,13 @@ public class Pass1GenerateControlFlowGraph {
|
||||
}
|
||||
|
||||
public ControlFlowGraph generate(StatementSequence sequence) {
|
||||
this.firstBlock = getOrCreateBlock(symbolTable.newNamedJumpLabel(BEGIN_BLOCK_NAME));
|
||||
this.firstBlock = getOrCreateBlock(symbolTable.addLabel(BEGIN_BLOCK_NAME));
|
||||
ControlFlowBlock currentBlock = this.firstBlock;
|
||||
sequence.addStatement(new StatementJumpTarget(symbolTable.newNamedJumpLabel(END_BLOCK_NAME)));
|
||||
sequence.addStatement(new StatementLabel(symbolTable.addLabel(END_BLOCK_NAME)));
|
||||
for (Statement statement : sequence.getStatements()) {
|
||||
if(statement instanceof StatementJumpTarget) {
|
||||
StatementJumpTarget statementJumpTarget = (StatementJumpTarget) statement;
|
||||
ControlFlowBlock nextBlock = getOrCreateBlock(statementJumpTarget.getLabel());
|
||||
if(statement instanceof StatementLabel) {
|
||||
StatementLabel statementLabel = (StatementLabel) statement;
|
||||
ControlFlowBlock nextBlock = getOrCreateBlock(statementLabel.getLabel());
|
||||
currentBlock.setDefaultSuccessor(nextBlock);
|
||||
nextBlock.addPredecessor(currentBlock);
|
||||
currentBlock = nextBlock;
|
||||
@ -35,13 +33,13 @@ public class Pass1GenerateControlFlowGraph {
|
||||
ControlFlowBlock jmpBlock = getOrCreateBlock(statementJump.getDestination());
|
||||
currentBlock.setDefaultSuccessor(jmpBlock);
|
||||
jmpBlock.addPredecessor(currentBlock);
|
||||
ControlFlowBlock nextBlock = getOrCreateBlock(symbolTable.newIntermediateJumpLabel());
|
||||
ControlFlowBlock nextBlock = getOrCreateBlock(symbolTable.addLabelIntermediate());
|
||||
currentBlock = nextBlock;
|
||||
} else if(statement instanceof StatementConditionalJump) {
|
||||
currentBlock.addStatement(statement);
|
||||
StatementConditionalJump statementConditionalJump = (StatementConditionalJump) statement;
|
||||
ControlFlowBlock jmpBlock = getOrCreateBlock(statementConditionalJump.getDestination());
|
||||
ControlFlowBlock nextBlock = getOrCreateBlock(symbolTable.newIntermediateJumpLabel());
|
||||
ControlFlowBlock nextBlock = getOrCreateBlock(symbolTable.addLabelIntermediate());
|
||||
currentBlock.setDefaultSuccessor(nextBlock);
|
||||
currentBlock.setConditionalSuccessor(jmpBlock);
|
||||
nextBlock.addPredecessor(currentBlock);
|
||||
|
@ -4,17 +4,34 @@ import dk.camelot64.kickc.parser.KickCBaseVisitor;
|
||||
import dk.camelot64.kickc.parser.KickCParser;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
|
||||
/** Generates program SSA form by visiting the ANTLR4 parse tree*/
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* Generates program SSA form by visiting the ANTLR4 parse tree
|
||||
*/
|
||||
public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
private SymbolTable symbolTable;
|
||||
private SymbolTable programSymbols;
|
||||
private Stack<SymbolTable> symbolsStack;
|
||||
private StatementSequence sequence;
|
||||
|
||||
public Pass1GenerateStatementSequence() {
|
||||
this.symbolTable = new SymbolTable();
|
||||
this.programSymbols = new SymbolTable();
|
||||
this.symbolsStack = new Stack<>();
|
||||
symbolsStack.push(programSymbols);
|
||||
this.sequence = new StatementSequence();
|
||||
}
|
||||
|
||||
public SymbolTable getProgramSymbols() {
|
||||
return programSymbols;
|
||||
}
|
||||
|
||||
private SymbolTable getCurrentSymbols() {
|
||||
return symbolsStack.peek();
|
||||
}
|
||||
|
||||
public void generate(KickCParser.FileContext file) {
|
||||
this.visit(file);
|
||||
}
|
||||
@ -27,7 +44,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
@Override
|
||||
public Void visitStmtSeq(KickCParser.StmtSeqContext ctx) {
|
||||
for(int i=0; i<ctx.getChildCount(); i++) {
|
||||
for (int i = 0; i < ctx.getChildCount(); i++) {
|
||||
this.visit(ctx.stmt(i));
|
||||
}
|
||||
return null;
|
||||
@ -48,27 +65,27 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
@Override
|
||||
public Void visitStmtIfElse(KickCParser.StmtIfElseContext ctx) {
|
||||
RValue rValue = (RValue) this.visit(ctx.expr());
|
||||
Label ifJumpLabel = symbolTable.newIntermediateJumpLabel();
|
||||
Label elseJumpLabel = symbolTable.newIntermediateJumpLabel();
|
||||
Label ifJumpLabel = getCurrentSymbols().addLabelIntermediate();
|
||||
Label elseJumpLabel = getCurrentSymbols().addLabelIntermediate();
|
||||
Statement ifJmpStmt = new StatementConditionalJump(rValue, ifJumpLabel);
|
||||
sequence.addStatement(ifJmpStmt);
|
||||
Statement elseJmpStmt = new StatementJump(elseJumpLabel);
|
||||
sequence.addStatement(elseJmpStmt);
|
||||
StatementJumpTarget ifJumpTarget = new StatementJumpTarget(ifJumpLabel);
|
||||
StatementLabel ifJumpTarget = new StatementLabel(ifJumpLabel);
|
||||
sequence.addStatement(ifJumpTarget);
|
||||
this.visit(ctx.stmt(0));
|
||||
KickCParser.StmtContext elseStmt = ctx.stmt(1);
|
||||
if(elseStmt!=null) {
|
||||
Label endJumpLabel = symbolTable.newIntermediateJumpLabel();
|
||||
if (elseStmt != null) {
|
||||
Label endJumpLabel = getCurrentSymbols().addLabelIntermediate();
|
||||
Statement endJmpStmt = new StatementJump(endJumpLabel);
|
||||
sequence.addStatement(endJmpStmt);
|
||||
StatementJumpTarget elseJumpTarget = new StatementJumpTarget(elseJumpLabel);
|
||||
StatementLabel elseJumpTarget = new StatementLabel(elseJumpLabel);
|
||||
sequence.addStatement(elseJumpTarget);
|
||||
this.visit(elseStmt);
|
||||
StatementJumpTarget endJumpTarget = new StatementJumpTarget(endJumpLabel);
|
||||
StatementLabel endJumpTarget = new StatementLabel(endJumpLabel);
|
||||
sequence.addStatement(endJumpTarget);
|
||||
} else {
|
||||
StatementJumpTarget elseJumpTarget = new StatementJumpTarget(elseJumpLabel);
|
||||
} else {
|
||||
StatementLabel elseJumpTarget = new StatementLabel(elseJumpLabel);
|
||||
sequence.addStatement(elseJumpTarget);
|
||||
}
|
||||
return null;
|
||||
@ -76,30 +93,30 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
@Override
|
||||
public Void visitStmtWhile(KickCParser.StmtWhileContext ctx) {
|
||||
Label beginJumpLabel = symbolTable.newIntermediateJumpLabel();
|
||||
Label doJumpLabel = symbolTable.newIntermediateJumpLabel();
|
||||
Label endJumpLabel = symbolTable.newIntermediateJumpLabel();
|
||||
StatementJumpTarget beginJumpTarget = new StatementJumpTarget(beginJumpLabel);
|
||||
Label beginJumpLabel = getCurrentSymbols().addLabelIntermediate();
|
||||
Label doJumpLabel = getCurrentSymbols().addLabelIntermediate();
|
||||
Label endJumpLabel = getCurrentSymbols().addLabelIntermediate();
|
||||
StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel);
|
||||
sequence.addStatement(beginJumpTarget);
|
||||
RValue rValue = (RValue) this.visit(ctx.expr());
|
||||
Statement doJmpStmt = new StatementConditionalJump(rValue, doJumpLabel);
|
||||
sequence.addStatement(doJmpStmt);
|
||||
Statement endJmpStmt = new StatementJump(endJumpLabel);
|
||||
sequence.addStatement(endJmpStmt);
|
||||
StatementJumpTarget doJumpTarget = new StatementJumpTarget(doJumpLabel);
|
||||
StatementLabel doJumpTarget = new StatementLabel(doJumpLabel);
|
||||
sequence.addStatement(doJumpTarget);
|
||||
this.visit(ctx.stmt());
|
||||
Statement beginJmpStmt = new StatementJump(beginJumpLabel);
|
||||
sequence.addStatement(beginJmpStmt);
|
||||
StatementJumpTarget endJumpTarget = new StatementJumpTarget(endJumpLabel);
|
||||
StatementLabel endJumpTarget = new StatementLabel(endJumpLabel);
|
||||
sequence.addStatement(endJumpTarget);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitStmtDoWhile(KickCParser.StmtDoWhileContext ctx) {
|
||||
Label beginJumpLabel = symbolTable.newIntermediateJumpLabel();
|
||||
StatementJumpTarget beginJumpTarget = new StatementJumpTarget(beginJumpLabel);
|
||||
Label beginJumpLabel = getCurrentSymbols().addLabelIntermediate();
|
||||
StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel);
|
||||
sequence.addStatement(beginJumpTarget);
|
||||
this.visit(ctx.stmt());
|
||||
RValue rValue = (RValue) this.visit(ctx.expr());
|
||||
@ -110,22 +127,55 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
@Override
|
||||
public Void visitStmtFunction(KickCParser.StmtFunctionContext ctx) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
SymbolType type = (SymbolType) visit(ctx.typeDecl());
|
||||
String name = ctx.NAME().getText();
|
||||
Procedure procedure = getCurrentSymbols().addProcedure(name, type);
|
||||
symbolsStack.push(procedure);
|
||||
List<Variable> parameterList = (List<Variable>) this.visit(ctx.parameterListDecl());
|
||||
procedure.setParameters(parameterList);
|
||||
sequence.addStatement(new StatementProcedure(procedure));
|
||||
this.visit(ctx.stmtSeq());
|
||||
symbolsStack.pop();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Variable> visitParameterListDecl(KickCParser.ParameterListDeclContext ctx) {
|
||||
ArrayList<Variable> parameterDecls = new ArrayList<>();
|
||||
for (KickCParser.ParameterDeclContext parameterDeclCtx: ctx.parameterDecl()) {
|
||||
Variable parameterDecl = (Variable) this.visit(parameterDeclCtx);
|
||||
parameterDecls.add(parameterDecl);
|
||||
}
|
||||
return parameterDecls;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Variable visitParameterDecl(KickCParser.ParameterDeclContext ctx) {
|
||||
SymbolType type = (SymbolType) this.visit(ctx.typeDecl());
|
||||
VariableUnversioned param = new VariableUnversioned(ctx.NAME().getText(), getCurrentSymbols(), type);
|
||||
return param;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitStmtReturn(KickCParser.StmtReturnContext ctx) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
KickCParser.ExprContext exprCtx = ctx.expr();
|
||||
RValue rValue = null;
|
||||
if (exprCtx != null) {
|
||||
rValue = (RValue) this.visit(exprCtx);
|
||||
}
|
||||
Statement stmt = new StatementReturn(rValue);
|
||||
sequence.addStatement(stmt);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitStmtDeclaration(KickCParser.StmtDeclarationContext ctx) {
|
||||
if(ctx.getChild(0).getText().equals("const")) {
|
||||
System.out.println("Const!"+ctx.getText());
|
||||
if (ctx.getChild(0).getText().equals("const")) {
|
||||
System.out.println("Const!" + ctx.getText());
|
||||
}
|
||||
SymbolType type = (SymbolType)visit(ctx.typeDecl());
|
||||
VariableUnversioned lValue = symbolTable.newVariableDeclaration(ctx.NAME().getText(), type);
|
||||
if(ctx.initializer()!=null) {
|
||||
SymbolType type = (SymbolType) visit(ctx.typeDecl());
|
||||
VariableUnversioned lValue = getCurrentSymbols().addVariable(ctx.NAME().getText(), type);
|
||||
if (ctx.initializer() != null) {
|
||||
RValue rValue = (RValue) visit(ctx.initializer());
|
||||
Statement stmt = new StatementAssignment(lValue, rValue);
|
||||
sequence.addStatement(stmt);
|
||||
@ -144,7 +194,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
@Override
|
||||
public LValue visitLvalueName(KickCParser.LvalueNameContext ctx) {
|
||||
return symbolTable.newVariableUsage(ctx.NAME().getText());
|
||||
return getCurrentSymbols().getVariable(ctx.NAME().getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -155,9 +205,9 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
@Override
|
||||
public LValue visitLvaluePtr(KickCParser.LvaluePtrContext ctx) {
|
||||
LValue lval = (LValue) visit(ctx.lvalue());
|
||||
if(lval instanceof Variable) {
|
||||
if (lval instanceof Variable) {
|
||||
return new PointerDereferenceSimple((Variable) lval);
|
||||
} else {
|
||||
} else {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
}
|
||||
@ -194,10 +244,10 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
public SymbolType visitTypeArray(KickCParser.TypeArrayContext ctx) {
|
||||
SymbolType elementType = (SymbolType) visit(ctx.typeDecl());
|
||||
Constant size = ParseTreeConstantEvaluator.evaluate(ctx.expr());
|
||||
if(size instanceof ConstantInteger) {
|
||||
if (size instanceof ConstantInteger) {
|
||||
return new SymbolTypeArray(elementType, ((ConstantInteger) size).getNumber());
|
||||
} else {
|
||||
throw new RuntimeException("Array size not a constant integer "+ctx.getText());
|
||||
throw new RuntimeException("Array size not a constant integer " + ctx.getText());
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,7 +259,21 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
@Override
|
||||
public Object visitExprCall(KickCParser.ExprCallContext ctx) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
Label label = new Label(ctx.NAME().getText(), getCurrentSymbols(), false);
|
||||
List<RValue> parameters = (List<RValue>) this.visit(ctx.parameterList());
|
||||
VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate();
|
||||
sequence.addStatement(new StatementCallLValue(tmpVar, label, parameters));
|
||||
return tmpVar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RValue> visitParameterList(KickCParser.ParameterListContext ctx) {
|
||||
List<RValue> parameters = new ArrayList<>();
|
||||
for (KickCParser.ExprContext exprContext : ctx.expr()) {
|
||||
RValue param = (RValue) this.visit(exprContext);
|
||||
parameters.add(param);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -217,7 +281,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
RValue array = (LValue) visit(ctx.expr(0));
|
||||
RValue index = (RValue) visit(ctx.expr(1));
|
||||
Operator operator = new Operator("*idx");
|
||||
VariableIntermediate tmpVar = symbolTable.newIntermediateAssignment();
|
||||
VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate();
|
||||
Statement stmt = new StatementAssignment(tmpVar, array, operator, index);
|
||||
sequence.addStatement(stmt);
|
||||
return tmpVar;
|
||||
@ -226,7 +290,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
@Override
|
||||
public RValue visitExprNumber(KickCParser.ExprNumberContext ctx) {
|
||||
Number number = NumberParser.parseLiteral(ctx.getText());
|
||||
if(number instanceof Integer) {
|
||||
if (number instanceof Integer) {
|
||||
return new ConstantInteger((Integer) number);
|
||||
} else {
|
||||
return new ConstantDouble((Double) number);
|
||||
@ -244,14 +308,13 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
return new ConstantBool(Boolean.valueOf(bool));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public RValue visitExprBinary(KickCParser.ExprBinaryContext ctx) {
|
||||
RValue left = (RValue) this.visit(ctx.expr(0));
|
||||
RValue right = (RValue) this.visit(ctx.expr(1));
|
||||
String op = ((TerminalNode)ctx.getChild(1)).getSymbol().getText();
|
||||
String op = ((TerminalNode) ctx.getChild(1)).getSymbol().getText();
|
||||
Operator operator = new Operator(op);
|
||||
VariableIntermediate tmpVar = symbolTable.newIntermediateAssignment();
|
||||
VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate();
|
||||
Statement stmt = new StatementAssignment(tmpVar, left, operator, right);
|
||||
sequence.addStatement(stmt);
|
||||
return tmpVar;
|
||||
@ -260,9 +323,9 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
@Override
|
||||
public RValue visitExprUnary(KickCParser.ExprUnaryContext ctx) {
|
||||
RValue child = (RValue) this.visit(ctx.expr());
|
||||
String op = ((TerminalNode)ctx.getChild(0)).getSymbol().getText();
|
||||
String op = ((TerminalNode) ctx.getChild(0)).getSymbol().getText();
|
||||
Operator operator = new Operator(op);
|
||||
VariableIntermediate tmpVar = symbolTable.newIntermediateAssignment();
|
||||
VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate();
|
||||
Statement stmt = new StatementAssignment(tmpVar, operator, child);
|
||||
sequence.addStatement(stmt);
|
||||
return tmpVar;
|
||||
@ -275,15 +338,11 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
@Override
|
||||
public RValue visitExprId(KickCParser.ExprIdContext ctx) {
|
||||
return symbolTable.newVariableUsage(ctx.NAME().getText());
|
||||
return getCurrentSymbols().getVariable(ctx.NAME().getText());
|
||||
}
|
||||
|
||||
public StatementSequence getSequence() {
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public SymbolTable getSymbols() {
|
||||
return this.symbolTable;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public class Pass3CodeGeneration {
|
||||
// Generate entry points (if needed)
|
||||
genBlockEntryPoints(asm, block);
|
||||
// Generate label
|
||||
asm.addLabel(block.getLabel().getName().replace('@', 'B'));
|
||||
asm.addLabel(block.getLabel().getLocalName().replace('@', 'B'));
|
||||
// Generate statements
|
||||
genStatements(asm, block);
|
||||
// Generate exit
|
||||
@ -32,7 +32,7 @@ public class Pass3CodeGeneration {
|
||||
if (defaultSuccessor.hasPhiStatements()) {
|
||||
genBlockPhiTransition(asm, block, defaultSuccessor);
|
||||
}
|
||||
asm.addInstruction("JMP", AsmAddressingMode.ABS, defaultSuccessor.getLabel().getName().replace('@', 'B'));
|
||||
asm.addInstruction("JMP", AsmAddressingMode.ABS, defaultSuccessor.getLabel().getLocalName().replace('@', 'B'));
|
||||
}
|
||||
}
|
||||
return asm;
|
||||
@ -84,14 +84,14 @@ public class Pass3CodeGeneration {
|
||||
for (ControlFlowBlock predecessor : block.getPredecessors()) {
|
||||
if (block.equals(predecessor.getConditionalSuccessor())) {
|
||||
genBlockPhiTransition(asm, predecessor, block);
|
||||
asm.addInstruction("JMP", AsmAddressingMode.ABS, block.getLabel().getName().replace('@', 'B'));
|
||||
asm.addInstruction("JMP", AsmAddressingMode.ABS, block.getLabel().getLocalName().replace('@', 'B'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void genBlockPhiTransition(AsmProgram asm, ControlFlowBlock fromBlock, ControlFlowBlock toBlock) {
|
||||
asm.addLabel((toBlock.getLabel().getName() + "_from_" + fromBlock.getLabel().getName()).replace('@', 'B'));
|
||||
asm.addLabel((toBlock.getLabel().getLocalName() + "_from_" + fromBlock.getLabel().getLocalName()).replace('@', 'B'));
|
||||
for (Statement statement : toBlock.getStatements()) {
|
||||
if (!(statement instanceof StatementPhi)) {
|
||||
// No more phi statements to handle
|
||||
|
@ -30,6 +30,14 @@ public class PassTypeInference {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(statement instanceof StatementCallLValue) {
|
||||
StatementCallLValue callLValue = (StatementCallLValue) statement;
|
||||
LValue lValue = callLValue.getLValue();
|
||||
if(lValue instanceof Variable) {
|
||||
Label label = callLValue.getCallLabel();
|
||||
Procedure procedure = symbols.getProcedure(label.getLocalName());
|
||||
((Variable) lValue).setInferredType(procedure.getReturnType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
71
src/dk/camelot64/kickc/icl/Procedure.java
Normal file
71
src/dk/camelot64/kickc/icl/Procedure.java
Normal file
@ -0,0 +1,71 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** Symbol describing a procedure/function */
|
||||
public class Procedure extends SymbolTable {
|
||||
|
||||
private final SymbolType returnType;
|
||||
private List<Variable> parameters;
|
||||
|
||||
public Procedure(String name, SymbolType returnType, SymbolTable parentScope) {
|
||||
super(name, new SymbolTypeProcedure(returnType), parentScope);
|
||||
this.returnType = returnType;
|
||||
}
|
||||
|
||||
public void setParameters(List<Variable> parameters) {
|
||||
this.parameters = parameters;
|
||||
for (Variable parameter : parameters) {
|
||||
add(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
public Label getLabel() {
|
||||
return new Label(getLocalName(), this, false);
|
||||
}
|
||||
|
||||
public SymbolType getReturnType() {
|
||||
return returnType;
|
||||
}
|
||||
|
||||
public List<Variable> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullName() {
|
||||
return super.getFullName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypedName() {
|
||||
StringBuilder res = new StringBuilder();
|
||||
res.append("("+getType().getTypeName() + ") ");
|
||||
res.append(getFullName());
|
||||
res.append("(");
|
||||
boolean first = true;
|
||||
if(parameters!=null) {
|
||||
for (Variable parameter : parameters) {
|
||||
if (!first) res.append(" , ");
|
||||
first = false;
|
||||
res.append(parameter.getTypedName());
|
||||
}
|
||||
}
|
||||
res.append(")");
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
public String getSymbolTableContents() {
|
||||
StringBuilder res = new StringBuilder();
|
||||
res.append(getTypedName());
|
||||
res.append("\n");
|
||||
res.append(super.getSymbolTableContents());
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getTypedName();
|
||||
}
|
||||
|
||||
}
|
@ -8,7 +8,7 @@ package dk.camelot64.kickc.icl;
|
||||
* <br>
|
||||
* <i> lValue := rValue1 <operator> rValue2 </i>
|
||||
*/
|
||||
public class StatementAssignment implements Statement {
|
||||
public class StatementAssignment implements StatementLValue {
|
||||
|
||||
/** The variable being assigned a value by the statement. */
|
||||
private LValue lValue;
|
||||
|
60
src/dk/camelot64/kickc/icl/StatementCallLValue.java
Normal file
60
src/dk/camelot64/kickc/icl/StatementCallLValue.java
Normal file
@ -0,0 +1,60 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Call procedure in SSA form.
|
||||
* <br>
|
||||
* <i> X<sub>i</sub> := call label param1 param2 param3 ... </i>
|
||||
*/
|
||||
public class StatementCallLValue implements StatementLValue {
|
||||
|
||||
/** The variable being assigned a value by the call. */
|
||||
private LValue lValue;
|
||||
private Label callLabel;
|
||||
private List<RValue> parameters;
|
||||
|
||||
public StatementCallLValue(LValue lValue, Label callLabel, List<RValue> parameters) {
|
||||
this.lValue = lValue;
|
||||
this.callLabel = callLabel;
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public LValue getLValue() {
|
||||
return lValue;
|
||||
}
|
||||
|
||||
public void setLValue(LValue lValue) {
|
||||
this.lValue = lValue;
|
||||
}
|
||||
|
||||
public Label getCallLabel() {
|
||||
return callLabel;
|
||||
}
|
||||
|
||||
public List<RValue> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public int getNumParameters() {
|
||||
return parameters.size();
|
||||
}
|
||||
|
||||
public RValue getParameter(int idx) {
|
||||
return parameters.get(idx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder res = new StringBuilder();
|
||||
res.append(lValue);
|
||||
res.append(" ← ");
|
||||
res.append("call ");
|
||||
res.append(callLabel+" ");
|
||||
for (RValue parameter : parameters) {
|
||||
res.append(parameter+" ");
|
||||
}
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
}
|
@ -72,7 +72,7 @@ public class StatementConditionalJump implements Statement {
|
||||
}
|
||||
out.append(rValue2);
|
||||
out.append(") goto ");
|
||||
out.append(destination.getName());
|
||||
out.append(destination.getLocalName());
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ public class StatementJump implements Statement {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "goto "+destination.getName();
|
||||
return "goto "+destination.getLocalName();
|
||||
}
|
||||
|
||||
public void setDestination(Label destination) {
|
||||
|
12
src/dk/camelot64/kickc/icl/StatementLValue.java
Normal file
12
src/dk/camelot64/kickc/icl/StatementLValue.java
Normal file
@ -0,0 +1,12 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/**
|
||||
* Single Static Assignment Form Statement with an LValuie - that is a statement assigning a value to a variable.
|
||||
*/
|
||||
public interface StatementLValue extends Statement {
|
||||
|
||||
LValue getLValue();
|
||||
|
||||
void setLValue(LValue lValue);
|
||||
|
||||
}
|
@ -3,11 +3,11 @@ package dk.camelot64.kickc.icl;
|
||||
/**
|
||||
* Single Static Assignment Form Statement Jump target.
|
||||
*/
|
||||
public class StatementJumpTarget implements Statement {
|
||||
public class StatementLabel implements Statement {
|
||||
|
||||
private Label label;
|
||||
|
||||
public StatementJumpTarget(Label label) {
|
||||
public StatementLabel(Label label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ public class StatementJumpTarget implements Statement {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return label+":";
|
||||
return label.getFullName()+":";
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ import java.util.List;
|
||||
* <br>
|
||||
* <i> X<sub>i</sub> := phi(X<sub>j</sub>, X<sub>k</sub>, ...) </i>
|
||||
*/
|
||||
public class StatementPhi implements Statement {
|
||||
public class StatementPhi implements StatementLValue {
|
||||
|
||||
/** The versioned variable being assigned a value by the statement. */
|
||||
private VariableVersion lValue;
|
||||
@ -57,14 +57,14 @@ public class StatementPhi implements Statement {
|
||||
return lValue;
|
||||
}
|
||||
|
||||
public void setLValue(Variable lValue) {
|
||||
@Override
|
||||
public void setLValue(LValue lValue) {
|
||||
if(!(lValue instanceof VariableVersion)) {
|
||||
throw new RuntimeException("Error modifying phi-statement lValue "+this.lValue+". Attempt to set to non-versioned variable "+lValue);
|
||||
}
|
||||
this.lValue = (VariableVersion) lValue;
|
||||
}
|
||||
|
||||
|
||||
public void addPreviousVersion(ControlFlowBlock block, VariableVersion symbol) {
|
||||
previousVersions.add(new PreviousSymbol(block, symbol));
|
||||
}
|
||||
@ -78,7 +78,7 @@ public class StatementPhi implements Statement {
|
||||
StringBuilder out = new StringBuilder();
|
||||
out.append(lValue + " ← " + "phi(");
|
||||
for (PreviousSymbol previousSymbol : previousVersions) {
|
||||
out.append(" "+previousSymbol.getBlock().getLabel().getName()+"/"+previousSymbol.getRValue());
|
||||
out.append(" "+previousSymbol.getBlock().getLabel().getLocalName()+"/"+previousSymbol.getRValue());
|
||||
}
|
||||
out.append(" )");
|
||||
return out.toString();
|
||||
|
21
src/dk/camelot64/kickc/icl/StatementProcedure.java
Normal file
21
src/dk/camelot64/kickc/icl/StatementProcedure.java
Normal file
@ -0,0 +1,21 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/** Procedure declaration in SSA */
|
||||
public class StatementProcedure implements Statement {
|
||||
|
||||
private Procedure procedure;
|
||||
|
||||
public StatementProcedure(Procedure procedure) {
|
||||
this.procedure = procedure;
|
||||
}
|
||||
|
||||
public Procedure getProcedure() {
|
||||
return procedure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "proc "+procedure.toString()+":";
|
||||
}
|
||||
|
||||
}
|
24
src/dk/camelot64/kickc/icl/StatementReturn.java
Normal file
24
src/dk/camelot64/kickc/icl/StatementReturn.java
Normal file
@ -0,0 +1,24 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/**
|
||||
* Return Statement inside procedure in Single Static Assignment Form.
|
||||
*/
|
||||
public class StatementReturn implements Statement {
|
||||
|
||||
/** Return value. May be null if not returning a value. */
|
||||
private RValue value;
|
||||
|
||||
public StatementReturn(RValue value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public RValue getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "return "+(value==null?"":value);
|
||||
}
|
||||
|
||||
}
|
@ -20,7 +20,7 @@ public class StatementSequence {
|
||||
public String toString() {
|
||||
StringBuffer out = new StringBuffer();
|
||||
for (Statement statement : statements) {
|
||||
if(!(statement instanceof StatementJumpTarget)) {
|
||||
if(!(statement instanceof StatementLabel)) {
|
||||
out.append(" ");
|
||||
}
|
||||
out.append(statement.toString()+"\n");
|
||||
|
@ -3,8 +3,15 @@ package dk.camelot64.kickc.icl;
|
||||
/** A Symbol (variable, jump label, etc.) */
|
||||
public interface Symbol extends Value {
|
||||
|
||||
public String getName();
|
||||
String getLocalName();
|
||||
|
||||
String getFullName();
|
||||
|
||||
String getTypedName();
|
||||
|
||||
SymbolType getType();
|
||||
|
||||
SymbolTable getScope();
|
||||
|
||||
public SymbolType getType();
|
||||
|
||||
}
|
||||
|
@ -1,122 +1,181 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
import sun.jvm.hotspot.debugger.cdbg.Sym;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Manages symbols (variables, labels)
|
||||
*/
|
||||
public class SymbolTable {
|
||||
public class SymbolTable implements Symbol {
|
||||
|
||||
private String name;
|
||||
private SymbolType type;
|
||||
private Map<String, Symbol> symbols;
|
||||
private int intermediateVarCount = 0;
|
||||
private int intermediateLabelCount = 1;
|
||||
private RegisterAllocation allocation;
|
||||
private SymbolTable parentScope;
|
||||
|
||||
public SymbolTable(String name, SymbolType type, SymbolTable parentScope) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.parentScope = parentScope;
|
||||
this.symbols = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
public SymbolTable() {
|
||||
this.name = "";
|
||||
this.type = new SymbolTypeProgram();
|
||||
this.parentScope = null;
|
||||
this.symbols = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocalName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullName() {
|
||||
return getFullName(this);
|
||||
}
|
||||
|
||||
public static String getFullName(Symbol symbol) {
|
||||
if(symbol.getScope()!=null) {
|
||||
String scopeName = symbol.getScope().getFullName();
|
||||
if(scopeName.length()>0) {
|
||||
return scopeName+"::"+symbol.getLocalName();
|
||||
}
|
||||
}
|
||||
return symbol.getLocalName();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SymbolTable getScope() {
|
||||
return parentScope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypedName() {
|
||||
return "(" + getType().getTypeName() + ") " + getFullName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Symbol add(Symbol symbol) {
|
||||
if (symbols.get(symbol.getLocalName()) != null) {
|
||||
throw new RuntimeException("Symbol already declared " + symbol.getLocalName());
|
||||
}
|
||||
symbols.put(symbol.getLocalName(), symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public void remove(Symbol symbol) {
|
||||
symbols.remove(symbol.getLocalName());
|
||||
}
|
||||
|
||||
public VariableUnversioned addVariable(String name, SymbolType type) {
|
||||
VariableUnversioned symbol = new VariableUnversioned(name, this, type);
|
||||
add(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public VariableIntermediate addVariableIntermediate() {
|
||||
String name = "$" + intermediateVarCount++;
|
||||
VariableIntermediate symbol = new VariableIntermediate(name, this, SymbolTypeBasic.VAR);
|
||||
add(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public Variable getVariable(String name) {
|
||||
return (Variable) symbols.get(name);
|
||||
}
|
||||
|
||||
public Collection<Variable> getAllVariables() {
|
||||
Collection<Variable> vars = new ArrayList<>();
|
||||
for (Symbol symbol : symbols.values()) {
|
||||
if(symbol instanceof Variable) {
|
||||
if (symbol instanceof Variable) {
|
||||
vars.add((Variable) symbol);
|
||||
}
|
||||
}
|
||||
return vars;
|
||||
}
|
||||
|
||||
private Symbol addSymbol(Symbol symbol) {
|
||||
if(symbols.get(symbol.getName())!=null) {
|
||||
throw new RuntimeException("Symbol already declared "+symbol.getName());
|
||||
public Label addLabel(String name) {
|
||||
Label symbol = new Label(name, this, false);
|
||||
add(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public Label addLabelIntermediate() {
|
||||
String name = "@" + intermediateLabelCount++;
|
||||
Label symbol = new Label(name, this, true);
|
||||
add(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
|
||||
public Procedure addProcedure(String name, SymbolType type) {
|
||||
Symbol symbol = symbols.get(name);
|
||||
if (symbol != null) {
|
||||
throw new RuntimeException("Error! Symbol already defined " + symbol);
|
||||
}
|
||||
symbols.put(symbol.getName(), symbol);
|
||||
return symbol;
|
||||
Procedure procedure = new Procedure(name, type, this);
|
||||
add(procedure);
|
||||
return procedure;
|
||||
}
|
||||
|
||||
public VariableUnversioned newVariableDeclaration(String name, SymbolType type) {
|
||||
VariableUnversioned symbol = new VariableUnversioned(name, type);
|
||||
addSymbol(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public VariableUnversioned newVariableDeclaration(String name, String type) {
|
||||
SymbolType symbolType = SymbolTypeBasic.get(type);
|
||||
VariableUnversioned symbol = new VariableUnversioned(name, symbolType);
|
||||
addSymbol(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public VariableUnversioned newVariableUsage(String name) {
|
||||
return (VariableUnversioned) symbols.get(name);
|
||||
}
|
||||
|
||||
public VariableIntermediate newIntermediateAssignment() {
|
||||
String name = "$"+intermediateVarCount++;
|
||||
VariableIntermediate symbol = new VariableIntermediate(name, SymbolTypeBasic.VAR);
|
||||
addSymbol(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public Label newNamedJumpLabel(String name) {
|
||||
Label symbol = new Label(name, false);
|
||||
addSymbol(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public Label newIntermediateJumpLabel() {
|
||||
String name = "@"+ intermediateLabelCount++;
|
||||
Label symbol = new Label(name, true);
|
||||
addSymbol(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public void remove(Symbol symbol) {
|
||||
symbols.remove(symbol.getName());
|
||||
public Procedure getProcedure(String name) {
|
||||
Symbol symbol = symbols.get(name);
|
||||
if (symbol != null && symbol instanceof Procedure) {
|
||||
return (Procedure) symbol;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public VariableVersion createVersion(VariableUnversioned symbol) {
|
||||
VariableVersion version = new VariableVersion(symbol, symbol.getNextVersionNumber());
|
||||
symbols.put(version.getName(), version);
|
||||
symbols.put(version.getLocalName(), version);
|
||||
return version;
|
||||
}
|
||||
|
||||
public Variable getVariable(String name) {
|
||||
return (Variable) symbols.get(name);
|
||||
}
|
||||
|
||||
public void setAllocation(RegisterAllocation allocation) {
|
||||
this.allocation = allocation;
|
||||
}
|
||||
|
||||
public RegisterAllocation.Register getRegister(Variable variable) {
|
||||
RegisterAllocation.Register register = null;
|
||||
if(allocation!=null) {
|
||||
if (allocation != null) {
|
||||
register = allocation.getRegister(variable);
|
||||
}
|
||||
return register;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer out = new StringBuffer();
|
||||
public String getSymbolTableContents() {
|
||||
StringBuilder res = new StringBuilder();
|
||||
Set<String> names = symbols.keySet();
|
||||
List<String> sortedNames = new ArrayList<>(names);
|
||||
Collections.sort(sortedNames);
|
||||
for (String name : sortedNames) {
|
||||
Symbol symbol = symbols.get(name);
|
||||
out.append(symbol.toString());
|
||||
if(symbol instanceof Variable) {
|
||||
if (symbol instanceof SymbolTable) {
|
||||
res.append(((SymbolTable) symbol).getSymbolTableContents());
|
||||
} else {
|
||||
res.append(symbol.toString());
|
||||
}
|
||||
if (symbol instanceof Variable) {
|
||||
RegisterAllocation.Register register = getRegister((Variable) symbol);
|
||||
if(register!=null) {
|
||||
out.append(" "+register);
|
||||
if (register != null) {
|
||||
res.append(" " + register);
|
||||
}
|
||||
}
|
||||
out.append("\n");
|
||||
res.append("\n");
|
||||
}
|
||||
return out.toString();
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,7 +6,9 @@ public enum SymbolTypeBasic implements SymbolType {
|
||||
WORD("word"),
|
||||
STRING("string"),
|
||||
BOOLEAN("boolean"),
|
||||
// A label
|
||||
LABEL("label"),
|
||||
// Unresolved type. Will be infered later
|
||||
VAR("var");
|
||||
|
||||
private String typeName;
|
||||
|
20
src/dk/camelot64/kickc/icl/SymbolTypeProcedure.java
Normal file
20
src/dk/camelot64/kickc/icl/SymbolTypeProcedure.java
Normal file
@ -0,0 +1,20 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/** A function returning another type */
|
||||
public class SymbolTypeProcedure implements SymbolType {
|
||||
|
||||
private SymbolType returnType;
|
||||
|
||||
public SymbolTypeProcedure(SymbolType returnType) {
|
||||
this.returnType = returnType;
|
||||
}
|
||||
|
||||
public SymbolType getReturnType() {
|
||||
return returnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return returnType.getTypeName() + "()";
|
||||
}
|
||||
}
|
14
src/dk/camelot64/kickc/icl/SymbolTypeProgram.java
Normal file
14
src/dk/camelot64/kickc/icl/SymbolTypeProgram.java
Normal file
@ -0,0 +1,14 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/** A program */
|
||||
public class SymbolTypeProgram implements SymbolType {
|
||||
|
||||
public SymbolTypeProgram() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return "PROGRAM";
|
||||
}
|
||||
}
|
@ -1,27 +1,51 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/** A Symbol (variable, jump label, etc.) */
|
||||
public abstract class Variable implements Symbol, RValue, LValue {
|
||||
/**
|
||||
* A Symbol (variable, jump label, etc.)
|
||||
*/
|
||||
public abstract class Variable implements Symbol, RValue, LValue {
|
||||
|
||||
/** The name of the symbol. */
|
||||
/**
|
||||
* The name of the symbol.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/** The type of the symbol. VAR means tha type is unknown, and has not been inferred yet. */
|
||||
/**
|
||||
* Scope
|
||||
*/
|
||||
private SymbolTable scope;
|
||||
|
||||
/**
|
||||
* The type of the symbol. VAR means tha type is unknown, and has not been inferred yet.
|
||||
*/
|
||||
private SymbolType type;
|
||||
|
||||
/** true if the symbol type is infered (not declared) */
|
||||
/**
|
||||
* true if the symbol type is infered (not declared)
|
||||
*/
|
||||
private boolean inferredType;
|
||||
|
||||
public Variable(String name, SymbolType type) {
|
||||
public Variable(String name, SymbolTable scope, SymbolType type) {
|
||||
this.name = name;
|
||||
this.scope = scope;
|
||||
this.type = type;
|
||||
this.inferredType = false;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
public String getLocalName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullName() {
|
||||
return SymbolTable.getFullName(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypedName() {
|
||||
return "(" + type.getTypeName() + (inferredType ? "~" : "") + ") " + getFullName();
|
||||
}
|
||||
|
||||
public SymbolType getType() {
|
||||
return type;
|
||||
}
|
||||
@ -39,24 +63,34 @@ public abstract class Variable implements Symbol, RValue, LValue {
|
||||
|
||||
public abstract boolean isIntermediate();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "("+type.getTypeName() + (inferredType ?"~":"") + ") "+name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Variable symbol = (Variable) o;
|
||||
if (!name.equals(symbol.name)) return false;
|
||||
return type == symbol.type;
|
||||
|
||||
Variable variable = (Variable) o;
|
||||
|
||||
if (inferredType != variable.inferredType) return false;
|
||||
if (!name.equals(variable.name)) return false;
|
||||
if (scope != null ? !scope.equals(variable.scope) : variable.scope != null) return false;
|
||||
return type.equals(variable.type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = name.hashCode();
|
||||
result = 31 * result + (scope != null ? scope.hashCode() : 0);
|
||||
result = 31 * result + type.hashCode();
|
||||
result = 31 * result + (inferredType ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getTypedName();
|
||||
}
|
||||
|
||||
public SymbolTable getScope() {
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/** A Symbol (variable, jump label, etc.) */
|
||||
/**
|
||||
* A Symbol (variable, jump label, etc.)
|
||||
*/
|
||||
public class VariableIntermediate extends Variable {
|
||||
|
||||
public VariableIntermediate(String name, SymbolType type) {
|
||||
super(name, type);
|
||||
public VariableIntermediate(String name, SymbolTable scope, SymbolType type) {
|
||||
super(name, scope, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,17 +1,23 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/** A Symbol (variable, jump label, etc.) */
|
||||
/**
|
||||
* A Symbol (variable, jump label, etc.)
|
||||
*/
|
||||
public class VariableUnversioned extends Variable {
|
||||
|
||||
/** The number of the next version */
|
||||
/**
|
||||
* The number of the next version
|
||||
*/
|
||||
private Integer nextVersionNumber;
|
||||
|
||||
public VariableUnversioned(String name, SymbolType type) {
|
||||
super(name, type);
|
||||
this.nextVersionNumber = 0;
|
||||
public VariableUnversioned(String name, SymbolTable scope, SymbolType type) {
|
||||
super(name, scope, type);
|
||||
this.nextVersionNumber = 0;
|
||||
}
|
||||
|
||||
/** Get the version number of the next version. (if anyone versions the symbol). */
|
||||
/**
|
||||
* Get the version number of the next version. (if anyone versions the symbol).
|
||||
*/
|
||||
int getNextVersionNumber() {
|
||||
return nextVersionNumber++;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ public class VariableVersion extends Variable {
|
||||
private VariableUnversioned versionOf;
|
||||
|
||||
public VariableVersion(VariableUnversioned versionOf, int version) {
|
||||
super(versionOf.getName()+"#"+version, versionOf.getType());
|
||||
super(versionOf.getLocalName()+"#"+version, versionOf.getScope(), versionOf.getType());
|
||||
this.versionOf = versionOf;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ stmt
|
||||
| 'if' '(' expr ')' stmt ( 'else' stmt )? #stmtIfElse
|
||||
| 'while' '(' expr ')' stmt #stmtWhile
|
||||
| 'do' stmt 'while' '(' expr ')' #stmtDoWhile
|
||||
| 'return' expr ';' #stmtReturn
|
||||
| 'return' expr? ';' #stmtReturn
|
||||
;
|
||||
|
||||
parameterListDecl
|
||||
|
@ -419,9 +419,9 @@ public class KickCParser extends Parser {
|
||||
enterRule(_localctx, 4, RULE_stmt);
|
||||
int _la;
|
||||
try {
|
||||
setState(91);
|
||||
setState(92);
|
||||
_errHandler.sync(this);
|
||||
switch ( getInterpreter().adaptivePredict(_input,7,_ctx) ) {
|
||||
switch ( getInterpreter().adaptivePredict(_input,8,_ctx) ) {
|
||||
case 1:
|
||||
_localctx = new StmtBlockContext(_localctx);
|
||||
enterOuterAlt(_localctx, 1);
|
||||
@ -606,9 +606,17 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
setState(87);
|
||||
match(T__11);
|
||||
setState(88);
|
||||
expr(0);
|
||||
setState(89);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__2) | (1L << T__13) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0)) {
|
||||
{
|
||||
setState(88);
|
||||
expr(0);
|
||||
}
|
||||
}
|
||||
|
||||
setState(91);
|
||||
match(T__6);
|
||||
}
|
||||
break;
|
||||
@ -658,21 +666,21 @@ public class KickCParser extends Parser {
|
||||
try {
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(93);
|
||||
setState(94);
|
||||
parameterDecl();
|
||||
setState(98);
|
||||
setState(99);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
while (_la==T__12) {
|
||||
{
|
||||
{
|
||||
setState(94);
|
||||
match(T__12);
|
||||
setState(95);
|
||||
match(T__12);
|
||||
setState(96);
|
||||
parameterDecl();
|
||||
}
|
||||
}
|
||||
setState(100);
|
||||
setState(101);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
}
|
||||
@ -719,9 +727,9 @@ public class KickCParser extends Parser {
|
||||
try {
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(101);
|
||||
typeDecl(0);
|
||||
setState(102);
|
||||
typeDecl(0);
|
||||
setState(103);
|
||||
match(NAME);
|
||||
}
|
||||
}
|
||||
@ -827,28 +835,28 @@ public class KickCParser extends Parser {
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
|
||||
setState(105);
|
||||
setState(106);
|
||||
match(SIMPLETYPE);
|
||||
}
|
||||
_ctx.stop = _input.LT(-1);
|
||||
setState(117);
|
||||
setState(118);
|
||||
_errHandler.sync(this);
|
||||
_alt = getInterpreter().adaptivePredict(_input,11,_ctx);
|
||||
_alt = getInterpreter().adaptivePredict(_input,12,_ctx);
|
||||
while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
|
||||
if ( _alt==1 ) {
|
||||
if ( _parseListeners!=null ) triggerExitRuleEvent();
|
||||
_prevctx = _localctx;
|
||||
{
|
||||
setState(115);
|
||||
setState(116);
|
||||
_errHandler.sync(this);
|
||||
switch ( getInterpreter().adaptivePredict(_input,10,_ctx) ) {
|
||||
switch ( getInterpreter().adaptivePredict(_input,11,_ctx) ) {
|
||||
case 1:
|
||||
{
|
||||
_localctx = new TypePtrContext(new TypeDeclContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_typeDecl);
|
||||
setState(107);
|
||||
if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)");
|
||||
setState(108);
|
||||
if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)");
|
||||
setState(109);
|
||||
match(T__13);
|
||||
}
|
||||
break;
|
||||
@ -856,30 +864,30 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new TypeArrayContext(new TypeDeclContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_typeDecl);
|
||||
setState(109);
|
||||
if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)");
|
||||
setState(110);
|
||||
if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)");
|
||||
setState(111);
|
||||
match(T__14);
|
||||
setState(112);
|
||||
setState(113);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__2) | (1L << T__13) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0)) {
|
||||
{
|
||||
setState(111);
|
||||
setState(112);
|
||||
expr(0);
|
||||
}
|
||||
}
|
||||
|
||||
setState(114);
|
||||
setState(115);
|
||||
match(T__15);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
setState(119);
|
||||
setState(120);
|
||||
_errHandler.sync(this);
|
||||
_alt = getInterpreter().adaptivePredict(_input,11,_ctx);
|
||||
_alt = getInterpreter().adaptivePredict(_input,12,_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -952,7 +960,7 @@ public class KickCParser extends Parser {
|
||||
enterRule(_localctx, 12, RULE_initializer);
|
||||
int _la;
|
||||
try {
|
||||
setState(132);
|
||||
setState(133);
|
||||
_errHandler.sync(this);
|
||||
switch (_input.LA(1)) {
|
||||
case T__2:
|
||||
@ -969,7 +977,7 @@ public class KickCParser extends Parser {
|
||||
_localctx = new InitExprContext(_localctx);
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(120);
|
||||
setState(121);
|
||||
expr(0);
|
||||
}
|
||||
break;
|
||||
@ -977,27 +985,27 @@ public class KickCParser extends Parser {
|
||||
_localctx = new InitListContext(_localctx);
|
||||
enterOuterAlt(_localctx, 2);
|
||||
{
|
||||
setState(121);
|
||||
match(T__0);
|
||||
setState(122);
|
||||
match(T__0);
|
||||
setState(123);
|
||||
initializer();
|
||||
setState(127);
|
||||
setState(128);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
while (_la==T__12) {
|
||||
{
|
||||
{
|
||||
setState(123);
|
||||
match(T__12);
|
||||
setState(124);
|
||||
match(T__12);
|
||||
setState(125);
|
||||
initializer();
|
||||
}
|
||||
}
|
||||
setState(129);
|
||||
setState(130);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
}
|
||||
setState(130);
|
||||
setState(131);
|
||||
match(T__1);
|
||||
}
|
||||
break;
|
||||
@ -1120,7 +1128,7 @@ public class KickCParser extends Parser {
|
||||
int _alt;
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(142);
|
||||
setState(143);
|
||||
_errHandler.sync(this);
|
||||
switch (_input.LA(1)) {
|
||||
case T__2:
|
||||
@ -1129,11 +1137,11 @@ public class KickCParser extends Parser {
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
|
||||
setState(135);
|
||||
match(T__2);
|
||||
setState(136);
|
||||
lvalue(0);
|
||||
match(T__2);
|
||||
setState(137);
|
||||
lvalue(0);
|
||||
setState(138);
|
||||
match(T__3);
|
||||
}
|
||||
break;
|
||||
@ -1142,7 +1150,7 @@ public class KickCParser extends Parser {
|
||||
_localctx = new LvalueNameContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(139);
|
||||
setState(140);
|
||||
match(NAME);
|
||||
}
|
||||
break;
|
||||
@ -1151,9 +1159,9 @@ public class KickCParser extends Parser {
|
||||
_localctx = new LvaluePtrContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(140);
|
||||
match(T__13);
|
||||
setState(141);
|
||||
match(T__13);
|
||||
setState(142);
|
||||
lvalue(2);
|
||||
}
|
||||
break;
|
||||
@ -1161,9 +1169,9 @@ public class KickCParser extends Parser {
|
||||
throw new NoViableAltException(this);
|
||||
}
|
||||
_ctx.stop = _input.LT(-1);
|
||||
setState(151);
|
||||
setState(152);
|
||||
_errHandler.sync(this);
|
||||
_alt = getInterpreter().adaptivePredict(_input,15,_ctx);
|
||||
_alt = getInterpreter().adaptivePredict(_input,16,_ctx);
|
||||
while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
|
||||
if ( _alt==1 ) {
|
||||
if ( _parseListeners!=null ) triggerExitRuleEvent();
|
||||
@ -1172,20 +1180,20 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new LvalueArrayContext(new LvalueContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_lvalue);
|
||||
setState(144);
|
||||
if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)");
|
||||
setState(145);
|
||||
match(T__14);
|
||||
if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)");
|
||||
setState(146);
|
||||
expr(0);
|
||||
match(T__14);
|
||||
setState(147);
|
||||
expr(0);
|
||||
setState(148);
|
||||
match(T__15);
|
||||
}
|
||||
}
|
||||
}
|
||||
setState(153);
|
||||
setState(154);
|
||||
_errHandler.sync(this);
|
||||
_alt = getInterpreter().adaptivePredict(_input,15,_ctx);
|
||||
_alt = getInterpreter().adaptivePredict(_input,16,_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1420,20 +1428,20 @@ public class KickCParser extends Parser {
|
||||
int _alt;
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(176);
|
||||
setState(177);
|
||||
_errHandler.sync(this);
|
||||
switch ( getInterpreter().adaptivePredict(_input,17,_ctx) ) {
|
||||
switch ( getInterpreter().adaptivePredict(_input,18,_ctx) ) {
|
||||
case 1:
|
||||
{
|
||||
_localctx = new ExprParContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
|
||||
setState(155);
|
||||
match(T__2);
|
||||
setState(156);
|
||||
expr(0);
|
||||
match(T__2);
|
||||
setState(157);
|
||||
expr(0);
|
||||
setState(158);
|
||||
match(T__3);
|
||||
}
|
||||
break;
|
||||
@ -1442,21 +1450,21 @@ public class KickCParser extends Parser {
|
||||
_localctx = new ExprCallContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(159);
|
||||
match(NAME);
|
||||
setState(160);
|
||||
match(NAME);
|
||||
setState(161);
|
||||
match(T__2);
|
||||
setState(162);
|
||||
setState(163);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__2) | (1L << T__13) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0)) {
|
||||
{
|
||||
setState(161);
|
||||
setState(162);
|
||||
parameterList();
|
||||
}
|
||||
}
|
||||
|
||||
setState(164);
|
||||
setState(165);
|
||||
match(T__3);
|
||||
}
|
||||
break;
|
||||
@ -1465,13 +1473,13 @@ public class KickCParser extends Parser {
|
||||
_localctx = new ExprCastContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(165);
|
||||
match(T__2);
|
||||
setState(166);
|
||||
typeDecl(0);
|
||||
match(T__2);
|
||||
setState(167);
|
||||
match(T__3);
|
||||
typeDecl(0);
|
||||
setState(168);
|
||||
match(T__3);
|
||||
setState(169);
|
||||
expr(13);
|
||||
}
|
||||
break;
|
||||
@ -1480,7 +1488,7 @@ public class KickCParser extends Parser {
|
||||
_localctx = new ExprUnaryContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(170);
|
||||
setState(171);
|
||||
_la = _input.LA(1);
|
||||
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__13) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20))) != 0)) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -1490,7 +1498,7 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(171);
|
||||
setState(172);
|
||||
expr(11);
|
||||
}
|
||||
break;
|
||||
@ -1499,7 +1507,7 @@ public class KickCParser extends Parser {
|
||||
_localctx = new ExprIdContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(172);
|
||||
setState(173);
|
||||
match(NAME);
|
||||
}
|
||||
break;
|
||||
@ -1508,7 +1516,7 @@ public class KickCParser extends Parser {
|
||||
_localctx = new ExprNumberContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(173);
|
||||
setState(174);
|
||||
match(NUMBER);
|
||||
}
|
||||
break;
|
||||
@ -1517,7 +1525,7 @@ public class KickCParser extends Parser {
|
||||
_localctx = new ExprStringContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(174);
|
||||
setState(175);
|
||||
match(STRING);
|
||||
}
|
||||
break;
|
||||
@ -1526,30 +1534,30 @@ public class KickCParser extends Parser {
|
||||
_localctx = new ExprBoolContext(_localctx);
|
||||
_ctx = _localctx;
|
||||
_prevctx = _localctx;
|
||||
setState(175);
|
||||
setState(176);
|
||||
match(BOOLEAN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
_ctx.stop = _input.LT(-1);
|
||||
setState(203);
|
||||
setState(204);
|
||||
_errHandler.sync(this);
|
||||
_alt = getInterpreter().adaptivePredict(_input,19,_ctx);
|
||||
_alt = getInterpreter().adaptivePredict(_input,20,_ctx);
|
||||
while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
|
||||
if ( _alt==1 ) {
|
||||
if ( _parseListeners!=null ) triggerExitRuleEvent();
|
||||
_prevctx = _localctx;
|
||||
{
|
||||
setState(201);
|
||||
setState(202);
|
||||
_errHandler.sync(this);
|
||||
switch ( getInterpreter().adaptivePredict(_input,18,_ctx) ) {
|
||||
switch ( getInterpreter().adaptivePredict(_input,19,_ctx) ) {
|
||||
case 1:
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(178);
|
||||
if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)");
|
||||
setState(179);
|
||||
if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)");
|
||||
setState(180);
|
||||
_la = _input.LA(1);
|
||||
if ( !(_la==T__21 || _la==T__22) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -1559,7 +1567,7 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(180);
|
||||
setState(181);
|
||||
expr(11);
|
||||
}
|
||||
break;
|
||||
@ -1567,9 +1575,9 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(181);
|
||||
if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
|
||||
setState(182);
|
||||
if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
|
||||
setState(183);
|
||||
_la = _input.LA(1);
|
||||
if ( !(_la==T__13 || _la==T__23) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -1579,7 +1587,7 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(183);
|
||||
setState(184);
|
||||
expr(10);
|
||||
}
|
||||
break;
|
||||
@ -1587,9 +1595,9 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(184);
|
||||
if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)");
|
||||
setState(185);
|
||||
if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)");
|
||||
setState(186);
|
||||
_la = _input.LA(1);
|
||||
if ( !(_la==T__16 || _la==T__17) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -1599,7 +1607,7 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(186);
|
||||
setState(187);
|
||||
expr(9);
|
||||
}
|
||||
break;
|
||||
@ -1607,9 +1615,9 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(187);
|
||||
if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
|
||||
setState(188);
|
||||
if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
|
||||
setState(189);
|
||||
_la = _input.LA(1);
|
||||
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__24) | (1L << T__25) | (1L << T__26) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__30) | (1L << T__31) | (1L << T__32))) != 0)) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -1619,7 +1627,7 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(189);
|
||||
setState(190);
|
||||
expr(8);
|
||||
}
|
||||
break;
|
||||
@ -1627,9 +1635,9 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(190);
|
||||
if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)");
|
||||
setState(191);
|
||||
if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)");
|
||||
setState(192);
|
||||
_la = _input.LA(1);
|
||||
if ( !(_la==T__33 || _la==T__34) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -1639,7 +1647,7 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(192);
|
||||
setState(193);
|
||||
expr(7);
|
||||
}
|
||||
break;
|
||||
@ -1647,9 +1655,9 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(193);
|
||||
if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)");
|
||||
setState(194);
|
||||
if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)");
|
||||
setState(195);
|
||||
_la = _input.LA(1);
|
||||
if ( !(_la==T__35 || _la==T__36) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@ -1659,7 +1667,7 @@ public class KickCParser extends Parser {
|
||||
_errHandler.reportMatch(this);
|
||||
consume();
|
||||
}
|
||||
setState(195);
|
||||
setState(196);
|
||||
expr(6);
|
||||
}
|
||||
break;
|
||||
@ -1667,22 +1675,22 @@ public class KickCParser extends Parser {
|
||||
{
|
||||
_localctx = new ExprArrayContext(new ExprContext(_parentctx, _parentState));
|
||||
pushNewRecursionContext(_localctx, _startState, RULE_expr);
|
||||
setState(196);
|
||||
if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)");
|
||||
setState(197);
|
||||
match(T__14);
|
||||
if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)");
|
||||
setState(198);
|
||||
expr(0);
|
||||
match(T__14);
|
||||
setState(199);
|
||||
expr(0);
|
||||
setState(200);
|
||||
match(T__15);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
setState(205);
|
||||
setState(206);
|
||||
_errHandler.sync(this);
|
||||
_alt = getInterpreter().adaptivePredict(_input,19,_ctx);
|
||||
_alt = getInterpreter().adaptivePredict(_input,20,_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1730,21 +1738,21 @@ public class KickCParser extends Parser {
|
||||
try {
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(206);
|
||||
setState(207);
|
||||
expr(0);
|
||||
setState(211);
|
||||
setState(212);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
while (_la==T__12) {
|
||||
{
|
||||
{
|
||||
setState(207);
|
||||
match(T__12);
|
||||
setState(208);
|
||||
match(T__12);
|
||||
setState(209);
|
||||
expr(0);
|
||||
}
|
||||
}
|
||||
setState(213);
|
||||
setState(214);
|
||||
_errHandler.sync(this);
|
||||
_la = _input.LA(1);
|
||||
}
|
||||
@ -1809,77 +1817,77 @@ public class KickCParser extends Parser {
|
||||
}
|
||||
|
||||
public static final String _serializedATN =
|
||||
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\67\u00d9\4\2\t\2"+
|
||||
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\67\u00da\4\2\t\2"+
|
||||
"\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
|
||||
"\t\13\3\2\3\2\3\2\3\3\6\3\33\n\3\r\3\16\3\34\3\4\3\4\5\4!\n\4\3\4\3\4"+
|
||||
"\3\4\3\4\3\4\5\4(\n\4\3\4\3\4\3\4\5\4-\n\4\3\4\3\4\3\4\5\4\62\n\4\3\4"+
|
||||
"\3\4\3\4\3\4\5\48\n\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4"+
|
||||
"\3\4\3\4\3\4\3\4\3\4\5\4K\n\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4"+
|
||||
"\3\4\3\4\3\4\3\4\3\4\3\4\3\4\5\4^\n\4\3\5\3\5\3\5\7\5c\n\5\f\5\16\5f\13"+
|
||||
"\5\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\5\7s\n\7\3\7\7\7v\n\7\f"+
|
||||
"\7\16\7y\13\7\3\b\3\b\3\b\3\b\3\b\7\b\u0080\n\b\f\b\16\b\u0083\13\b\3"+
|
||||
"\b\3\b\5\b\u0087\n\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\5\t\u0091\n\t\3\t"+
|
||||
"\3\t\3\t\3\t\3\t\7\t\u0098\n\t\f\t\16\t\u009b\13\t\3\n\3\n\3\n\3\n\3\n"+
|
||||
"\3\n\3\n\3\n\5\n\u00a5\n\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n"+
|
||||
"\3\n\5\n\u00b3\n\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n"+
|
||||
"\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\7\n\u00cc\n\n\f\n\16\n\u00cf"+
|
||||
"\13\n\3\13\3\13\3\13\7\13\u00d4\n\13\f\13\16\13\u00d7\13\13\3\13\2\5\f"+
|
||||
"\20\22\f\2\4\6\b\n\f\16\20\22\24\2\t\4\2\20\20\23\27\3\2\30\31\4\2\20"+
|
||||
"\20\32\32\3\2\23\24\3\2\33#\3\2$%\3\2&\'\2\u00f6\2\26\3\2\2\2\4\32\3\2"+
|
||||
"\2\2\6]\3\2\2\2\b_\3\2\2\2\ng\3\2\2\2\fj\3\2\2\2\16\u0086\3\2\2\2\20\u0090"+
|
||||
"\3\2\2\2\22\u00b2\3\2\2\2\24\u00d0\3\2\2\2\26\27\5\4\3\2\27\30\7\2\2\3"+
|
||||
"\30\3\3\2\2\2\31\33\5\6\4\2\32\31\3\2\2\2\33\34\3\2\2\2\34\32\3\2\2\2"+
|
||||
"\34\35\3\2\2\2\35\5\3\2\2\2\36 \7\3\2\2\37!\5\4\3\2 \37\3\2\2\2 !\3\2"+
|
||||
"\2\2!\"\3\2\2\2\"^\7\4\2\2#$\5\f\7\2$%\7\64\2\2%\'\7\5\2\2&(\5\b\5\2\'"+
|
||||
"&\3\2\2\2\'(\3\2\2\2()\3\2\2\2)*\7\6\2\2*,\7\3\2\2+-\5\4\3\2,+\3\2\2\2"+
|
||||
",-\3\2\2\2-.\3\2\2\2./\7\4\2\2/^\3\2\2\2\60\62\7\7\2\2\61\60\3\2\2\2\61"+
|
||||
"\62\3\2\2\2\62\63\3\2\2\2\63\64\5\f\7\2\64\67\7\64\2\2\65\66\7\b\2\2\66"+
|
||||
"8\5\16\b\2\67\65\3\2\2\2\678\3\2\2\289\3\2\2\29:\7\t\2\2:^\3\2\2\2;<\5"+
|
||||
"\20\t\2<=\7\b\2\2=>\5\22\n\2>?\7\t\2\2?^\3\2\2\2@A\5\22\n\2AB\7\t\2\2"+
|
||||
"B^\3\2\2\2CD\7\n\2\2DE\7\5\2\2EF\5\22\n\2FG\7\6\2\2GJ\5\6\4\2HI\7\13\2"+
|
||||
"\2IK\5\6\4\2JH\3\2\2\2JK\3\2\2\2K^\3\2\2\2LM\7\f\2\2MN\7\5\2\2NO\5\22"+
|
||||
"\n\2OP\7\6\2\2PQ\5\6\4\2Q^\3\2\2\2RS\7\r\2\2ST\5\6\4\2TU\7\f\2\2UV\7\5"+
|
||||
"\2\2VW\5\22\n\2WX\7\6\2\2X^\3\2\2\2YZ\7\16\2\2Z[\5\22\n\2[\\\7\t\2\2\\"+
|
||||
"^\3\2\2\2]\36\3\2\2\2]#\3\2\2\2]\61\3\2\2\2];\3\2\2\2]@\3\2\2\2]C\3\2"+
|
||||
"\2\2]L\3\2\2\2]R\3\2\2\2]Y\3\2\2\2^\7\3\2\2\2_d\5\n\6\2`a\7\17\2\2ac\5"+
|
||||
"\n\6\2b`\3\2\2\2cf\3\2\2\2db\3\2\2\2de\3\2\2\2e\t\3\2\2\2fd\3\2\2\2gh"+
|
||||
"\5\f\7\2hi\7\64\2\2i\13\3\2\2\2jk\b\7\1\2kl\7(\2\2lw\3\2\2\2mn\f\4\2\2"+
|
||||
"nv\7\20\2\2op\f\3\2\2pr\7\21\2\2qs\5\22\n\2rq\3\2\2\2rs\3\2\2\2st\3\2"+
|
||||
"\2\2tv\7\22\2\2um\3\2\2\2uo\3\2\2\2vy\3\2\2\2wu\3\2\2\2wx\3\2\2\2x\r\3"+
|
||||
"\2\2\2yw\3\2\2\2z\u0087\5\22\n\2{|\7\3\2\2|\u0081\5\16\b\2}~\7\17\2\2"+
|
||||
"~\u0080\5\16\b\2\177}\3\2\2\2\u0080\u0083\3\2\2\2\u0081\177\3\2\2\2\u0081"+
|
||||
"\u0082\3\2\2\2\u0082\u0084\3\2\2\2\u0083\u0081\3\2\2\2\u0084\u0085\7\4"+
|
||||
"\2\2\u0085\u0087\3\2\2\2\u0086z\3\2\2\2\u0086{\3\2\2\2\u0087\17\3\2\2"+
|
||||
"\2\u0088\u0089\b\t\1\2\u0089\u008a\7\5\2\2\u008a\u008b\5\20\t\2\u008b"+
|
||||
"\u008c\7\6\2\2\u008c\u0091\3\2\2\2\u008d\u0091\7\64\2\2\u008e\u008f\7"+
|
||||
"\20\2\2\u008f\u0091\5\20\t\4\u0090\u0088\3\2\2\2\u0090\u008d\3\2\2\2\u0090"+
|
||||
"\u008e\3\2\2\2\u0091\u0099\3\2\2\2\u0092\u0093\f\3\2\2\u0093\u0094\7\21"+
|
||||
"\2\2\u0094\u0095\5\22\n\2\u0095\u0096\7\22\2\2\u0096\u0098\3\2\2\2\u0097"+
|
||||
"\u0092\3\2\2\2\u0098\u009b\3\2\2\2\u0099\u0097\3\2\2\2\u0099\u009a\3\2"+
|
||||
"\2\2\u009a\21\3\2\2\2\u009b\u0099\3\2\2\2\u009c\u009d\b\n\1\2\u009d\u009e"+
|
||||
"\7\5\2\2\u009e\u009f\5\22\n\2\u009f\u00a0\7\6\2\2\u00a0\u00b3\3\2\2\2"+
|
||||
"\u00a1\u00a2\7\64\2\2\u00a2\u00a4\7\5\2\2\u00a3\u00a5\5\24\13\2\u00a4"+
|
||||
"\u00a3\3\2\2\2\u00a4\u00a5\3\2\2\2\u00a5\u00a6\3\2\2\2\u00a6\u00b3\7\6"+
|
||||
"\2\2\u00a7\u00a8\7\5\2\2\u00a8\u00a9\5\f\7\2\u00a9\u00aa\7\6\2\2\u00aa"+
|
||||
"\u00ab\5\22\n\17\u00ab\u00b3\3\2\2\2\u00ac\u00ad\t\2\2\2\u00ad\u00b3\5"+
|
||||
"\22\n\r\u00ae\u00b3\7\64\2\2\u00af\u00b3\7+\2\2\u00b0\u00b3\7)\2\2\u00b1"+
|
||||
"\u00b3\7*\2\2\u00b2\u009c\3\2\2\2\u00b2\u00a1\3\2\2\2\u00b2\u00a7\3\2"+
|
||||
"\2\2\u00b2\u00ac\3\2\2\2\u00b2\u00ae\3\2\2\2\u00b2\u00af\3\2\2\2\u00b2"+
|
||||
"\u00b0\3\2\2\2\u00b2\u00b1\3\2\2\2\u00b3\u00cd\3\2\2\2\u00b4\u00b5\f\f"+
|
||||
"\2\2\u00b5\u00b6\t\3\2\2\u00b6\u00cc\5\22\n\r\u00b7\u00b8\f\13\2\2\u00b8"+
|
||||
"\u00b9\t\4\2\2\u00b9\u00cc\5\22\n\f\u00ba\u00bb\f\n\2\2\u00bb\u00bc\t"+
|
||||
"\5\2\2\u00bc\u00cc\5\22\n\13\u00bd\u00be\f\t\2\2\u00be\u00bf\t\6\2\2\u00bf"+
|
||||
"\u00cc\5\22\n\n\u00c0\u00c1\f\b\2\2\u00c1\u00c2\t\7\2\2\u00c2\u00cc\5"+
|
||||
"\22\n\t\u00c3\u00c4\f\7\2\2\u00c4\u00c5\t\b\2\2\u00c5\u00cc\5\22\n\b\u00c6"+
|
||||
"\u00c7\f\16\2\2\u00c7\u00c8\7\21\2\2\u00c8\u00c9\5\22\n\2\u00c9\u00ca"+
|
||||
"\7\22\2\2\u00ca\u00cc\3\2\2\2\u00cb\u00b4\3\2\2\2\u00cb\u00b7\3\2\2\2"+
|
||||
"\u00cb\u00ba\3\2\2\2\u00cb\u00bd\3\2\2\2\u00cb\u00c0\3\2\2\2\u00cb\u00c3"+
|
||||
"\3\2\2\2\u00cb\u00c6\3\2\2\2\u00cc\u00cf\3\2\2\2\u00cd\u00cb\3\2\2\2\u00cd"+
|
||||
"\u00ce\3\2\2\2\u00ce\23\3\2\2\2\u00cf\u00cd\3\2\2\2\u00d0\u00d5\5\22\n"+
|
||||
"\2\u00d1\u00d2\7\17\2\2\u00d2\u00d4\5\22\n\2\u00d3\u00d1\3\2\2\2\u00d4"+
|
||||
"\u00d7\3\2\2\2\u00d5\u00d3\3\2\2\2\u00d5\u00d6\3\2\2\2\u00d6\25\3\2\2"+
|
||||
"\2\u00d7\u00d5\3\2\2\2\27\34 \',\61\67J]druw\u0081\u0086\u0090\u0099\u00a4"+
|
||||
"\u00b2\u00cb\u00cd\u00d5";
|
||||
"\3\4\3\4\3\4\3\4\3\4\5\4\\\n\4\3\4\5\4_\n\4\3\5\3\5\3\5\7\5d\n\5\f\5\16"+
|
||||
"\5g\13\5\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\5\7t\n\7\3\7\7\7"+
|
||||
"w\n\7\f\7\16\7z\13\7\3\b\3\b\3\b\3\b\3\b\7\b\u0081\n\b\f\b\16\b\u0084"+
|
||||
"\13\b\3\b\3\b\5\b\u0088\n\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\5\t\u0092"+
|
||||
"\n\t\3\t\3\t\3\t\3\t\3\t\7\t\u0099\n\t\f\t\16\t\u009c\13\t\3\n\3\n\3\n"+
|
||||
"\3\n\3\n\3\n\3\n\3\n\5\n\u00a6\n\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n"+
|
||||
"\3\n\3\n\3\n\5\n\u00b4\n\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n"+
|
||||
"\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\7\n\u00cd\n\n\f\n\16"+
|
||||
"\n\u00d0\13\n\3\13\3\13\3\13\7\13\u00d5\n\13\f\13\16\13\u00d8\13\13\3"+
|
||||
"\13\2\5\f\20\22\f\2\4\6\b\n\f\16\20\22\24\2\t\4\2\20\20\23\27\3\2\30\31"+
|
||||
"\4\2\20\20\32\32\3\2\23\24\3\2\33#\3\2$%\3\2&\'\2\u00f8\2\26\3\2\2\2\4"+
|
||||
"\32\3\2\2\2\6^\3\2\2\2\b`\3\2\2\2\nh\3\2\2\2\fk\3\2\2\2\16\u0087\3\2\2"+
|
||||
"\2\20\u0091\3\2\2\2\22\u00b3\3\2\2\2\24\u00d1\3\2\2\2\26\27\5\4\3\2\27"+
|
||||
"\30\7\2\2\3\30\3\3\2\2\2\31\33\5\6\4\2\32\31\3\2\2\2\33\34\3\2\2\2\34"+
|
||||
"\32\3\2\2\2\34\35\3\2\2\2\35\5\3\2\2\2\36 \7\3\2\2\37!\5\4\3\2 \37\3\2"+
|
||||
"\2\2 !\3\2\2\2!\"\3\2\2\2\"_\7\4\2\2#$\5\f\7\2$%\7\64\2\2%\'\7\5\2\2&"+
|
||||
"(\5\b\5\2\'&\3\2\2\2\'(\3\2\2\2()\3\2\2\2)*\7\6\2\2*,\7\3\2\2+-\5\4\3"+
|
||||
"\2,+\3\2\2\2,-\3\2\2\2-.\3\2\2\2./\7\4\2\2/_\3\2\2\2\60\62\7\7\2\2\61"+
|
||||
"\60\3\2\2\2\61\62\3\2\2\2\62\63\3\2\2\2\63\64\5\f\7\2\64\67\7\64\2\2\65"+
|
||||
"\66\7\b\2\2\668\5\16\b\2\67\65\3\2\2\2\678\3\2\2\289\3\2\2\29:\7\t\2\2"+
|
||||
":_\3\2\2\2;<\5\20\t\2<=\7\b\2\2=>\5\22\n\2>?\7\t\2\2?_\3\2\2\2@A\5\22"+
|
||||
"\n\2AB\7\t\2\2B_\3\2\2\2CD\7\n\2\2DE\7\5\2\2EF\5\22\n\2FG\7\6\2\2GJ\5"+
|
||||
"\6\4\2HI\7\13\2\2IK\5\6\4\2JH\3\2\2\2JK\3\2\2\2K_\3\2\2\2LM\7\f\2\2MN"+
|
||||
"\7\5\2\2NO\5\22\n\2OP\7\6\2\2PQ\5\6\4\2Q_\3\2\2\2RS\7\r\2\2ST\5\6\4\2"+
|
||||
"TU\7\f\2\2UV\7\5\2\2VW\5\22\n\2WX\7\6\2\2X_\3\2\2\2Y[\7\16\2\2Z\\\5\22"+
|
||||
"\n\2[Z\3\2\2\2[\\\3\2\2\2\\]\3\2\2\2]_\7\t\2\2^\36\3\2\2\2^#\3\2\2\2^"+
|
||||
"\61\3\2\2\2^;\3\2\2\2^@\3\2\2\2^C\3\2\2\2^L\3\2\2\2^R\3\2\2\2^Y\3\2\2"+
|
||||
"\2_\7\3\2\2\2`e\5\n\6\2ab\7\17\2\2bd\5\n\6\2ca\3\2\2\2dg\3\2\2\2ec\3\2"+
|
||||
"\2\2ef\3\2\2\2f\t\3\2\2\2ge\3\2\2\2hi\5\f\7\2ij\7\64\2\2j\13\3\2\2\2k"+
|
||||
"l\b\7\1\2lm\7(\2\2mx\3\2\2\2no\f\4\2\2ow\7\20\2\2pq\f\3\2\2qs\7\21\2\2"+
|
||||
"rt\5\22\n\2sr\3\2\2\2st\3\2\2\2tu\3\2\2\2uw\7\22\2\2vn\3\2\2\2vp\3\2\2"+
|
||||
"\2wz\3\2\2\2xv\3\2\2\2xy\3\2\2\2y\r\3\2\2\2zx\3\2\2\2{\u0088\5\22\n\2"+
|
||||
"|}\7\3\2\2}\u0082\5\16\b\2~\177\7\17\2\2\177\u0081\5\16\b\2\u0080~\3\2"+
|
||||
"\2\2\u0081\u0084\3\2\2\2\u0082\u0080\3\2\2\2\u0082\u0083\3\2\2\2\u0083"+
|
||||
"\u0085\3\2\2\2\u0084\u0082\3\2\2\2\u0085\u0086\7\4\2\2\u0086\u0088\3\2"+
|
||||
"\2\2\u0087{\3\2\2\2\u0087|\3\2\2\2\u0088\17\3\2\2\2\u0089\u008a\b\t\1"+
|
||||
"\2\u008a\u008b\7\5\2\2\u008b\u008c\5\20\t\2\u008c\u008d\7\6\2\2\u008d"+
|
||||
"\u0092\3\2\2\2\u008e\u0092\7\64\2\2\u008f\u0090\7\20\2\2\u0090\u0092\5"+
|
||||
"\20\t\4\u0091\u0089\3\2\2\2\u0091\u008e\3\2\2\2\u0091\u008f\3\2\2\2\u0092"+
|
||||
"\u009a\3\2\2\2\u0093\u0094\f\3\2\2\u0094\u0095\7\21\2\2\u0095\u0096\5"+
|
||||
"\22\n\2\u0096\u0097\7\22\2\2\u0097\u0099\3\2\2\2\u0098\u0093\3\2\2\2\u0099"+
|
||||
"\u009c\3\2\2\2\u009a\u0098\3\2\2\2\u009a\u009b\3\2\2\2\u009b\21\3\2\2"+
|
||||
"\2\u009c\u009a\3\2\2\2\u009d\u009e\b\n\1\2\u009e\u009f\7\5\2\2\u009f\u00a0"+
|
||||
"\5\22\n\2\u00a0\u00a1\7\6\2\2\u00a1\u00b4\3\2\2\2\u00a2\u00a3\7\64\2\2"+
|
||||
"\u00a3\u00a5\7\5\2\2\u00a4\u00a6\5\24\13\2\u00a5\u00a4\3\2\2\2\u00a5\u00a6"+
|
||||
"\3\2\2\2\u00a6\u00a7\3\2\2\2\u00a7\u00b4\7\6\2\2\u00a8\u00a9\7\5\2\2\u00a9"+
|
||||
"\u00aa\5\f\7\2\u00aa\u00ab\7\6\2\2\u00ab\u00ac\5\22\n\17\u00ac\u00b4\3"+
|
||||
"\2\2\2\u00ad\u00ae\t\2\2\2\u00ae\u00b4\5\22\n\r\u00af\u00b4\7\64\2\2\u00b0"+
|
||||
"\u00b4\7+\2\2\u00b1\u00b4\7)\2\2\u00b2\u00b4\7*\2\2\u00b3\u009d\3\2\2"+
|
||||
"\2\u00b3\u00a2\3\2\2\2\u00b3\u00a8\3\2\2\2\u00b3\u00ad\3\2\2\2\u00b3\u00af"+
|
||||
"\3\2\2\2\u00b3\u00b0\3\2\2\2\u00b3\u00b1\3\2\2\2\u00b3\u00b2\3\2\2\2\u00b4"+
|
||||
"\u00ce\3\2\2\2\u00b5\u00b6\f\f\2\2\u00b6\u00b7\t\3\2\2\u00b7\u00cd\5\22"+
|
||||
"\n\r\u00b8\u00b9\f\13\2\2\u00b9\u00ba\t\4\2\2\u00ba\u00cd\5\22\n\f\u00bb"+
|
||||
"\u00bc\f\n\2\2\u00bc\u00bd\t\5\2\2\u00bd\u00cd\5\22\n\13\u00be\u00bf\f"+
|
||||
"\t\2\2\u00bf\u00c0\t\6\2\2\u00c0\u00cd\5\22\n\n\u00c1\u00c2\f\b\2\2\u00c2"+
|
||||
"\u00c3\t\7\2\2\u00c3\u00cd\5\22\n\t\u00c4\u00c5\f\7\2\2\u00c5\u00c6\t"+
|
||||
"\b\2\2\u00c6\u00cd\5\22\n\b\u00c7\u00c8\f\16\2\2\u00c8\u00c9\7\21\2\2"+
|
||||
"\u00c9\u00ca\5\22\n\2\u00ca\u00cb\7\22\2\2\u00cb\u00cd\3\2\2\2\u00cc\u00b5"+
|
||||
"\3\2\2\2\u00cc\u00b8\3\2\2\2\u00cc\u00bb\3\2\2\2\u00cc\u00be\3\2\2\2\u00cc"+
|
||||
"\u00c1\3\2\2\2\u00cc\u00c4\3\2\2\2\u00cc\u00c7\3\2\2\2\u00cd\u00d0\3\2"+
|
||||
"\2\2\u00ce\u00cc\3\2\2\2\u00ce\u00cf\3\2\2\2\u00cf\23\3\2\2\2\u00d0\u00ce"+
|
||||
"\3\2\2\2\u00d1\u00d6\5\22\n\2\u00d2\u00d3\7\17\2\2\u00d3\u00d5\5\22\n"+
|
||||
"\2\u00d4\u00d2\3\2\2\2\u00d5\u00d8\3\2\2\2\u00d6\u00d4\3\2\2\2\u00d6\u00d7"+
|
||||
"\3\2\2\2\u00d7\25\3\2\2\2\u00d8\u00d6\3\2\2\2\30\34 \',\61\67J[^esvx\u0082"+
|
||||
"\u0087\u0091\u009a\u00a5\u00b3\u00cc\u00ce\u00d6";
|
||||
public static final ATN _ATN =
|
||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
static {
|
||||
|
@ -13,7 +13,7 @@ import java.util.List;
|
||||
/** Test my KickC Grammar */
|
||||
public class Main {
|
||||
public static void main(String[] args) throws IOException {
|
||||
final String fileName = "src/dk/camelot64/kickc/test/selfassign.kc";
|
||||
final String fileName = "src/dk/camelot64/kickc/test/callsum.kc";
|
||||
final CharStream input = CharStreams.fromFileName(fileName);
|
||||
System.out.println(input.toString());
|
||||
KickCLexer lexer = new KickCLexer(input);
|
||||
@ -29,11 +29,13 @@ public class Main {
|
||||
Pass1GenerateStatementSequence pass1GenerateStatementSequence = new Pass1GenerateStatementSequence();
|
||||
pass1GenerateStatementSequence.generate(file);
|
||||
StatementSequence statementSequence = pass1GenerateStatementSequence.getSequence();
|
||||
SymbolTable symbolTable = pass1GenerateStatementSequence.getSymbols();
|
||||
SymbolTable symbolTable = pass1GenerateStatementSequence.getProgramSymbols();
|
||||
new PassTypeInference().inferTypes(statementSequence, symbolTable);
|
||||
|
||||
System.out.println("PROGRAM");
|
||||
System.out.println(statementSequence.toString());
|
||||
System.out.println("SYMBOLS");
|
||||
System.out.println(symbolTable.getSymbolTableContents());
|
||||
|
||||
Pass1GenerateControlFlowGraph pass1GenerateControlFlowGraph = new Pass1GenerateControlFlowGraph(symbolTable);
|
||||
ControlFlowGraph controlFlowGraph = pass1GenerateControlFlowGraph.generate(statementSequence);
|
||||
|
9
src/dk/camelot64/kickc/test/callinc.kc
Normal file
9
src/dk/camelot64/kickc/test/callinc.kc
Normal file
@ -0,0 +1,9 @@
|
||||
byte i = 5;
|
||||
a = inc(3);
|
||||
a = inc(a);
|
||||
a = a + i;
|
||||
|
||||
byte inc(byte a) {
|
||||
i = i + 1;
|
||||
return a + i;
|
||||
}
|
9
src/dk/camelot64/kickc/test/callsum.kc
Normal file
9
src/dk/camelot64/kickc/test/callsum.kc
Normal file
@ -0,0 +1,9 @@
|
||||
byte a = 12;
|
||||
byte s = sum(5,a);
|
||||
a = a+s;
|
||||
a = sum(s, a);
|
||||
return;
|
||||
|
||||
byte sum(byte b1, byte b2) {
|
||||
return b1+b2;
|
||||
}
|
@ -11,12 +11,11 @@ byte inc(byte a) {
|
||||
// Not committed to a specific parameter transfer style (non SSA)
|
||||
@BEGIN:
|
||||
(byte) i := 5
|
||||
(byte) a := call INC 3
|
||||
(byte) a := call INC a
|
||||
(byte) a := call inc 3
|
||||
(byte) a := call inc a
|
||||
(byte) a := a + i
|
||||
to: @END
|
||||
INC:
|
||||
(byte) param INC.a
|
||||
byte inc(byte a):
|
||||
(byte) i := i + 1
|
||||
(byte§) $1 := INC.a + i
|
||||
return (byte) $1
|
||||
@ -25,38 +24,37 @@ INC:
|
||||
// Variable/Register parameter/return transfer (non SSA)
|
||||
@BEGIN:
|
||||
(byte) i := 5
|
||||
(byte) INC.a := 3
|
||||
(byte) a := call INC
|
||||
(byte) inc.a := 3
|
||||
(byte) a := call inc
|
||||
to: @1
|
||||
@1:
|
||||
(byte) INC.a := a
|
||||
(byte) a := call INC
|
||||
(byte) inc.a := a
|
||||
(byte) a := call inc
|
||||
to: @2
|
||||
@2:
|
||||
(byte§) a := a + i
|
||||
to: @END
|
||||
INC:
|
||||
(byte) param INC.a
|
||||
inc: (byte) inc((byte) a)
|
||||
(byte) i := i + 1
|
||||
(byte§) $1 := INC.a + i
|
||||
(byte§) $1 := inc.a + i
|
||||
(byte)return $1
|
||||
to: @RETURN
|
||||
|
||||
// Variable/Register parameter/return transfer (SSA)
|
||||
@BEGIN:
|
||||
(byte) i#0 := 5
|
||||
(byte) INC.a#0 := 3
|
||||
call INC
|
||||
(byte) a#0 := INC.return#0
|
||||
(byte) i#3 := INC.i#1
|
||||
(byte) inc.a#0 := 3
|
||||
call inc
|
||||
(byte) a#0 := inc.return#0
|
||||
(byte) i#3 := inc.i#1
|
||||
to: @1
|
||||
@1:
|
||||
(byte) i#2 = phi( @BEGIN/i#3)
|
||||
(byte§) a#1 := phi(@BEGIN/a#0)
|
||||
(byte) INC.a#1 := a#1
|
||||
call INC
|
||||
(byte) a#1 := INC.return#0
|
||||
(byte) i#4 := INC.i#1
|
||||
(byte) inc.a#1 := a#1
|
||||
call inc
|
||||
(byte) a#1 := inc.return#0
|
||||
(byte) i#4 := inc.i#1
|
||||
to @2
|
||||
@2:
|
||||
(byte) i#1 = phi( @1/i#4)
|
||||
@ -64,47 +62,46 @@ INC:
|
||||
(byte§) $2 := a#2 + i#1
|
||||
(byte§) a#2 := $2
|
||||
to: @END
|
||||
INC: from @BEGIN @1
|
||||
(byte) param INC.a
|
||||
(byte) INC.a#2 = phi( @BEGIN/INC.a#0 @1/INC.a#1)
|
||||
(byte) INC.i#0 = phi( @BEGIN/i#0 @1/i#2)
|
||||
(byte) INC.i#1 := INC.i#0 + INC.1#0;
|
||||
(byte§) $1 := INC.a#2 + INC.i#1;
|
||||
(byte) INC.return#0 := $1
|
||||
(byte) return INC.return#0
|
||||
inc: (byte) inc((byte) a) from @BEGIN @1
|
||||
(byte) inc.a#2 = phi( @BEGIN/inc.a#0 @1/inc.a#1)
|
||||
(byte) inc.i#0 = phi( @BEGIN/i#0 @1/i#2)
|
||||
(byte) inc.i#1 := inc.i#0 + 1;
|
||||
(byte§) $1 := inc.a#2 + inc.i#1;
|
||||
(byte) inc.return#0 := $1
|
||||
(byte) return inc.return#0
|
||||
to: @RETURN
|
||||
|
||||
// Variable/Register parameter/return transfer (SSA) optimized
|
||||
@BEGIN:
|
||||
call INC
|
||||
call inc
|
||||
to: @1
|
||||
@1:
|
||||
call INC
|
||||
call inc
|
||||
to @2
|
||||
@2:
|
||||
(byte§) a#2 := INC.return#0 + INC.i#1
|
||||
(byte§) a#2 := inc.return#0 + inc.i#1
|
||||
to: @END
|
||||
INC: from @BEGIN @1
|
||||
(byte) INC.a#2 = phi( @BEGIN/3 @1/INC.return#0)
|
||||
(byte) INC.i#0 = phi( @BEGIN/5 @1/INC.i#1)
|
||||
(byte) INC.i#1 := INC.i#0 + 1;
|
||||
(byte) INC.return#0 := INC.a#2 + INC.i#1
|
||||
inc: (byte) inc((byte) a) from @BEGIN @1
|
||||
(byte) inc.a#2 = phi( @BEGIN/3 @1/inc.return#0)
|
||||
(byte) inc.i#0 = phi( @BEGIN/5 @1/inc.i#1)
|
||||
(byte) inc.i#1 := inc.i#0 + 1;
|
||||
(byte) inc.return#0 := inc.a#2 + inc.i#1
|
||||
to: @RETURN
|
||||
|
||||
// Inline call (non SSA)
|
||||
@BEGIN:
|
||||
(byte) i := 5
|
||||
to: INC@1
|
||||
INC@1:
|
||||
(byte) INC.a := 3
|
||||
to: inc@1
|
||||
inc@1:
|
||||
(byte) inc.a := 3
|
||||
(byte) i := i + 1
|
||||
(byte§) $2 := INC.a + i
|
||||
(byte§) $2 := inc.a + i
|
||||
(byte) a := (byte) $2
|
||||
to: INC@2
|
||||
INC@2:
|
||||
(byte) INC.a := a
|
||||
to: inc@2
|
||||
inc@2:
|
||||
(byte) inc.a := a
|
||||
(byte) i := i + 1
|
||||
(byte§) $3 := INC.a + i
|
||||
(byte§) $3 := inc.a + i
|
||||
(byte) a := (byte) $3
|
||||
to: @1
|
||||
@1:
|
||||
@ -114,28 +111,29 @@ INC@2:
|
||||
// Inline call (SSA)
|
||||
@BEGIN:
|
||||
(byte) i#0 := 5
|
||||
to: INC@1
|
||||
INC@1:
|
||||
to: inc@1
|
||||
inc@1: from @BEGIN
|
||||
(byte) i#5 := phi(@BEGIN/i#0)
|
||||
(byte) INC.a#0 := 3
|
||||
(byte) inc.a#0 := 3
|
||||
(byte) i#1 := i#5 + 1
|
||||
(byte§) $2 := INC.a#0 + i#1
|
||||
(byte§) $2 := inc.a#0 + i#1
|
||||
(byte) a#0 := (byte) $2
|
||||
to: INC@2
|
||||
INC@2:
|
||||
(byte) i#4 := phi(INC@2/i#1)
|
||||
(byte) a#4 := phi(INC@1/a#0)
|
||||
(byte) INC.a#1 := a#4
|
||||
to: inc@2
|
||||
inc@2: from inc@1
|
||||
(byte) i#4 := phi(inc@2/i#1)
|
||||
(byte) a#4 := phi(inc@1/a#0)
|
||||
(byte) inc.a#1 := a#4
|
||||
(byte) i#2 := i#4 + 1
|
||||
(byte§) $3 := INC.a#1 + i#2
|
||||
(byte§) $3 := inc.a#1 + i#2
|
||||
(byte) a#1 := (byte) $3
|
||||
to: @1
|
||||
@1:
|
||||
(byte) i#3 := phi(INC@2/i#2)
|
||||
(byte) a#3 := phi(INC@2/a#1)
|
||||
@1: from inc@2
|
||||
(byte) i#3 := phi(inc@2/i#2)
|
||||
(byte) a#3 := phi(inc@2/a#1)
|
||||
(byte) a#2 := a#3 + i#3;
|
||||
to: @END
|
||||
|
||||
|
||||
// Inline call (SSA) - optimized
|
||||
@BEGIN:
|
||||
(byte) i#3 := 7
|
||||
|
Loading…
Reference in New Issue
Block a user