1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-20 02:32:36 +00:00

Typified all Symbols

This commit is contained in:
Jesper Gravgaard 2017-05-13 16:20:58 +02:00
parent 3b8580498b
commit 73fa2839e0
18 changed files with 374 additions and 276 deletions

View File

@ -7,7 +7,7 @@ import java.util.List;
* The connections defines the control flow of the program. */
public class ControlFlowBlock {
private Symbol label;
private Label label;
private List<ControlFlowBlock> predecessors;
@ -17,7 +17,7 @@ public class ControlFlowBlock {
private ControlFlowBlock conditionalSuccessor;
public ControlFlowBlock(Symbol label) {
public ControlFlowBlock(Label label) {
this.label = label;
this.statements = new ArrayList<>();
this.predecessors = new ArrayList<>();
@ -25,7 +25,7 @@ public class ControlFlowBlock {
this.conditionalSuccessor = null;
}
public Symbol getLabel() {
public Label getLabel() {
return label;
}
@ -65,7 +65,7 @@ public class ControlFlowBlock {
return statements;
}
public void addPhiStatement(Symbol newVersion) {
public void addPhiStatement(VariableVersion newVersion) {
statements.add(0, new StatementPhi(newVersion));
}

View File

@ -0,0 +1,51 @@
package dk.camelot64.kickc.icl;
/** A Symbol (variable, jump label, etc.) */
public class Label implements Symbol {
/** The name of the label. */
private String name;
private boolean intermediate;
public Label(String name, boolean intermediate) {
this.name = name;
this.intermediate = intermediate;
}
public String getName() {
return name;
}
public boolean isIntermediate() {
return intermediate;
}
public SymbolType getType() {
return SymbolType.LABEL;
}
@Override
public String toString() {
return "("+getType().getTypeName() + ") "+name;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Label that = (Label) o;
return name.equals(that.name);
}
@Override
public int hashCode() {
return name.hashCode();
}
}

View File

@ -9,17 +9,17 @@ import java.util.Map;
public class PassGenerateControlFlowGraph {
public static final String FIRST_BLOCK_NAME = "@0";
private SymbolManager symbolManager;
private SymbolTable symbolTable;
private Map<Symbol, ControlFlowBlock> blocks;
private ControlFlowBlock firstBlock;
public PassGenerateControlFlowGraph(SymbolManager symbolManager) {
this.symbolManager = symbolManager;
public PassGenerateControlFlowGraph(SymbolTable symbolTable) {
this.symbolTable = symbolTable;
this.blocks = new LinkedHashMap<>();
}
public ControlFlowGraph generate(StatementSequence sequence) {
this.firstBlock = getOrCreateBlock(symbolManager.newNamedJumpLabel(FIRST_BLOCK_NAME));
this.firstBlock = getOrCreateBlock(symbolTable.newNamedJumpLabel(FIRST_BLOCK_NAME));
ControlFlowBlock currentBlock = this.firstBlock;
for (Statement statement : sequence.getStatements()) {
if(statement instanceof StatementJumpTarget) {
@ -33,13 +33,13 @@ public class PassGenerateControlFlowGraph {
ControlFlowBlock jmpBlock = getOrCreateBlock(statementJump.getDestination());
currentBlock.setDefaultSuccessor(jmpBlock);
jmpBlock.addPredecessor(currentBlock);
ControlFlowBlock nextBlock = getOrCreateBlock(symbolManager.newIntermediateJumpLabel());
ControlFlowBlock nextBlock = getOrCreateBlock(symbolTable.newIntermediateJumpLabel());
currentBlock = nextBlock;
} else if(statement instanceof StatementConditionalJump) {
currentBlock.addStatement(statement);
StatementConditionalJump statementConditionalJump = (StatementConditionalJump) statement;
ControlFlowBlock jmpBlock = getOrCreateBlock(statementConditionalJump.getDestination());
ControlFlowBlock nextBlock = getOrCreateBlock(symbolManager.newIntermediateJumpLabel());
ControlFlowBlock nextBlock = getOrCreateBlock(symbolTable.newIntermediateJumpLabel());
currentBlock.setDefaultSuccessor(nextBlock);
currentBlock.setConditionalSuccessor(jmpBlock);
nextBlock.addPredecessor(currentBlock);
@ -74,11 +74,11 @@ public class PassGenerateControlFlowGraph {
}
for (ControlFlowBlock block : remove) {
blocks.remove(block.getLabel());
symbolManager.remove(block.getLabel());
symbolTable.remove(block.getLabel());
}
}
private ControlFlowBlock getOrCreateBlock(Symbol label) {
private ControlFlowBlock getOrCreateBlock(Label label) {
ControlFlowBlock block = blocks.get(label);
if(block==null) {
block = new ControlFlowBlock(label);

View File

@ -10,10 +10,10 @@ import java.util.Map;
*/
public class PassGenerateSingleStaticAssignmentForm {
private SymbolManager symbols;
private SymbolTable symbols;
private ControlFlowGraph controlFlowGraph;
public PassGenerateSingleStaticAssignmentForm(SymbolManager symbols, ControlFlowGraph controlFlowGraph) {
public PassGenerateSingleStaticAssignmentForm(SymbolTable symbols, ControlFlowGraph controlFlowGraph) {
this.symbols = symbols;
this.controlFlowGraph = controlFlowGraph;
}
@ -21,25 +21,24 @@ public class PassGenerateSingleStaticAssignmentForm {
public void generate() {
versionAllAssignments();
versionAllUses();
boolean done = false;
boolean done;
do {
System.out.println("Completing Phi functions...");
done = completePhiFunctions();
} while (!done);
}
/** Version all non-versioned non-intermediary being assigned a value. */
private void versionAllAssignments() {
for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) {
for (Statement statement : block.getStatements()) {
if (statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
Symbol assignedSymbol = (Symbol) assignment.getlValue();
if (!assignedSymbol.isIntermediate() && !assignedSymbol.isVersioned()) {
LValue lValue = assignment.getlValue();
if(lValue instanceof VariableUnversioned) {
// Assignment to a non-versioned non-intermediary variable
Symbol version = symbols.createVersion(assignedSymbol);
VariableUnversioned assignedSymbol = (VariableUnversioned) lValue;
VariableVersion version = symbols.createVersion(assignedSymbol);
assignment.setLValue(version);
}
}
@ -51,33 +50,34 @@ public class PassGenerateSingleStaticAssignmentForm {
private void versionAllUses() {
for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) {
// Newest version of variables in the block.
Map<Symbol, Symbol> blockVersions = new HashMap<>();
Map<VariableUnversioned, VariableVersion> blockVersions = new HashMap<>();
// New phi functions introduced in the block to create versions of variables.
Map<Symbol, Symbol> blockNewPhis = new HashMap<>();
Map<VariableUnversioned, VariableVersion> blockNewPhis = new HashMap<>();
for (Statement statement : block.getStatements()) {
if (statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
{
Symbol version = findOrCreateVersion(assignment.getRValue1(), blockVersions, blockNewPhis);
VariableVersion version = findOrCreateVersion(assignment.getRValue1(), blockVersions, blockNewPhis);
if (version != null) {
assignment.setRValue1(version);
}
}
{
Symbol version = findOrCreateVersion(assignment.getRValue2(), blockVersions, blockNewPhis);
VariableVersion version = findOrCreateVersion(assignment.getRValue2(), blockVersions, blockNewPhis);
if (version != null) {
assignment.setRValue2(version);
}
}
// Update map of versions encountered in the block
Symbol lSymbol = (Symbol) assignment.getlValue();
if (lSymbol.isVersioned()) {
blockVersions.put(lSymbol.getVersionOf(), lSymbol);
LValue lValue = assignment.getlValue();
if (lValue instanceof VariableVersion) {
VariableVersion versioned = (VariableVersion) lValue;
blockVersions.put(versioned.getVersionOf(), versioned);
}
}
}
// Add new Phi functions to block
for (Symbol symbol : blockNewPhis.keySet()) {
for (VariableUnversioned symbol : blockNewPhis.keySet()) {
block.addPhiStatement(blockNewPhis.get(symbol));
}
}
@ -92,22 +92,23 @@ public class PassGenerateSingleStaticAssignmentForm {
* @param blockNewPhis New versions to be created as phi-functions. Modified if a new phi-function needs to be created.
* @return Null if the rValue does not need versioning. The versioned symbol to use if it does.
*/
private Symbol findOrCreateVersion(RValue rValue, Map<Symbol, Symbol> blockVersions, Map<Symbol, Symbol> blockNewPhis) {
Symbol version = null;
if (rValue instanceof Symbol) {
Symbol rSymbol = (Symbol) rValue;
if (!rSymbol.isIntermediate() && !rSymbol.isVersioned()) {
// rValue needs versioning - look for version in statements
version = blockVersions.get(rSymbol);
if (version == null) {
// look for version in new phi functions
version = blockNewPhis.get(rSymbol);
}
if (version == null) {
// create a new phi function
version = symbols.createVersion(rSymbol);
blockNewPhis.put(rSymbol, version);
}
private VariableVersion findOrCreateVersion(
RValue rValue,
Map<VariableUnversioned, VariableVersion> blockVersions,
Map<VariableUnversioned, VariableVersion> blockNewPhis) {
VariableVersion version = null;
if (rValue instanceof VariableUnversioned) {
// rValue needs versioning - look for version in statements
VariableUnversioned rSymbol = (VariableUnversioned) rValue;
version = blockVersions.get(rSymbol);
if (version == null) {
// look for version in new phi functions
version = blockNewPhis.get(rSymbol);
}
if (version == null) {
// create a new phi function
version = symbols.createVersion(rSymbol);
blockNewPhis.put(rSymbol, version);
}
}
return version;
@ -118,20 +119,20 @@ public class PassGenerateSingleStaticAssignmentForm {
* false if new phis were added , meaning another iteration is needed.
* */
private boolean completePhiFunctions() {
Map<ControlFlowBlock, Map<Symbol, Symbol>> newPhis = new HashMap<>();
Map<Symbol, Map<Symbol, Symbol>> symbolMap = buildSymbolMap();
Map<ControlFlowBlock, Map<VariableUnversioned, VariableVersion>> newPhis = new HashMap<>();
Map<Label, Map<VariableUnversioned, VariableVersion>> symbolMap = buildSymbolMap();
for (ControlFlowBlock block : this.controlFlowGraph.getAllBlocks()) {
for (Statement statement : block.getStatements()) {
if (statement instanceof StatementPhi) {
StatementPhi phi = (StatementPhi) statement;
if (phi.getPreviousVersions().isEmpty()) {
Symbol versioned = phi.getlValue();
Symbol unversioned = versioned.getVersionOf();
VariableVersion versioned = phi.getlValue();
VariableUnversioned unversioned = versioned.getVersionOf();
for (ControlFlowBlock predecessor : block.getPredecessors()) {
Symbol previousSymbol = symbolMap.get(predecessor.getLabel()).get(unversioned);
VariableVersion previousSymbol = symbolMap.get(predecessor.getLabel()).get(unversioned);
if (previousSymbol == null) {
// No previous symbol found in predecessor block. Look in new a phi functions.
Map<Symbol, Symbol> predecessorNewPhis = newPhis.get(predecessor);
Map<VariableUnversioned, VariableVersion> predecessorNewPhis = newPhis.get(predecessor);
if (predecessorNewPhis == null) {
predecessorNewPhis = new HashMap<>();
newPhis.put(predecessor, predecessorNewPhis);
@ -151,9 +152,9 @@ public class PassGenerateSingleStaticAssignmentForm {
}
// Ads new phi functions to blocks
for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) {
Map<Symbol, Symbol> blockNewPhis = newPhis.get(block);
Map<VariableUnversioned, VariableVersion> blockNewPhis = newPhis.get(block);
if(blockNewPhis!=null) {
for (Symbol symbol : blockNewPhis.keySet()) {
for (VariableUnversioned symbol : blockNewPhis.keySet()) {
block.addPhiStatement(blockNewPhis.get(symbol));
}
}
@ -165,33 +166,30 @@ public class PassGenerateSingleStaticAssignmentForm {
* Builds a map of all which versions each symbol has in each block.
* Maps Control Flow Block Label -> ( Unversioned Symbol -> Versioned Symbol) for all relevant symbols.
*/
private Map<Symbol, Map<Symbol, Symbol>> buildSymbolMap() {
Map<Symbol, Map<Symbol, Symbol>> symbolMap = new HashMap<>();
private Map<Label, Map<VariableUnversioned, VariableVersion>> buildSymbolMap() {
Map<Label, Map<VariableUnversioned, VariableVersion>> symbolMap = new HashMap<>();
for (ControlFlowBlock block : this.controlFlowGraph.getAllBlocks()) {
for (Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
LValue lValue = assignment.getlValue();
if(lValue instanceof Symbol) {
Symbol symbol = (Symbol) lValue;
if(symbol.isVersioned()) {
Symbol label = block.getLabel();
Symbol unversioned = symbol.getVersionOf();
Symbol versioned = symbol;
Map<Symbol, Symbol> blockMap = symbolMap.get(label);
if(blockMap == null) {
blockMap = new HashMap<>();
symbolMap.put(label, blockMap);
}
blockMap.put(unversioned, versioned);
if(lValue instanceof VariableVersion) {
VariableVersion versioned = (VariableVersion) lValue;
Label label = block.getLabel();
VariableUnversioned unversioned = versioned.getVersionOf();
Map<VariableUnversioned, VariableVersion> blockMap = symbolMap.get(label);
if (blockMap == null) {
blockMap = new HashMap<>();
symbolMap.put(label, blockMap);
}
blockMap.put(unversioned, versioned);
}
} else if(statement instanceof StatementPhi) {
StatementPhi phi = (StatementPhi) statement;
Symbol versioned = phi.getlValue();
Symbol unversioned = versioned.getVersionOf();
Symbol label = block.getLabel();
Map<Symbol, Symbol> blockMap = symbolMap.get(label);
VariableVersion versioned = phi.getlValue();
VariableUnversioned unversioned = versioned.getVersionOf();
Label label = block.getLabel();
Map<VariableUnversioned, VariableVersion> blockMap = symbolMap.get(label);
if(blockMap == null) {
blockMap = new HashMap<>();
symbolMap.put(label, blockMap);

View File

@ -7,11 +7,11 @@ import org.antlr.v4.runtime.tree.TerminalNode;
/** Generates program SSA form by visiting the ANTLR4 parse tree*/
public class PassGenerateStatementSequence extends KickCBaseVisitor<RValue> {
private SymbolManager symbolManager;
private SymbolTable symbolTable;
private StatementSequence sequence;
public PassGenerateStatementSequence() {
this.symbolManager = new SymbolManager();
this.symbolTable = new SymbolTable();
this.sequence = new StatementSequence();
}
@ -49,8 +49,8 @@ public class PassGenerateStatementSequence extends KickCBaseVisitor<RValue> {
@Override
public RValue visitStmtIfElse(KickCParser.StmtIfElseContext ctx) {
RValue rValue = this.visit(ctx.expr());
Symbol ifJumpLabel = symbolManager.newIntermediateJumpLabel();
Symbol elseJumpLabel = symbolManager.newIntermediateJumpLabel();
Label ifJumpLabel = symbolTable.newIntermediateJumpLabel();
Label elseJumpLabel = symbolTable.newIntermediateJumpLabel();
Statement ifJmpStmt = new StatementConditionalJump(rValue, ifJumpLabel);
sequence.addStatement(ifJmpStmt);
Statement elseJmpStmt = new StatementJump(elseJumpLabel);
@ -60,7 +60,7 @@ public class PassGenerateStatementSequence extends KickCBaseVisitor<RValue> {
this.visit(ctx.stmt(0));
KickCParser.StmtContext elseStmt = ctx.stmt(1);
if(elseStmt!=null) {
Symbol endJumpLabel = symbolManager.newIntermediateJumpLabel();
Label endJumpLabel = symbolTable.newIntermediateJumpLabel();
Statement endJmpStmt = new StatementJump(endJumpLabel);
sequence.addStatement(endJmpStmt);
StatementJumpTarget elseJumpTarget = new StatementJumpTarget(elseJumpLabel);
@ -77,9 +77,9 @@ public class PassGenerateStatementSequence extends KickCBaseVisitor<RValue> {
@Override
public RValue visitStmtWhile(KickCParser.StmtWhileContext ctx) {
Symbol beginJumpLabel = symbolManager.newIntermediateJumpLabel();
Symbol doJumpLabel = symbolManager.newIntermediateJumpLabel();
Symbol endJumpLabel = symbolManager.newIntermediateJumpLabel();
Label beginJumpLabel = symbolTable.newIntermediateJumpLabel();
Label doJumpLabel = symbolTable.newIntermediateJumpLabel();
Label endJumpLabel = symbolTable.newIntermediateJumpLabel();
StatementJumpTarget beginJumpTarget = new StatementJumpTarget(beginJumpLabel);
sequence.addStatement(beginJumpTarget);
RValue rValue = this.visit(ctx.expr());
@ -100,11 +100,11 @@ public class PassGenerateStatementSequence extends KickCBaseVisitor<RValue> {
@Override
public RValue visitStmtAssignment(KickCParser.StmtAssignmentContext ctx) {
if(ctx.TYPE()!=null) {
symbolManager.newVariableDeclaration(ctx.NAME().getText(), ctx.TYPE().getText());
symbolTable.newVariableDeclaration(ctx.NAME().getText(), ctx.TYPE().getText());
}
if(ctx.expr()!=null) {
RValue rValue = this.visit(ctx.expr());
Symbol variable = symbolManager.newVariableAssignment(ctx.NAME().getText());
VariableUnversioned variable = symbolTable.newVariableUsage(ctx.NAME().getText());
Statement stmt = new StatementAssignment(variable, rValue);
sequence.addStatement(stmt);
}
@ -139,7 +139,7 @@ public class PassGenerateStatementSequence extends KickCBaseVisitor<RValue> {
RValue right = this.visit(ctx.expr(1));
String op = ((TerminalNode)ctx.getChild(1)).getSymbol().getText();
Operator operator = new Operator(op);
Symbol tmpVar = symbolManager.newIntermediateAssignment();
VariableIntermediate tmpVar = symbolTable.newIntermediateAssignment();
Statement stmt = new StatementAssignment(tmpVar, left, operator, right);
sequence.addStatement(stmt);
return tmpVar;
@ -150,7 +150,7 @@ public class PassGenerateStatementSequence extends KickCBaseVisitor<RValue> {
RValue child = this.visit(ctx.expr());
String op = ((TerminalNode)ctx.getChild(0)).getSymbol().getText();
Operator operator = new Operator(op);
Symbol tmpVar = symbolManager.newIntermediateAssignment();
VariableIntermediate tmpVar = symbolTable.newIntermediateAssignment();
Statement stmt = new StatementAssignment(tmpVar, operator, child);
sequence.addStatement(stmt);
return tmpVar;
@ -163,15 +163,15 @@ public class PassGenerateStatementSequence extends KickCBaseVisitor<RValue> {
@Override
public RValue visitExprId(KickCParser.ExprIdContext ctx) {
return symbolManager.newVariableUsage(ctx.NAME().getText());
return symbolTable.newVariableUsage(ctx.NAME().getText());
}
public StatementSequence getSequence() {
return sequence;
}
public SymbolManager getSymbols() {
return this.symbolManager;
public SymbolTable getSymbols() {
return this.symbolTable;
}
}

View File

@ -5,11 +5,11 @@ package dk.camelot64.kickc.icl;
*/
public class PassTypeInference {
public void inferTypes(StatementSequence sequence, SymbolManager symbols) {
public void inferTypes(StatementSequence sequence, SymbolTable symbols) {
for (Statement statement : sequence.getStatements()) {
if (statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
Symbol symbol = (Symbol) assignment.getlValue();
Variable symbol = (Variable) assignment.getlValue();
if (SymbolType.VAR.equals(symbol.getType())) {
// Unresolved symbol - perform inference
Operator operator = assignment.getOperator();

View File

@ -9,9 +9,9 @@ package dk.camelot64.kickc.icl;
public class StatementConditionalJump implements Statement {
private RValue condition;
private Symbol destination;
private Label destination;
public StatementConditionalJump(RValue condition, Symbol destination) {
public StatementConditionalJump(RValue condition, Label destination) {
this.condition = condition;
this.destination = destination;
}
@ -20,7 +20,7 @@ public class StatementConditionalJump implements Statement {
return condition;
}
public Symbol getDestination() {
public Label getDestination() {
return destination;
}

View File

@ -8,13 +8,13 @@ package dk.camelot64.kickc.icl;
*/
public class StatementJump implements Statement {
private Symbol destination;
private Label destination;
public StatementJump(Symbol destination) {
public StatementJump(Label destination) {
this.destination = destination;
}
public Symbol getDestination() {
public Label getDestination() {
return destination;
}

View File

@ -5,13 +5,13 @@ package dk.camelot64.kickc.icl;
*/
public class StatementJumpTarget implements Statement {
private Symbol label;
private Label label;
public StatementJumpTarget(Symbol label) {
public StatementJumpTarget(Label label) {
this.label = label;
}
public Symbol getLabel() {
public Label getLabel() {
return label;
}

View File

@ -12,12 +12,12 @@ import java.util.List;
public class StatementPhi implements Statement {
/** The versioned variable being assigned a value by the statement. */
private Symbol lValue;
private VariableVersion lValue;
/** The previous version of the symbol from predeccesor control blocks. */
private List<PreviousSymbol> previousVersions;
public StatementPhi(Symbol lValue) {
public StatementPhi(VariableVersion lValue) {
this.lValue = lValue;
this.previousVersions = new ArrayList<>();
}
@ -28,9 +28,9 @@ public class StatementPhi implements Statement {
*/
public static class PreviousSymbol {
private ControlFlowBlock block;
private Symbol symbol;
private VariableVersion symbol;
public PreviousSymbol(ControlFlowBlock block, Symbol symbol) {
public PreviousSymbol(ControlFlowBlock block, VariableVersion symbol) {
this.block = block;
this.symbol = symbol;
}
@ -46,11 +46,11 @@ public class StatementPhi implements Statement {
}
public Symbol getlValue() {
public VariableVersion getlValue() {
return lValue;
}
public void addPreviousVersion(ControlFlowBlock block, Symbol symbol) {
public void addPreviousVersion(ControlFlowBlock block, VariableVersion symbol) {
previousVersions.add(new PreviousSymbol(block, symbol));
}

View File

@ -1,97 +1,10 @@
package dk.camelot64.kickc.icl;
/** A Symbol (variable, jump label, etc.) */
public class Symbol implements RValue, LValue {
public interface Symbol {
/** The name of the symbol. */
private String name;
public String getName();
/** The type of the symbol. VAR means tha type is unknown, and has not been inferred yet. */
private SymbolType type;
public SymbolType getType();
/** true if the symbol type is infered (not declared) */
private boolean inferredType;
/** true if this is an intermediate variable that is created as a part of evaluating an expression. */
private boolean intermediate;
/** If the symbol is a version of another symbol created during generation of single static assignment form (SSA) this contains the main symbol. */
private Symbol versionOf;
/** The number of the next version (if anyone versions this symbol)*/
private Integer nextVersionNumber;
public Symbol(String name, SymbolType type, boolean intermediate) {
this.name = name;
this.type = type;
this.intermediate = intermediate;
this.inferredType = false;
this.versionOf = null;
if(!intermediate) {
this.nextVersionNumber = 0;
}
}
Symbol(Symbol versionOf, int version) {
this.name = versionOf.getName() + "#" + version;
this.type = versionOf.getType();
this.intermediate = versionOf.isIntermediate();
this.inferredType = versionOf.isInferredType();
this.versionOf = versionOf;
this.nextVersionNumber = null;
}
public String getName() {
return name;
}
public SymbolType getType() {
return type;
}
public void setInferredType(SymbolType type) {
this.type = type;
this.inferredType = true;
}
public boolean isIntermediate() {
return intermediate;
}
/** Get the version number of the next version. (if anyone versions the symbol). */
int getNextVersionNumber() {
return nextVersionNumber++;
}
@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;
Symbol symbol = (Symbol) o;
if (!name.equals(symbol.name)) return false;
return type == symbol.type;
}
@Override
public int hashCode() {
int result = name.hashCode();
return result;
}
public boolean isInferredType() {
return inferredType;
}
public boolean isVersioned() {
return versionOf != null;
}
public Symbol getVersionOf() {
return versionOf;
}
}

View File

@ -1,79 +0,0 @@
package dk.camelot64.kickc.icl;
import java.util.*;
/**
* Manages symbols (variables, labels)
*/
public class SymbolManager {
private Map<String, Symbol> symbols;
private int intermediateVarCount = 0;
private int intermediateLabelCount = 1;
public SymbolManager() {
this.symbols = new LinkedHashMap<>();
}
private Symbol addSymbol(String name, SymbolType symbolType, boolean intermediate) {
if(symbols.get(name)!=null) {
throw new RuntimeException("Symbol already declared "+name);
}
Symbol symbol = new Symbol(name, symbolType, intermediate);
symbols.put(name, symbol);
return symbol;
}
public void newVariableDeclaration(String name, String type) {
SymbolType symbolType = SymbolType.get(type);
addSymbol(name, symbolType, false);
}
public Symbol newVariableAssignment(String varName) {
return symbols.get(varName);
}
public Symbol newVariableUsage(String varName) {
return symbols.get(varName);
}
public Symbol newIntermediateAssignment() {
String name = "$"+intermediateVarCount++;
Symbol symbol = addSymbol(name, SymbolType.VAR, true);
return symbol;
}
public Symbol newNamedJumpLabel(String name) {
Symbol symbol = addSymbol(name, SymbolType.LABEL, false);
return symbol;
}
public Symbol newIntermediateJumpLabel() {
String name = "@"+ intermediateLabelCount++;
Symbol symbol = addSymbol(name, SymbolType.LABEL, true);
return symbol;
}
@Override
public String toString() {
StringBuffer out = new StringBuffer();
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() + "\n");
}
return out.toString();
}
public void remove(Symbol symbol) {
symbols.remove(symbol.getName());
}
public Symbol createVersion(Symbol symbol) {
Symbol version = new Symbol(symbol, symbol.getNextVersionNumber());
symbols.put(version.getName(), version);
return version;
}
}

View File

@ -0,0 +1,79 @@
package dk.camelot64.kickc.icl;
import java.util.*;
/**
* Manages symbols (variables, labels)
*/
public class SymbolTable {
private Map<String, Symbol> symbols;
private int intermediateVarCount = 0;
private int intermediateLabelCount = 1;
public SymbolTable() {
this.symbols = new LinkedHashMap<>();
}
private Symbol addSymbol(Symbol symbol) {
if(symbols.get(symbol.getName())!=null) {
throw new RuntimeException("Symbol already declared "+symbol.getName());
}
symbols.put(symbol.getName(), symbol);
return symbol;
}
public VariableUnversioned newVariableDeclaration(String name, String type) {
SymbolType symbolType = SymbolType.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, SymbolType.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;
}
@Override
public String toString() {
StringBuffer out = new StringBuffer();
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() + "\n");
}
return out.toString();
}
public void remove(Symbol symbol) {
symbols.remove(symbol.getName());
}
public VariableVersion createVersion(VariableUnversioned symbol) {
VariableVersion version = new VariableVersion(symbol, symbol.getNextVersionNumber());
symbols.put(version.getName(), version);
return version;
}
}

View File

@ -0,0 +1,62 @@
package dk.camelot64.kickc.icl;
/** A Symbol (variable, jump label, etc.) */
public abstract class Variable implements Symbol, RValue, LValue {
/** 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. */
private SymbolType type;
/** true if the symbol type is infered (not declared) */
private boolean inferredType;
public Variable(String name, SymbolType type) {
this.name = name;
this.type = type;
this.inferredType = false;
}
public String getName() {
return name;
}
public SymbolType getType() {
return type;
}
public void setInferredType(SymbolType type) {
this.type = type;
this.inferredType = true;
}
public boolean isInferredType() {
return inferredType;
}
public abstract boolean isVersioned();
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;
}
@Override
public int hashCode() {
int result = name.hashCode();
return result;
}
}

View File

@ -0,0 +1,19 @@
package dk.camelot64.kickc.icl;
/** A Symbol (variable, jump label, etc.) */
public class VariableIntermediate extends Variable {
public VariableIntermediate(String name, SymbolType type) {
super(name, type);
}
@Override
public boolean isIntermediate() {
return true;
}
@Override
public boolean isVersioned() {
return false;
}
}

View File

@ -0,0 +1,28 @@
package dk.camelot64.kickc.icl;
/** A Symbol (variable, jump label, etc.) */
public class VariableUnversioned extends Variable {
/** The number of the next version */
private Integer nextVersionNumber;
public VariableUnversioned(String name, SymbolType type) {
super(name, type);
this.nextVersionNumber = 0;
}
/** Get the version number of the next version. (if anyone versions the symbol). */
int getNextVersionNumber() {
return nextVersionNumber++;
}
@Override
public boolean isVersioned() {
return false;
}
@Override
public boolean isIntermediate() {
return false;
}
}

View File

@ -0,0 +1,26 @@
package dk.camelot64.kickc.icl;
/** A Symbol (variable, jump label, etc.) */
public class VariableVersion extends Variable {
private VariableUnversioned versionOf;
public VariableVersion(VariableUnversioned versionOf, int version) {
super(versionOf.getName()+"#"+version, versionOf.getType());
this.versionOf = versionOf;
}
@Override
public boolean isVersioned() {
return true;
}
@Override
public boolean isIntermediate() {
return false;
}
public VariableUnversioned getVersionOf() {
return versionOf;
}
}

View File

@ -21,14 +21,15 @@ public class main {
PassGenerateStatementSequence passGenerateStatementSequence = new PassGenerateStatementSequence();
passGenerateStatementSequence.generate(file);
StatementSequence statementSequence = passGenerateStatementSequence.getSequence();
SymbolManager symbolManager = passGenerateStatementSequence.getSymbols();
new PassTypeInference().inferTypes(statementSequence, symbolManager);
PassGenerateControlFlowGraph passGenerateControlFlowGraph = new PassGenerateControlFlowGraph(symbolManager);
SymbolTable symbolTable = passGenerateStatementSequence.getSymbols();
new PassTypeInference().inferTypes(statementSequence, symbolTable);
PassGenerateControlFlowGraph passGenerateControlFlowGraph = new PassGenerateControlFlowGraph(symbolTable);
ControlFlowGraph controlFlowGraph = passGenerateControlFlowGraph.generate(statementSequence);
PassGenerateSingleStaticAssignmentForm passGenerateSingleStaticAssignmentForm = new PassGenerateSingleStaticAssignmentForm(symbolManager, controlFlowGraph);
PassGenerateSingleStaticAssignmentForm passGenerateSingleStaticAssignmentForm = new PassGenerateSingleStaticAssignmentForm(
symbolTable, controlFlowGraph);
passGenerateSingleStaticAssignmentForm.generate();
System.out.println("SYMBOLS");
System.out.println(symbolManager.toString());
System.out.println(symbolTable.toString());
System.out.println("PROGRAM");
System.out.println(statementSequence.toString());
System.out.println("CONTROL FLOW GRAPH");