1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-08-02 09:29:35 +00:00

Looking at function calls

This commit is contained in:
jespergravgaard 2017-06-05 16:01:50 +02:00
parent 2dedf8263b
commit 03ee43c3b7
34 changed files with 854 additions and 412 deletions

View File

@ -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);
}

View File

@ -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();

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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

View File

@ -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());
}
}
}
}

View 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();
}
}

View File

@ -8,7 +8,7 @@ package dk.camelot64.kickc.icl;
* <br>
* <i> lValue := rValue1 &lt;operator&gt; rValue2 </i>
*/
public class StatementAssignment implements Statement {
public class StatementAssignment implements StatementLValue {
/** The variable being assigned a value by the statement. */
private LValue lValue;

View 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();
}
}

View File

@ -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();
}

View File

@ -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) {

View 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);
}

View File

@ -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()+":";
}

View File

@ -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();

View 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()+":";
}
}

View 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);
}
}

View File

@ -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");

View File

@ -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();
}

View File

@ -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();
}
}

View File

@ -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;

View 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() + "()";
}
}

View 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";
}
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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++;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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 {

View File

@ -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);

View 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;
}

View 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;
}

View File

@ -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