1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-08-11 17:25:41 +00:00

Implementing JSON serialization of ICL

This commit is contained in:
Jesper Gravgaard
2017-07-18 22:49:25 +02:00
parent 1b0b81baf2
commit 819c904419
57 changed files with 787 additions and 237 deletions

View File

@@ -0,0 +1,14 @@
<component name="libraryTable">
<library name="com.fasterxml.jackson.core:jackson-core:2.8.9" type="repository">
<properties maven-id="com.fasterxml.jackson.core:jackson-core:2.8.9" />
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/jackson-core-2.8.9.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$PROJECT_DIR$/lib/jackson-core-2.8.9-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/jackson-core-2.8.9-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -0,0 +1,16 @@
<component name="libraryTable">
<library name="com.fasterxml.jackson.core:jackson-databind:2.8.9" type="repository">
<properties maven-id="com.fasterxml.jackson.core:jackson-databind:2.8.9" />
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/jackson-databind-2.8.9.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/jackson-annotations-2.8.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/jackson-core-2.8.9.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$PROJECT_DIR$/lib/jackson-databind-2.8.9-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/jackson-databind-2.8.9-sources.jar!/" />
</SOURCES>
</library>
</component>

15
.idea/libraries/junit_junit_4_12.xml generated Normal file
View File

@@ -0,0 +1,15 @@
<component name="libraryTable">
<library name="junit:junit:4.12" type="repository">
<properties maven-id="junit:junit:4.12" />
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/junit-4.12.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/hamcrest-core-1.3.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$PROJECT_DIR$/lib/junit-4.12-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/junit-4.12-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -8,5 +8,8 @@
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="org.antlr:antlr4:4.7" level="project" />
<orderEntry type="library" name="com.fasterxml.jackson.core:jackson-core:2.8.9" level="project" />
<orderEntry type="library" name="com.fasterxml.jackson.core:jackson-databind:2.8.9" level="project" />
<orderEntry type="library" name="junit:junit:4.12" level="project" />
</component>
</module>

BIN
lib/hamcrest-core-1.3.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lib/jackson-core-2.8.9.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lib/junit-4.12-javadoc.jar Normal file

Binary file not shown.

BIN
lib/junit-4.12-sources.jar Normal file

Binary file not shown.

BIN
lib/junit-4.12.jar Normal file

Binary file not shown.

View File

@@ -66,7 +66,7 @@ public class Compiler {
Pass1GenerateStatementSequence pass1GenerateStatementSequence = new Pass1GenerateStatementSequence(log);
pass1GenerateStatementSequence.generate(file);
StatementSequence statementSequence = pass1GenerateStatementSequence.getSequence();
Scope programScope = pass1GenerateStatementSequence.getProgramScope();
ProgramScope programScope = pass1GenerateStatementSequence.getProgramScope();
Pass1TypeInference pass1TypeInference = new Pass1TypeInference();
pass1TypeInference.inferTypes(statementSequence, programScope);

View File

@@ -21,7 +21,7 @@ public class AsmFragment {
/**
* The symbol table.
*/
private Scope symbols;
private ProgramScope symbols;
/**
* Binding of named values in the fragment to values (constants, variables, ...) .
@@ -33,26 +33,26 @@ public class AsmFragment {
*/
private String signature;
public AsmFragment(StatementConditionalJump conditionalJump, ControlFlowBlock block, Scope symbols, ControlFlowGraph graph) {
public AsmFragment(StatementConditionalJump conditionalJump, ControlFlowBlock block, ProgramScope symbols, ControlFlowGraph graph) {
this.bindings = new LinkedHashMap<>();
this.symbols = symbols;
String conditionalJumpSignature = conditionalJumpSignature(conditionalJump, block, graph);
setSignature(conditionalJumpSignature);
}
public AsmFragment(StatementAssignment assignment, Scope symbols) {
public AsmFragment(StatementAssignment assignment, ProgramScope symbols) {
this.bindings = new LinkedHashMap<>();
this.symbols = symbols;
setSignature(assignmentSignature(assignment.getLValue(), assignment.getRValue1(), assignment.getOperator(), assignment.getRValue2()));
setSignature(assignmentSignature(assignment.getlValue(), assignment.getrValue1(), assignment.getOperator(), assignment.getrValue2()));
}
public AsmFragment(LValue lValue, RValue rValue, Scope symbols) {
public AsmFragment(LValue lValue, RValue rValue, ProgramScope symbols) {
this.bindings = new LinkedHashMap<>();
this.symbols = symbols;
setSignature(assignmentSignature(lValue, null, null, rValue));
}
public AsmFragment(StatementAssignment assignment, StatementAssignment assignmentAlu, Scope symbols) {
public AsmFragment(StatementAssignment assignment, StatementAssignment assignmentAlu, ProgramScope symbols) {
this.bindings = new LinkedHashMap<>();
this.symbols = symbols;
setSignature(assignmentWithAluSignature(assignment, assignmentAlu));
@@ -60,21 +60,21 @@ public class AsmFragment {
}
private String assignmentWithAluSignature(StatementAssignment assignment, StatementAssignment assignmentAlu) {
RValue assignmentRValue2 = assignment.getRValue2();
RValue assignmentRValue2 = assignment.getrValue2();
RegisterAllocation.Register rVal2Register = symbols.getRegister((Variable) assignmentRValue2);
if(!rVal2Register.getType().equals(RegisterAllocation.RegisterType.REG_ALU_BYTE)) {
throw new RuntimeException("Error! ALU register only allowed as rValue2. "+assignment);
}
StringBuilder signature = new StringBuilder();
signature.append(bind(assignment.getLValue()));
signature.append(bind(assignment.getlValue()));
signature.append("=");
if (assignment.getRValue1() != null) {
signature.append(bind(assignment.getRValue1()));
if (assignment.getrValue1() != null) {
signature.append(bind(assignment.getrValue1()));
}
if (assignment.getOperator() != null) {
signature.append(getOperatorFragmentName(assignment.getOperator()));
}
signature.append(assignmentRightSideSignature(assignmentAlu.getRValue1(), assignmentAlu.getOperator(), assignmentAlu.getRValue2()));
signature.append(assignmentRightSideSignature(assignmentAlu.getrValue1(), assignmentAlu.getOperator(), assignmentAlu.getrValue2()));
return signature.toString();
}

View File

@@ -49,7 +49,7 @@ public class ControlFlowGraph {
for (Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(assignment.getLValue().equals(variable)) {
if(assignment.getlValue().equals(variable)) {
return assignment;
}
}

View File

@@ -1,6 +1,5 @@
package dk.camelot64.kickc.icl;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
@@ -116,7 +115,7 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
@Override
public StatementPhi visitPhi(StatementPhi phi) {
VariableVersion lValue = phi.getLValue();
VariableVersion lValue = phi.getlValue();
StatementPhi copyPhi = new StatementPhi(lValue);
for (StatementPhi.PreviousSymbol origPreviousVersion : phi.getPreviousVersions()) {
RValue rValue = origPreviousVersion.getRValue();
@@ -128,10 +127,10 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
@Override
public StatementAssignment visitAssignment(StatementAssignment origAssignment) {
LValue lValue = origAssignment.getLValue();
RValue rValue1 = origAssignment.getRValue1();
LValue lValue = origAssignment.getlValue();
RValue rValue1 = origAssignment.getrValue1();
Operator operator = origAssignment.getOperator();
RValue rValue2 = origAssignment.getRValue2();
RValue rValue2 = origAssignment.getrValue2();
return new StatementAssignment(lValue, rValue1, operator, rValue2);
}
@@ -158,7 +157,7 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
@Override
public StatementCall visitCall(StatementCall callLValue) {
LValue lValue = callLValue.getLValue();
LValue lValue = callLValue.getlValue();
String procedureName = callLValue.getProcedureName();
List<RValue> parameters = callLValue.getParameters();
return new StatementCall(lValue, procedureName, parameters);

View File

@@ -1,5 +1,9 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
/** A jump label */
public class Label implements Symbol {
@@ -17,6 +21,16 @@ public class Label implements Symbol {
this.intermediate = intermediate;
}
@JsonCreator
public Label(
@JsonProperty("name") String name,
@JsonProperty("intermediate") boolean intermediate) {
this.name = name;
this.scope = null;
this.intermediate = intermediate;
}
@Override
public String getLocalName() {
return name;
}
@@ -26,6 +40,11 @@ public class Label implements Symbol {
return scope;
}
@Override
public void setScope(Scope scope) {
this.scope = scope;
}
@Override
public int getScopeDepth() {
if(scope==null) {
@@ -44,6 +63,7 @@ public class Label implements Symbol {
return intermediate;
}
@JsonIgnore
public SymbolType getType() {
return SymbolTypeBasic.LABEL;
}
@@ -61,13 +81,12 @@ public class Label implements Symbol {
if (intermediate != label.intermediate) return false;
if (!name.equals(label.name)) return false;
return scope != null ? scope.equals(label.scope) : label.scope == null;
return getFullName().equals(label.getFullName());
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + (scope != null ? scope.hashCode() : 0);
int result = getFullName().hashCode();
result = 31 * result + (intermediate ? 1 : 0);
return result;
}

View File

@@ -1,25 +1,52 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/** Symbol describing a procedure/function */
public class Procedure extends Scope {
private final SymbolType returnType;
private List<Variable> parameters;
private List<String> parameterNames;
public Procedure(String name, SymbolType returnType, Scope parentScope) {
super(name, new SymbolTypeProcedure(returnType), parentScope);
super(name, parentScope);
this.returnType = returnType;
}
public Procedure(
@JsonProperty("name") String name,
@JsonProperty("returntype") SymbolType returnType,
@JsonProperty("parameterNames") List<String> parameterNames,
@JsonProperty("symbols") HashMap<String, Symbol> symbols,
@JsonProperty("intermediateVarCount") int intermediateVarCount,
@JsonProperty("intermediateLabelCount") int intermediateLabelCount) {
super(name, symbols, intermediateVarCount, intermediateLabelCount);
this.returnType = returnType;
this.parameterNames = parameterNames;
}
public List<String> getParameterNames() {
return parameterNames;
}
public void setParameterNames(List<String> parameterNames) {
this.parameterNames = parameterNames;
}
public void setParameters(List<Variable> parameters) {
this.parameters = parameters;
this.parameterNames = new ArrayList<>();
for (Variable parameter : parameters) {
add(parameter);
parameterNames.add(parameter.getLocalName());
}
}
@JsonIgnore
public Label getLabel() {
return new Label(getFullName(), getScope(), false);
}
@@ -28,7 +55,12 @@ public class Procedure extends Scope {
return returnType;
}
@JsonIgnore
public List<Variable> getParameters() {
ArrayList<Variable> parameters = new ArrayList<>();
for (String name : parameterNames) {
parameters.add(getScope().getVariable(name));
}
return parameters;
}
@@ -44,8 +76,8 @@ public class Procedure extends Scope {
res.append(getFullName());
res.append("(");
boolean first = true;
if(parameters!=null) {
for (Variable parameter : parameters) {
if(parameterNames !=null) {
for (Variable parameter : getParameters()) {
if (!first) res.append(" , ");
first = false;
res.append(parameter.getTypedName());
@@ -63,6 +95,22 @@ public class Procedure extends Scope {
return res.toString();
}
@Override
public SymbolType getType() {
return new SymbolTypeProcedure(returnType);
}
@Override
RegisterAllocation getAllocation() {
if(getScope()!=null) {
return getScope().getAllocation();
} else {
return null;
}
}
@Override
public String toString() {
return getTypedName();

View File

@@ -0,0 +1,36 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
/** A KickC Intermediate Compiler Language (ICL) Program */
public class Program {
/** The main scope. */
private Scope scope;
/** The control flow graph. */
private ControlFlowGraph graph;
@JsonCreator
public Program(
@JsonProperty("scope") Scope scope,
@JsonProperty("graph") ControlFlowGraph graph) {
this.scope = scope;
this.graph = graph;
}
public Scope getScope() {
return scope;
}
public void setScope(Scope scope) {
this.scope = scope;
}
public ControlFlowGraph getGraph() {
return graph;
}
public void setGraph(ControlFlowGraph graph) {
this.graph = graph;
}
}

View File

@@ -0,0 +1,73 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.HashMap;
/** The program scope containing the symbols of a program */
public class ProgramScope extends Scope {
private RegisterAllocation allocation;
public ProgramScope() {
super("", null);
}
@JsonCreator
public ProgramScope(
@JsonProperty("name") String name,
@JsonProperty("symbols") HashMap<String, Symbol> symbols,
@JsonProperty("intermediateVarCount") int intermediateVarCount,
@JsonProperty("intermediateLabelCount") int intermediateLabelCount,
@JsonProperty("allocation") RegisterAllocation allocation) {
super(name, symbols, intermediateVarCount, intermediateLabelCount);
this.allocation = allocation;
}
@Override
public SymbolType getType() {
return new SymbolTypeProgram();
}
public void setAllocation(RegisterAllocation allocation) {
this.allocation = allocation;
}
public RegisterAllocation.Register getRegister(Variable variable) {
RegisterAllocation.Register register = null;
if (allocation != null) {
register = allocation.getRegister(variable);
}
return register;
}
@Override
RegisterAllocation getAllocation() {
return allocation;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
ProgramScope that = (ProgramScope) o;
return allocation != null ? allocation.equals(that.allocation) : that.allocation == null;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (allocation != null ? allocation.hashCode() : 0);
return result;
}
}

View File

@@ -8,7 +8,7 @@ import java.util.Map;
/** Register Allocation for Variable Symbols */
public class RegisterAllocation {
private Map<Variable, Register> allocation;
private Map<String, Register> allocation;
public RegisterAllocation() {
this.allocation = new LinkedHashMap<>();
@@ -21,11 +21,18 @@ public class RegisterAllocation {
* @return The allocated register.
*/
public Register getRegister(Variable variable) {
return allocation.get(variable);
return allocation.get(variable.getFullName());
}
public Register getRegister(String varFullName) {
return allocation.get(varFullName);
}
public void allocate(Variable variable, Register register) {
allocation.put(variable, register);
if(variable!=null) {
allocation.put(variable.getFullName(), register);
}
}
/** A register used for storing a single variable. */
@@ -287,9 +294,9 @@ public class RegisterAllocation {
@Override
public String toString() {
StringBuffer out = new StringBuffer();
for (Variable variable : allocation.keySet()) {
Register register = getRegister(variable);
out.append(variable+" : "+register+"\n");
for (String varName: allocation.keySet()) {
Register register = getRegister(varName);
out.append(varName+" : "+register+"\n");
}
return out.toString();
}

View File

@@ -1,34 +1,54 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.*;
/**
* Manages symbols (variables, labels)
*/
public class Scope implements Symbol {
public abstract class Scope implements Symbol {
private String name;
private SymbolType type;
private Map<String, Symbol> symbols;
private HashMap<String, Symbol> symbols;
private int intermediateVarCount = 0;
private int intermediateLabelCount = 1;
private RegisterAllocation allocation;
@JsonIgnore
private Scope parentScope;
public Scope(String name, SymbolType type, Scope parentScope) {
public Scope(String name, Scope parentScope) {
this.name = name;
this.type = type;
this.parentScope = parentScope;
this.symbols = new LinkedHashMap<>();
}
@JsonCreator
public Scope(
@JsonProperty("name") String name,
@JsonProperty("symbols") HashMap<String, Symbol> symbols,
@JsonProperty("intermediateVarCount") int intermediateVarCount,
@JsonProperty("intermediateLabelCount") int intermediateLabelCount) {
this.name = name;
this.symbols = symbols;
this.intermediateVarCount = intermediateVarCount;
this.intermediateLabelCount = intermediateLabelCount;
for (Symbol symbol : symbols.values()) {
symbol.setScope(this);
}
}
public Scope() {
this.name = "";
this.type = new SymbolTypeProgram();
this.parentScope = null;
this.symbols = new LinkedHashMap<>();
}
public HashMap<String, Symbol> getSymbols() {
return symbols;
}
@Override
public String getLocalName() {
return name;
@@ -51,21 +71,23 @@ public class Scope implements Symbol {
@Override
@JsonIgnore
public Scope getScope() {
return parentScope;
}
@Override
@JsonIgnore
public String getTypedName() {
return "(" + getType().getTypeName() + ") " + getFullName();
}
@Override
public SymbolType getType() {
return type;
}
@JsonIgnore
public abstract SymbolType getType();
@Override
@JsonIgnore
public int getScopeDepth() {
if (parentScope == null) {
return 0;
@@ -127,7 +149,7 @@ public class Scope implements Symbol {
return (Variable) getSymbol(name);
}
@JsonIgnore
public Collection<Variable> getAllVariables() {
Collection<Variable> vars = new ArrayList<>();
for (Symbol symbol : symbols.values()) {
@@ -174,28 +196,15 @@ public class Scope implements Symbol {
}
}
public void setAllocation(RegisterAllocation allocation) {
this.allocation = allocation;
for (Symbol symbol : symbols.values()) {
if(symbol instanceof Scope) {
((Scope) symbol).setAllocation(allocation);
}
}
}
public RegisterAllocation.Register getRegister(Variable variable) {
RegisterAllocation.Register register = null;
if (allocation != null) {
register = allocation.getRegister(variable);
}
return register;
}
abstract RegisterAllocation getAllocation();
@JsonIgnore
public String getSymbolTableContents() {
StringBuilder res = new StringBuilder();
Set<String> names = symbols.keySet();
List<String> sortedNames = new ArrayList<>(names);
Collections.sort(sortedNames);
RegisterAllocation allocation = getAllocation();
for (String name : sortedNames) {
Symbol symbol = symbols.get(name);
if (symbol instanceof Scope) {
@@ -203,8 +212,8 @@ public class Scope implements Symbol {
} else {
res.append(symbol.toString());
}
if (symbol instanceof Variable) {
RegisterAllocation.Register register = getRegister((Variable) symbol);
if (symbol instanceof Variable && allocation!=null) {
RegisterAllocation.Register register = allocation.getRegister((Variable) symbol);
if (register != null) {
res.append(" " + register);
}
@@ -214,7 +223,47 @@ public class Scope implements Symbol {
return res.toString();
}
public Collection<Symbol> getSymbols() {
@JsonIgnore
public Collection<Symbol> getAllSymbols() {
return symbols.values();
}
@Override
public void setScope(Scope scope) {
this.parentScope = scope;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Scope scope = (Scope) o;
if (intermediateVarCount != scope.intermediateVarCount) {
return false;
}
if (intermediateLabelCount != scope.intermediateLabelCount) {
return false;
}
if (!name.equals(scope.name)) {
return false;
}
if (!symbols.equals(scope.symbols)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + intermediateVarCount;
result = 31 * result + intermediateLabelCount;
return result;
}
}

View File

@@ -1,5 +1,9 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
/**
* Single Static Assignment Form Statement.
* Intermediate form used for compiler optimization.
@@ -8,11 +12,11 @@ package dk.camelot64.kickc.icl;
* <br>
* <i> lValue := rValue1 &lt;operator&gt; rValue2 </i>
*/
@JsonPropertyOrder({"lValue", "rValue1", "operator", "rValue2"})
public class StatementAssignment implements StatementLValue {
/** The variable being assigned a value by the statement. */
private LValue lValue;
private RValue rValue1;
private Operator operator;
private RValue rValue2;
@@ -24,7 +28,12 @@ public class StatementAssignment implements StatementLValue {
this.rValue2 = rValue2;
}
public StatementAssignment(LValue lValue, RValue rValue1, Operator operator, RValue rValue2) {
@JsonCreator
public StatementAssignment(
@JsonProperty("lValue1") LValue lValue,
@JsonProperty("rValue1") RValue rValue1,
@JsonProperty("operator") Operator operator,
@JsonProperty("rValue2") RValue rValue2) {
this.lValue = lValue;
this.rValue1 = rValue1;
this.operator = operator;
@@ -38,19 +47,19 @@ public class StatementAssignment implements StatementLValue {
this.rValue2 = rValue2;
}
public LValue getLValue() {
public LValue getlValue() {
return lValue;
}
public void setLValue(LValue lValue) {
public void setlValue(LValue lValue) {
this.lValue = lValue;
}
public RValue getRValue1() {
public RValue getrValue1() {
return rValue1;
}
public void setRValue1(RValue rValue1) {
public void setrValue1(RValue rValue1) {
this.rValue1 = rValue1;
}
@@ -58,11 +67,11 @@ public class StatementAssignment implements StatementLValue {
return operator;
}
public RValue getRValue2() {
public RValue getrValue2() {
return rValue2;
}
public void setRValue2(RValue rValue2) {
public void setrValue2(RValue rValue2) {
this.rValue2 = rValue2;
}

View File

@@ -23,11 +23,11 @@ public class StatementCall implements StatementLValue {
this.parametersByAssignment = false;
}
public LValue getLValue() {
public LValue getlValue() {
return lValue;
}
public void setLValue(LValue lValue) {
public void setlValue(LValue lValue) {
this.lValue = lValue;
}

View File

@@ -5,8 +5,8 @@ package dk.camelot64.kickc.icl;
*/
public interface StatementLValue extends Statement {
LValue getLValue();
LValue getlValue();
void setLValue(LValue lValue);
void setlValue(LValue lValue);
}

View File

@@ -56,12 +56,12 @@ public class StatementPhi implements StatementLValue {
}
}
public VariableVersion getLValue() {
public VariableVersion getlValue() {
return lValue;
}
@Override
public void setLValue(LValue lValue) {
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);
}

View File

@@ -1,17 +1,26 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonIgnore;
/** A Symbol (variable, jump label, etc.) */
public interface Symbol extends Value {
@JsonIgnore
String getLocalName();
@JsonIgnore
String getFullName();
@JsonIgnore
String getTypedName();
SymbolType getType();
@JsonIgnore
Scope getScope();
@JsonIgnore
int getScopeDepth();
void setScope(Scope scope);
}

View File

@@ -1,8 +1,18 @@
package dk.camelot64.kickc.icl;
/** Symbol Types */
public interface SymbolType {
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
/** Symbol Types */
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type")
@JsonSubTypes({
@JsonSubTypes.Type(value = SymbolTypeProgram.class, name = "program"),
@JsonSubTypes.Type(value = SymbolTypeBasic.class, name = "basic"),
@JsonSubTypes.Type(value = SymbolTypeArray.class, name = "array"),
@JsonSubTypes.Type(value = SymbolTypePointer.class, name = "pointer"),
@JsonSubTypes.Type(value = SymbolTypeProcedure.class, name = "procedure")
})
public interface SymbolType {
public String getTypeName();
}

View File

@@ -1,21 +1,28 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
/** Basic Symbol Types */
public enum SymbolTypeBasic implements SymbolType {
BYTE("byte"),
WORD("word"),
STRING("string"),
BOOLEAN("boolean"),
public class SymbolTypeBasic implements SymbolType {
public static final SymbolTypeBasic BYTE = new SymbolTypeBasic("byte");
public static final SymbolTypeBasic WORD = new SymbolTypeBasic("word");
public static final SymbolTypeBasic STRING = new SymbolTypeBasic("string");
public static final SymbolTypeBasic BOOLEAN = new SymbolTypeBasic("boolean");
// A label
LABEL("label"),
public static final SymbolTypeBasic LABEL = new SymbolTypeBasic("label");
// Void type.
VOID("void"),
public static final SymbolTypeBasic VOID = new SymbolTypeBasic("void");
// Unresolved type. Will be infered later
VAR("var");
public static final SymbolTypeBasic VAR = new SymbolTypeBasic("var");
private String typeName;
SymbolTypeBasic(String typeName) {
@JsonCreator
SymbolTypeBasic(
@JsonProperty("typeName") String typeName) {
this.typeName = typeName;
}
@@ -34,5 +41,22 @@ public enum SymbolTypeBasic implements SymbolType {
return null;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SymbolTypeBasic that = (SymbolTypeBasic) o;
return typeName != null ? typeName.equals(that.typeName) : that.typeName == null;
}
@Override
public int hashCode() {
return typeName != null ? typeName.hashCode() : 0;
}
}

View File

@@ -1,11 +1,17 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
/** A function returning another type */
public class SymbolTypeProcedure implements SymbolType {
private SymbolType returnType;
public SymbolTypeProcedure(SymbolType returnType) {
@JsonCreator
public SymbolTypeProcedure(
@JsonProperty("returnType") SymbolType returnType) {
this.returnType = returnType;
}
@@ -14,6 +20,7 @@ public class SymbolTypeProcedure implements SymbolType {
}
@Override
@JsonIgnore
public String getTypeName() {
return returnType.getTypeName() + "()";
}

View File

@@ -1,5 +1,7 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonIgnore;
/** A program */
public class SymbolTypeProgram implements SymbolType {
@@ -8,7 +10,18 @@ public class SymbolTypeProgram implements SymbolType {
}
@Override
@JsonIgnore
public String getTypeName() {
return "PROGRAM";
}
@Override
public int hashCode() {
return 331;
}
@Override
public boolean equals(Object obj) {
return (obj instanceof SymbolTypeProgram);
}
}

View File

@@ -1,5 +1,23 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
/** Any value (variable, constant, label) */
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type")
@JsonSubTypes({
@JsonSubTypes.Type(value = ConstantBool.class, name = "boolean"),
@JsonSubTypes.Type(value = ConstantInteger.class, name = "integer"),
@JsonSubTypes.Type(value = ConstantDouble.class, name = "double"),
@JsonSubTypes.Type(value = ConstantString.class, name = "string"),
@JsonSubTypes.Type(value = VariableUnversioned.class, name = "variable_unversioned"),
@JsonSubTypes.Type(value = VariableVersion.class, name = "variable_versioned"),
@JsonSubTypes.Type(value = VariableIntermediate.class, name = "variable_intermediate"),
@JsonSubTypes.Type(value = Label.class, name = "label"),
@JsonSubTypes.Type(value = PointerDereferenceIndexed.class, name = "pointer_indexed"),
@JsonSubTypes.Type(value = PointerDereferenceSimple.class, name = "pointer_simple"),
@JsonSubTypes.Type(value = ProgramScope.class, name = "program"),
@JsonSubTypes.Type(value = Procedure.class, name = "procedure")
})
public interface Value {
}

View File

@@ -1,5 +1,7 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
* A Symbol (variable, jump label, etc.)
*/
@@ -13,6 +15,7 @@ public abstract class Variable implements Symbol, RValue, LValue {
/**
* Scope
*/
@JsonIgnore
private Scope scope;
/**
@@ -32,6 +35,7 @@ public abstract class Variable implements Symbol, RValue, LValue {
this.inferredType = false;
}
@Override
public String getLocalName() {
return name;
}
@@ -42,6 +46,7 @@ public abstract class Variable implements Symbol, RValue, LValue {
}
@Override
@JsonIgnore
public String getTypedName() {
return "(" + type.getTypeName() + (inferredType ? "~" : "") + ") " + getFullName();
}
@@ -50,7 +55,7 @@ public abstract class Variable implements Symbol, RValue, LValue {
return type;
}
public void setInferredType(SymbolType type) {
public void setTypeInferred(SymbolType type) {
this.type = type;
this.inferredType = true;
}
@@ -59,27 +64,42 @@ public abstract class Variable implements Symbol, RValue, LValue {
return inferredType;
}
public void setInferredType(boolean inferredType) {
this.inferredType = inferredType;
}
public void setScope(Scope scope) {
this.scope = scope;
}
public void setType(SymbolType type) {
this.type = type;
}
public void setName(String name) {
this.name = name;
}
@JsonIgnore
public abstract boolean isVersioned();
@JsonIgnore
public abstract boolean isIntermediate();
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
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;
if (!getFullName().equals(variable.getFullName())) return false;
return type.equals(variable.type);
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + (scope != null ? scope.hashCode() : 0);
int result = getFullName().hashCode();
result = 31 * result + type.hashCode();
result = 31 * result + (inferredType ? 1 : 0);
return result;

View File

@@ -1,5 +1,9 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* A Symbol (variable, jump label, etc.)
*/
@@ -9,6 +13,13 @@ public class VariableIntermediate extends Variable {
super(name, scope, type);
}
@JsonCreator
public VariableIntermediate(
@JsonProperty("name") String name,
@JsonProperty("type") SymbolType type) {
super(name, null, type);
}
@Override
public boolean isIntermediate() {
return true;
@@ -18,4 +29,6 @@ public class VariableIntermediate extends Variable {
public boolean isVersioned() {
return false;
}
}

View File

@@ -1,5 +1,8 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* A Symbol (variable, jump label, etc.)
*/
@@ -10,11 +13,23 @@ public class VariableUnversioned extends Variable {
*/
private Integer nextVersionNumber;
public VariableUnversioned(String name, Scope scope, SymbolType type) {
public VariableUnversioned(
String name,
Scope scope,
SymbolType type) {
super(name, scope, type);
this.nextVersionNumber = 0;
}
@JsonCreator
public VariableUnversioned(
@JsonProperty("name") String name,
@JsonProperty("type") SymbolType type,
@JsonProperty("nextVersionNumber") Integer nextVersionNumber) {
super(name, null, type);
this.nextVersionNumber = nextVersionNumber;
}
/**
* Get the version number of the next version. (if anyone versions the symbol).
*/

View File

@@ -1,13 +1,26 @@
package dk.camelot64.kickc.icl;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
/** A Symbol (variable, jump label, etc.) */
public class VariableVersion extends Variable {
private VariableUnversioned versionOf;
private String versionOfName;
public VariableVersion(VariableUnversioned versionOf, int version) {
super(versionOf.getLocalName()+"#"+version, versionOf.getScope(), versionOf.getType());
this.versionOf = versionOf;
this.versionOfName = versionOf.getLocalName();
}
@JsonCreator
public VariableVersion(
@JsonProperty("name") String name,
@JsonProperty("type") SymbolType type,
@JsonProperty("versionOfName") String versionOfName) {
super(name, null, type);
this.versionOfName = versionOfName;
}
@Override
@@ -20,25 +33,40 @@ public class VariableVersion extends Variable {
return false;
}
@JsonIgnore
public VariableUnversioned getVersionOf() {
return versionOf;
return (VariableUnversioned) getScope().getVariable(versionOfName);
}
public String getVersionOfName() {
return versionOfName;
}
public void setVersionOfName(String versionOfName) {
this.versionOfName = versionOfName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
VariableVersion that = (VariableVersion) o;
return versionOf != null ? versionOf.equals(that.versionOf) : that.versionOf == null;
return versionOfName != null ? versionOfName.equals(that.versionOfName) : that.versionOfName == null;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (versionOf != null ? versionOf.hashCode() : 0);
result = 31 * result + (versionOfName != null ? versionOfName.hashCode() : 0);
return result;
}
}

View File

@@ -0,0 +1,39 @@
package dk.camelot64.kickc.icl.jackson;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
/** Factory for Jackson JSON serialization of the KickC ICL */
public class IclJacksonFactory {
private static ObjectMapper mapper;
private static Module module;
static {
mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
SimpleModule jsonModule = new SimpleModule("KickC ICL Types");
module = jsonModule;
mapper.registerModule(jsonModule);
}
/** Get an ObjectMapper usable for serializing/deserializing KickC ICL to/from JSON */
public static ObjectMapper getMapper() {
return mapper;
}
/** Get a Jackson Module usable for serializing/deserializing KickC ICL to/from JSON */
public static Module getModule() {
return module;
}
}

View File

@@ -41,21 +41,21 @@ public class Pass1GenerateSingleStaticAssignmentForm {
for (Statement statement : block.getStatements()) {
if (statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
LValue lValue = assignment.getLValue();
LValue lValue = assignment.getlValue();
if (lValue instanceof VariableUnversioned) {
// Assignment to a non-versioned non-intermediary variable
VariableUnversioned assignedSymbol = (VariableUnversioned) lValue;
VariableVersion version = assignedSymbol.createVersion();
assignment.setLValue(version);
assignment.setlValue(version);
}
} else if(statement instanceof StatementCall) {
StatementCall call = (StatementCall) statement;
LValue lValue = call.getLValue();
LValue lValue = call.getlValue();
if (lValue instanceof VariableUnversioned) {
// Assignment to a non-versioned non-intermediary variable
VariableUnversioned assignedSymbol = (VariableUnversioned) lValue;
VariableVersion version = assignedSymbol.createVersion();
call.setLValue(version);
call.setlValue(version);
}
}
}
@@ -85,19 +85,19 @@ public class Pass1GenerateSingleStaticAssignmentForm {
if (statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
{
VariableVersion version = findOrCreateVersion(assignment.getRValue1(), blockVersions, blockNewPhis);
VariableVersion version = findOrCreateVersion(assignment.getrValue1(), blockVersions, blockNewPhis);
if (version != null) {
assignment.setRValue1(version);
assignment.setrValue1(version);
}
}
{
VariableVersion version = findOrCreateVersion(assignment.getRValue2(), blockVersions, blockNewPhis);
VariableVersion version = findOrCreateVersion(assignment.getrValue2(), blockVersions, blockNewPhis);
if (version != null) {
assignment.setRValue2(version);
assignment.setrValue2(version);
}
}
// Update map of versions encountered in the block
LValue lValue = assignment.getLValue();
LValue lValue = assignment.getlValue();
if (lValue instanceof VariableVersion) {
VariableVersion versioned = (VariableVersion) lValue;
blockVersions.put(versioned.getVersionOf(), versioned);
@@ -175,7 +175,7 @@ public class Pass1GenerateSingleStaticAssignmentForm {
if (statement instanceof StatementPhi) {
StatementPhi phi = (StatementPhi) statement;
if (phi.getPreviousVersions().isEmpty()) {
VariableVersion versioned = phi.getLValue();
VariableVersion versioned = phi.getlValue();
VariableUnversioned unversioned = versioned.getVersionOf();
for (ControlFlowBlock predecessor : controlFlowGraph.getPredecessors(block)) {
Label predecessorLabel = predecessor.getLabel();
@@ -226,7 +226,7 @@ public class Pass1GenerateSingleStaticAssignmentForm {
for (Statement statement : block.getStatements()) {
if (statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
LValue lValue = assignment.getLValue();
LValue lValue = assignment.getlValue();
if (lValue instanceof VariableVersion) {
VariableVersion versioned = (VariableVersion) lValue;
Label label = block.getLabel();
@@ -240,7 +240,7 @@ public class Pass1GenerateSingleStaticAssignmentForm {
}
} else if (statement instanceof StatementPhi) {
StatementPhi phi = (StatementPhi) statement;
VariableVersion versioned = phi.getLValue();
VariableVersion versioned = phi.getlValue();
VariableUnversioned unversioned = versioned.getVersionOf();
Label label = block.getLabel();
Map<VariableUnversioned, VariableVersion> blockMap = symbolMap.get(label);
@@ -251,7 +251,7 @@ public class Pass1GenerateSingleStaticAssignmentForm {
blockMap.put(unversioned, versioned);
} else if (statement instanceof StatementCall) {
StatementCall call = (StatementCall) statement;
LValue lValue = call.getLValue();
LValue lValue = call.getlValue();
if (lValue instanceof VariableVersion) {
VariableVersion versioned = (VariableVersion) lValue;
Label label = block.getLabel();

View File

@@ -18,19 +18,19 @@ import java.util.Stack;
public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
private CompileLog log;
private Scope programScope;
private ProgramScope programScope;
private Stack<Scope> scopeStack;
private StatementSequence sequence;
public Pass1GenerateStatementSequence(CompileLog log) {
this.log = log;
this.programScope = new Scope();
this.programScope = new ProgramScope();
this.scopeStack = new Stack<>();
scopeStack.push(programScope);
this.sequence = new StatementSequence();
}
public Scope getProgramScope() {
public ProgramScope getProgramScope() {
return programScope;
}

View File

@@ -41,10 +41,10 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
getCurrentBlock().setCallSuccessor(procedure.getLabel());
splitCurrentBlock(scope.addLabelIntermediate());
if(!SymbolTypeBasic.VOID.equals(procedure.getReturnType())) {
addStatementToCurrentBlock(new StatementAssignment(origCall.getLValue(), procReturnVar));
addStatementToCurrentBlock(new StatementAssignment(origCall.getlValue(), procReturnVar));
} else {
// No return type. Remove variable receiving the result.
LValue lValue = origCall.getLValue();
LValue lValue = origCall.getlValue();
if(lValue instanceof Variable) {
Variable lVar = (Variable) lValue;
lVar.getScope().remove(lVar);

View File

@@ -47,7 +47,7 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor
if (returnVarFinal == null) {
throw new RuntimeException("Error! Cannot find final return variable for " + procedure.getFullName());
}
StatementAssignment returnAssignment = new StatementAssignment(origCall.getLValue(), returnVarFinal);
StatementAssignment returnAssignment = new StatementAssignment(origCall.getlValue(), returnVarFinal);
addStatementToCurrentBlock(returnAssignment);
}
return null;

View File

@@ -21,30 +21,30 @@ public class Pass1TypeInference {
scopes.pop();
} else if (statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
LValue lValue = assignment.getLValue();
LValue lValue = assignment.getlValue();
if (lValue instanceof Variable) {
Variable symbol = (Variable) lValue;
if (SymbolTypeBasic.VAR.equals(symbol.getType())) {
// Unresolved symbol - perform inference
Operator operator = assignment.getOperator();
if (operator == null || assignment.getRValue1() == null) {
if (operator == null || assignment.getrValue1() == null) {
// Copy operation or Unary operation
RValue rValue = assignment.getRValue2();
RValue rValue = assignment.getrValue2();
SymbolType subType = inferType(rValue);
SymbolType type = inferType(operator, subType);
symbol.setInferredType(type);
symbol.setTypeInferred(type);
} else {
// Binary operation
SymbolType type1 = inferType(assignment.getRValue1());
SymbolType type2 = inferType(assignment.getRValue2());
SymbolType type1 = inferType(assignment.getrValue1());
SymbolType type2 = inferType(assignment.getrValue2());
SymbolType type = inferType(type1, operator, type2);
symbol.setInferredType(type);
symbol.setTypeInferred(type);
}
}
}
} else if(statement instanceof StatementCall) {
StatementCall call = (StatementCall) statement;
LValue lValue = call.getLValue();
LValue lValue = call.getlValue();
if(lValue instanceof Variable) {
String procedureName = call.getProcedureName();
Procedure procedure = scopes.peek().getProcedure(procedureName);
@@ -52,7 +52,7 @@ public class Pass1TypeInference {
if(procedure.getParameters().size()!=call.getParameters().size()) {
throw new RuntimeException("Wrong number of parameters in call. Expected " +procedure.getParameters().size()+". "+statement.toString());
}
((Variable) lValue).setInferredType(procedure.getReturnType());
((Variable) lValue).setTypeInferred(procedure.getReturnType());
}
}
}

View File

@@ -48,15 +48,15 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
Statement statement = iterator.next();
if (statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
AliasSet aliasSet = aliases.findAliasSet(assignment.getLValue());
AliasSet aliasSet = aliases.findAliasSet(assignment.getlValue());
if (aliasSet != null) {
if ((assignment.getRValue1() == null) && (assignment.getOperator() == null) && aliasSet.contains(assignment.getRValue2())) {
if ((assignment.getrValue1() == null) && (assignment.getOperator() == null) && aliasSet.contains(assignment.getrValue2())) {
iterator.remove();
}
}
} else if (statement instanceof StatementPhi) {
StatementPhi phi = (StatementPhi) statement;
AliasSet aliasSet = aliases.findAliasSet(phi.getLValue());
AliasSet aliasSet = aliases.findAliasSet(phi.getlValue());
if (aliasSet != null) {
if (phi.getPreviousVersions().size() == 1 && aliasSet.contains(phi.getPreviousVersion(0).getRValue())) {
iterator.remove();
@@ -241,7 +241,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
}
}
}
if (aliasSet.contains(phi.getLValue())) {
if (aliasSet.contains(phi.getlValue())) {
lMatch[0] = true;
}
return null;
@@ -261,11 +261,11 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@Override
public Void visitAssignment(StatementAssignment assignment) {
if (assignment.getLValue() instanceof VariableVersion || assignment.getLValue() instanceof VariableIntermediate) {
Variable variable = (Variable) assignment.getLValue();
if (assignment.getRValue1() == null && assignment.getOperator() == null && assignment.getRValue2() instanceof Variable) {
if (assignment.getlValue() instanceof VariableVersion || assignment.getlValue() instanceof VariableIntermediate) {
Variable variable = (Variable) assignment.getlValue();
if (assignment.getrValue1() == null && assignment.getOperator() == null && assignment.getrValue2() instanceof Variable) {
// Alias assignment
Variable alias = (Variable) assignment.getRValue2();
Variable alias = (Variable) assignment.getrValue2();
aliases.add(variable, alias);
}
}
@@ -277,7 +277,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
if (phi.getPreviousVersions().size() == 1) {
StatementPhi.PreviousSymbol previousSymbol = phi.getPreviousVersions().get(0);
if (previousSymbol.getRValue() instanceof Variable) {
VariableVersion variable = phi.getLValue();
VariableVersion variable = phi.getlValue();
Variable alias = (Variable) previousSymbol.getRValue();
aliases.add(variable, alias);
}

View File

@@ -44,7 +44,7 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion {
private HashSet<Symbol> getAllSymbols(Scope symbols) {
HashSet<Symbol> allSymbols = new HashSet<>();
for (Symbol symbol : symbols.getSymbols()) {
for (Symbol symbol : symbols.getAllSymbols()) {
allSymbols.add(symbol);
if(symbol instanceof Scope) {
HashSet<Symbol> subSymbols = getAllSymbols((Scope) symbol);
@@ -110,9 +110,9 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion {
@Override
public Void visitAssignment(StatementAssignment assignment) {
addSymbol(assignment.getLValue());
addSymbol(assignment.getRValue1());
addSymbol(assignment.getRValue2());
addSymbol(assignment.getlValue());
addSymbol(assignment.getrValue1());
addSymbol(assignment.getrValue2());
return super.visitAssignment(assignment);
}
@@ -130,7 +130,7 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion {
@Override
public Void visitCall(StatementCall callLValue) {
addSymbol(callLValue.getLValue());
addSymbol(callLValue.getlValue());
addSymbol(callLValue.getProcedure());
if(callLValue.getParameters()!=null) {
for (RValue param : callLValue.getParameters()) {
@@ -142,7 +142,7 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion {
@Override
public Void visitPhi(StatementPhi phi) {
addSymbol(phi.getLValue());
addSymbol(phi.getlValue());
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
addSymbol(previousSymbol.getRValue());
}

View File

@@ -54,9 +54,9 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
case "=<":
case ">=":
case "=>":
conditionalJump.setRValue1(conditionAssignment.getRValue1());
conditionalJump.setRValue1(conditionAssignment.getrValue1());
conditionalJump.setOperator(conditionAssignment.getOperator());
conditionalJump.setRValue2(conditionAssignment.getRValue2());
conditionalJump.setRValue2(conditionAssignment.getrValue2());
simpleConditionVars.add(conditionVar);
log.append("Simple Condition " + conditionVar + " " + conditionalJump);
break;

View File

@@ -39,7 +39,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
for (Statement statement : block.getStatements()) {
if (statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if(assignment.getLValue() instanceof PointerDereferenceIndexed) {
if(assignment.getlValue() instanceof PointerDereferenceIndexed) {
optimized |= optimizePointerDereferenceIndexed(assignment);
}
Operator operator = assignment.getOperator();
@@ -60,13 +60,13 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
}
private boolean optimizePointerDereferenceIndexed(StatementAssignment assignment) {
PointerDereferenceIndexed pointerDereferenceIndexed = (PointerDereferenceIndexed) assignment.getLValue();
PointerDereferenceIndexed pointerDereferenceIndexed = (PointerDereferenceIndexed) assignment.getlValue();
if(pointerDereferenceIndexed.getPointer() instanceof ConstantInteger && pointerDereferenceIndexed.getIndex() instanceof Constant) {
ConstantInteger ptrConstant = (ConstantInteger) pointerDereferenceIndexed.getPointer();
ConstantInteger idxConstant = (ConstantInteger) pointerDereferenceIndexed.getIndex();
int newPtr = ptrConstant.getNumber() + idxConstant.getNumber();
assignment.setLValue(new PointerDereferenceSimple(new ConstantInteger(newPtr)));
log.append("Consolidated assigned array index constant in assignment " + assignment.getLValue());
assignment.setlValue(new PointerDereferenceSimple(new ConstantInteger(newPtr)));
log.append("Consolidated assigned array index constant in assignment " + assignment.getlValue());
return true;
}
if(pointerDereferenceIndexed.getPointer() instanceof ConstantInteger && pointerDereferenceIndexed.getIndex() instanceof Variable) {
@@ -76,7 +76,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
ConstantInteger ptrConstant = (ConstantInteger) pointerDereferenceIndexed.getPointer();
int newPtr = ptrConstant.getNumber() + consolidated.getNumber();
pointerDereferenceIndexed.setPointer(new ConstantInteger(newPtr));
log.append("Consolidated assigned array index constant in assignment " + assignment.getLValue());
log.append("Consolidated assigned array index constant in assignment " + assignment.getlValue());
return true;
}
}
@@ -84,24 +84,24 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
}
private boolean optimizeArrayDeref(StatementAssignment assignment) {
if (assignment.getRValue1() instanceof ConstantInteger && assignment.getRValue2() instanceof ConstantInteger) {
ConstantInteger ptrConstant = (ConstantInteger) assignment.getRValue1();
ConstantInteger idxConstant = (ConstantInteger) assignment.getRValue2();
if (assignment.getrValue1() instanceof ConstantInteger && assignment.getrValue2() instanceof ConstantInteger) {
ConstantInteger ptrConstant = (ConstantInteger) assignment.getrValue1();
ConstantInteger idxConstant = (ConstantInteger) assignment.getrValue2();
int newPtr = ptrConstant.getNumber() + idxConstant.getNumber();
assignment.setRValue1(null);
assignment.setrValue1(null);
assignment.setOperator(new Operator("*"));
assignment.setRValue2(new ConstantInteger(newPtr));
log.append("Consolidated referenced array index constant in assignment " + assignment.getLValue());
assignment.setrValue2(new ConstantInteger(newPtr));
log.append("Consolidated referenced array index constant in assignment " + assignment.getlValue());
return true;
}
if (assignment.getRValue1() instanceof ConstantInteger && assignment.getRValue2() instanceof Variable) {
Variable variable = (Variable) assignment.getRValue2();
if (assignment.getrValue1() instanceof ConstantInteger && assignment.getrValue2() instanceof Variable) {
Variable variable = (Variable) assignment.getrValue2();
ConstantInteger consolidated = consolidateSubConstants(variable);
if (consolidated != null) {
ConstantInteger ptrConstant = (ConstantInteger) assignment.getRValue1();
ConstantInteger ptrConstant = (ConstantInteger) assignment.getrValue1();
int newPtr = ptrConstant.getNumber() + consolidated.getNumber();
assignment.setRValue1(new ConstantInteger(newPtr));
log.append("Consolidated referenced array index constant in assignment " + assignment.getLValue());
assignment.setrValue1(new ConstantInteger(newPtr));
log.append("Consolidated referenced array index constant in assignment " + assignment.getlValue());
return true;
}
}
@@ -109,28 +109,28 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
}
private boolean optimizePlus(StatementAssignment assignment) {
if (assignment.getRValue1() instanceof ConstantInteger && assignment.getRValue2() instanceof Variable) {
Variable variable = (Variable) assignment.getRValue2();
if (assignment.getrValue1() instanceof ConstantInteger && assignment.getrValue2() instanceof Variable) {
Variable variable = (Variable) assignment.getrValue2();
ConstantInteger consolidated = consolidateSubConstants(variable);
if (consolidated != null) {
ConstantInteger const1 = (ConstantInteger) assignment.getRValue1();
assignment.setRValue1(new ConstantInteger(const1.getNumber() + consolidated.getNumber()));
log.append("Consolidated constant in assignment " + assignment.getLValue());
ConstantInteger const1 = (ConstantInteger) assignment.getrValue1();
assignment.setrValue1(new ConstantInteger(const1.getNumber() + consolidated.getNumber()));
log.append("Consolidated constant in assignment " + assignment.getlValue());
return true;
}
} else if (assignment.getRValue1() instanceof Variable && assignment.getRValue2() instanceof ConstantInteger) {
Variable variable = (Variable) assignment.getRValue1();
} else if (assignment.getrValue1() instanceof Variable && assignment.getrValue2() instanceof ConstantInteger) {
Variable variable = (Variable) assignment.getrValue1();
ConstantInteger consolidated = consolidateSubConstants(variable);
if (consolidated != null) {
ConstantInteger const2 = (ConstantInteger) assignment.getRValue2();
ConstantInteger const2 = (ConstantInteger) assignment.getrValue2();
int newNumber = const2.getNumber() + consolidated.getNumber();
if (newNumber < 0) {
assignment.setRValue2(new ConstantInteger(-newNumber));
assignment.setrValue2(new ConstantInteger(-newNumber));
assignment.setOperator(new Operator("-"));
} else {
assignment.setRValue2(new ConstantInteger(newNumber));
assignment.setrValue2(new ConstantInteger(newNumber));
}
log.append("Consolidated constant in assignment " + assignment.getLValue());
log.append("Consolidated constant in assignment " + assignment.getlValue());
return true;
}
}
@@ -150,25 +150,25 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
}
StatementAssignment assignment = getGraph().getAssignment(variable);
if (assignment != null && assignment.getOperator() != null && "+".equals(assignment.getOperator().getOperator())) {
if (assignment.getRValue1() instanceof ConstantInteger) {
ConstantInteger constant = (ConstantInteger) assignment.getRValue1();
assignment.setRValue1(null);
if (assignment.getrValue1() instanceof ConstantInteger) {
ConstantInteger constant = (ConstantInteger) assignment.getrValue1();
assignment.setrValue1(null);
assignment.setOperator(null);
return constant;
} else if (assignment.getRValue2() instanceof ConstantInteger) {
ConstantInteger constant = (ConstantInteger) assignment.getRValue2();
assignment.setRValue2(assignment.getRValue1());
} else if (assignment.getrValue2() instanceof ConstantInteger) {
ConstantInteger constant = (ConstantInteger) assignment.getrValue2();
assignment.setrValue2(assignment.getrValue1());
assignment.setOperator(null);
assignment.setRValue1(null);
assignment.setrValue1(null);
return constant;
} else {
ConstantInteger const1 = null;
if (assignment.getRValue1() instanceof Variable) {
const1 = consolidateSubConstants((Variable) assignment.getRValue1());
if (assignment.getrValue1() instanceof Variable) {
const1 = consolidateSubConstants((Variable) assignment.getrValue1());
}
ConstantInteger const2 = null;
if (assignment.getRValue2() instanceof Variable) {
const2 = consolidateSubConstants((Variable) assignment.getRValue2());
if (assignment.getrValue2() instanceof Variable) {
const2 = consolidateSubConstants((Variable) assignment.getrValue2());
}
ConstantInteger result = null;
if (const1 != null) {
@@ -183,24 +183,24 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
}
}
if (assignment != null && assignment.getOperator() != null && "-".equals(assignment.getOperator().getOperator())) {
if (assignment.getRValue1() instanceof ConstantInteger) {
ConstantInteger constant = (ConstantInteger) assignment.getRValue1();
assignment.setRValue1(null);
if (assignment.getrValue1() instanceof ConstantInteger) {
ConstantInteger constant = (ConstantInteger) assignment.getrValue1();
assignment.setrValue1(null);
return constant;
} else if (assignment.getRValue2() instanceof ConstantInteger) {
ConstantInteger constant = (ConstantInteger) assignment.getRValue2();
assignment.setRValue2(assignment.getRValue1());
} else if (assignment.getrValue2() instanceof ConstantInteger) {
ConstantInteger constant = (ConstantInteger) assignment.getrValue2();
assignment.setrValue2(assignment.getrValue1());
assignment.setOperator(null);
assignment.setRValue1(null);
assignment.setrValue1(null);
return new ConstantInteger(-constant.getNumber());
} else {
ConstantInteger const1 = null;
if (assignment.getRValue1() instanceof Variable) {
const1 = consolidateSubConstants((Variable) assignment.getRValue1());
if (assignment.getrValue1() instanceof Variable) {
const1 = consolidateSubConstants((Variable) assignment.getrValue1());
}
ConstantInteger const2 = null;
if (assignment.getRValue2() instanceof Variable) {
const2 = consolidateSubConstants((Variable) assignment.getRValue2());
if (assignment.getrValue2() instanceof Variable) {
const2 = consolidateSubConstants((Variable) assignment.getrValue2());
}
ConstantInteger result = null;
if (const1 != null) {

View File

@@ -39,26 +39,26 @@ public class Pass2ConstantPropagation extends Pass2SsaOptimization {
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@Override
public Void visitAssignment(StatementAssignment assignment) {
if (assignment.getLValue() instanceof VariableVersion || assignment.getLValue() instanceof VariableIntermediate) {
Variable variable = (Variable) assignment.getLValue();
if (assignment.getRValue1() == null && assignment.getRValue2() instanceof Constant) {
if (assignment.getlValue() instanceof VariableVersion || assignment.getlValue() instanceof VariableIntermediate) {
Variable variable = (Variable) assignment.getlValue();
if (assignment.getrValue1() == null && assignment.getrValue2() instanceof Constant) {
if (assignment.getOperator() == null) {
// Constant assignment
Constant constant = (Constant) assignment.getRValue2();
Constant constant = (Constant) assignment.getrValue2();
constants.put(variable, constant);
} else {
// Constant unary expression
Constant constant = calculateUnary(assignment.getOperator(), (Constant) assignment.getRValue2());
Constant constant = calculateUnary(assignment.getOperator(), (Constant) assignment.getrValue2());
if(constant!=null) {
constants.put(variable, constant);
}
}
} else if (assignment.getRValue1() instanceof Constant && assignment.getRValue2() instanceof Constant) {
} else if (assignment.getrValue1() instanceof Constant && assignment.getrValue2() instanceof Constant) {
// Constant binary expression
Constant constant = calculateBinary(
assignment.getOperator(),
(Constant) assignment.getRValue1(),
(Constant) assignment.getRValue2());
(Constant) assignment.getrValue1(),
(Constant) assignment.getrValue2());
if(constant!=null) {
constants.put(variable, constant);
}
@@ -72,7 +72,7 @@ public class Pass2ConstantPropagation extends Pass2SsaOptimization {
if (phi.getPreviousVersions().size() == 1) {
StatementPhi.PreviousSymbol previousSymbol = phi.getPreviousVersions().get(0);
if (previousSymbol.getRValue() instanceof Constant) {
VariableVersion variable = phi.getLValue();
VariableVersion variable = phi.getlValue();
Constant constant = (Constant) previousSymbol.getRValue();
constants.put(variable, constant);
}

View File

@@ -51,7 +51,7 @@ public class Pass2RedundantPhiElimination extends Pass2SsaOptimization {
}
}
if(found) {
VariableVersion variable = phi.getLValue();
VariableVersion variable = phi.getlValue();
if(phiRValue==null) {phiRValue = VOID;}
aliases.put(variable, phiRValue);
}

View File

@@ -26,10 +26,10 @@ public class Pass2SelfPhiElimination extends Pass2SsaOptimization {
public Void visitPhi(StatementPhi phi) {
for (Iterator<StatementPhi.PreviousSymbol> iterator = phi.getPreviousVersions().iterator(); iterator.hasNext(); ) {
StatementPhi.PreviousSymbol previousSymbol = iterator.next();
if (previousSymbol.getRValue().equals(phi.getLValue())) {
if (previousSymbol.getRValue().equals(phi.getlValue())) {
iterator.remove();
optimized[0] = Boolean.TRUE;
log.append("Self Phi Eliminated "+phi.getLValue());
log.append("Self Phi Eliminated "+phi.getlValue());
}
}
return null;

View File

@@ -59,20 +59,20 @@ public abstract class Pass2SsaOptimization {
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@Override
public Void visitAssignment(StatementAssignment assignment) {
LValue lValue = assignment.getLValue();
LValue lValue = assignment.getlValue();
if (getAlias(aliases, lValue) != null) {
RValue alias = getAlias(aliases, lValue);
if (alias instanceof LValue) {
assignment.setLValue((LValue) alias);
assignment.setlValue((LValue) alias);
} else {
throw new RuntimeException("Error replacing LValue variable " + lValue + " with " + alias);
}
}
if (getAlias(aliases, assignment.getRValue1()) != null) {
assignment.setRValue1(getAlias(aliases, assignment.getRValue1()));
if (getAlias(aliases, assignment.getrValue1()) != null) {
assignment.setrValue1(getAlias(aliases, assignment.getrValue1()));
}
if (getAlias(aliases, assignment.getRValue2()) != null) {
assignment.setRValue2(getAlias(aliases, assignment.getRValue2()));
if (getAlias(aliases, assignment.getrValue2()) != null) {
assignment.setrValue2(getAlias(aliases, assignment.getrValue2()));
}
// Handle pointer dereference in LValue
if (lValue instanceof PointerDereferenceSimple) {
@@ -136,10 +136,10 @@ public abstract class Pass2SsaOptimization {
@Override
public Void visitPhi(StatementPhi phi) {
if (getAlias(aliases, phi.getLValue()) != null) {
RValue alias = getAlias(aliases, phi.getLValue());
if (getAlias(aliases, phi.getlValue()) != null) {
RValue alias = getAlias(aliases, phi.getlValue());
if (alias instanceof LValue) {
phi.setLValue((Variable) alias);
phi.setlValue((Variable) alias);
}
}
for (Iterator<StatementPhi.PreviousSymbol> iterator = phi.getPreviousVersions().iterator(); iterator.hasNext(); ) {
@@ -254,12 +254,12 @@ public abstract class Pass2SsaOptimization {
Statement statement = iterator.next();
if (statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
if (variables.contains(assignment.getLValue())) {
if (variables.contains(assignment.getlValue())) {
iterator.remove();
}
} else if (statement instanceof StatementPhi) {
StatementPhi phi = (StatementPhi) statement;
if (variables.contains(phi.getLValue())) {
if (variables.contains(phi.getlValue())) {
iterator.remove();
}
}
@@ -283,7 +283,7 @@ public abstract class Pass2SsaOptimization {
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@Override
public Void visitAssignment(StatementAssignment assignment) {
assignments.put(assignment.getLValue(), assignment);
assignments.put(assignment.getlValue(), assignment);
return null;
}
};
@@ -296,8 +296,8 @@ public abstract class Pass2SsaOptimization {
ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
@Override
public Void visitAssignment(StatementAssignment assignment) {
addUsage(assignment.getRValue1(), assignment);
addUsage(assignment.getRValue2(), assignment);
addUsage(assignment.getrValue1(), assignment);
addUsage(assignment.getrValue2(), assignment);
return null;
}
@@ -354,8 +354,8 @@ public abstract class Pass2SsaOptimization {
@Override
public Object visitAssignment(StatementAssignment assignment) {
addUsage(assignment.getRValue1());
addUsage(assignment.getRValue2());
addUsage(assignment.getrValue1());
addUsage(assignment.getrValue2());
return null;
}

View File

@@ -11,9 +11,9 @@ import java.util.*;
public class Pass3CodeGeneration {
private ControlFlowGraph graph;
private Scope symbols;
private ProgramScope symbols;
public Pass3CodeGeneration(ControlFlowGraph graph, Scope symbols) {
public Pass3CodeGeneration(ControlFlowGraph graph, ProgramScope symbols) {
this.graph = graph;
this.symbols = symbols;
}
@@ -46,7 +46,7 @@ public class Pass3CodeGeneration {
if (!(statement instanceof StatementPhi)) {
if (statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
LValue lValue = assignment.getLValue();
LValue lValue = assignment.getlValue();
boolean isAlu = false;
if (lValue instanceof Variable) {
RegisterAllocation.Register lValRegister = symbols.getRegister((Variable) lValue);
@@ -124,7 +124,7 @@ public class Pass3CodeGeneration {
});
for (StatementPhi.PreviousSymbol previousSymbol : previousVersions) {
if (previousSymbol.getBlock().equals(fromBlock.getLabel())) {
genAsmMove(asm, phi.getLValue(), previousSymbol.getRValue());
genAsmMove(asm, phi.getlValue(), previousSymbol.getRValue());
break;
}
}

View File

@@ -8,10 +8,10 @@ import dk.camelot64.kickc.icl.*;
public class Pass3RegisterAllocation {
private ControlFlowGraph graph;
private Scope symbols;
private ProgramScope symbols;
int currentZp = 2;
public Pass3RegisterAllocation(ControlFlowGraph graph, Scope symbols) {
public Pass3RegisterAllocation(ControlFlowGraph graph, ProgramScope symbols) {
this.graph = graph;
this.symbols = symbols;
}
@@ -159,7 +159,7 @@ public class Pass3RegisterAllocation {
}
private void performAllocation(Scope scope, RegisterAllocation allocation) {
for (Symbol symbol : scope.getSymbols()) {
for (Symbol symbol : scope.getAllSymbols()) {
if (symbol instanceof Scope) {
performAllocation((Scope) symbol, allocation);
} else if (symbol instanceof VariableIntermediate || symbol instanceof VariableVersion) {

View File

@@ -1,6 +1,7 @@
package dk.camelot64.kickc.test;
import dk.camelot64.kickc.Compiler;
import junit.framework.TestCase;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
@@ -16,7 +17,7 @@ import java.util.ArrayList;
import java.util.List;
/** Compile a number of source files and compare the resulting assembler with expected output*/
public class TestCompilationOutput {
public class TestCompilationOutput extends TestCase {
private Path tempDir;
private String testPath;
@@ -28,12 +29,14 @@ public class TestCompilationOutput {
tempDir = Files.createTempDirectory("kickc-output");
}
public static void main(String[] args) throws IOException, URISyntaxException {
public void testFlipper() throws IOException, URISyntaxException {
TestCompilationOutput tester = new TestCompilationOutput();
//tester.testFile("fibmem");
tester.testFile("flipper-rex2");
}
public void testBresenham() throws IOException, URISyntaxException {
TestCompilationOutput tester = new TestCompilationOutput();
tester.testFile("bresenham");
//tester.testFile("unused");
}
private void testFile(String fileName) throws IOException, URISyntaxException {

View File

@@ -0,0 +1,63 @@
package dk.camelot64.kickc.test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;
import dk.camelot64.kickc.icl.*;
import dk.camelot64.kickc.icl.jackson.IclJacksonFactory;
import junit.framework.TestCase;
import java.io.IOException;
import java.util.ArrayList;
/** Test JSON serialization of the KickC ICL */
public class TestIclJson extends TestCase {
public void testJsonVariable() throws IOException {
VariableUnversioned v1 = new VariableUnversioned("v1", null, SymbolTypeBasic.BYTE);
String json = "{\"@type\":\"variable_unversioned\",\"name\":\"v1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":0,\"inferredType\":false}";
assertJsonSerialization(v1, json, Variable.class);
}
public void testJsonScopeSimple() throws IOException {
Scope scope = new ProgramScope();
VariableUnversioned v1 = scope.addVariable("v1", SymbolTypeBasic.BYTE);
v1.createVersion();
scope.addVariableIntermediate();
scope.addLabel("main");
scope.addLabelIntermediate();
String json = "{\"@type\":\"program\",\"name\":\"\",\"symbols\":{\"v1\":{\"@type\":\"variable_unversioned\",\"name\":\"v1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":1,\"inferredType\":false},\"v1#0\":{\"@type\":\"variable_versioned\",\"name\":\"v1#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"v1\",\"inferredType\":false},\"$0\":{\"@type\":\"variable_intermediate\",\"name\":\"$0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"var\"},\"inferredType\":false},\"main\":{\"@type\":\"label\",\"name\":\"main\",\"intermediate\":false},\"@1\":{\"@type\":\"label\",\"name\":\"@1\",\"intermediate\":true}},\"intermediateVarCount\":1,\"intermediateLabelCount\":2,\"allocation\":null}";
assertJsonSerialization(scope, json, Scope.class);
}
public void testJsonScopeProcedure() throws IOException {
Scope scope = new ProgramScope();
scope.addVariable("v1", SymbolTypeBasic.BYTE);
Procedure procedure = scope.addProcedure("main", SymbolTypeBasic.VOID);
procedure.addVariable("v2", SymbolTypeBasic.BYTE);
ArrayList<Variable> parameters = new ArrayList<>();
parameters.add(new VariableUnversioned("p1", procedure, SymbolTypeBasic.BYTE));
parameters.add(new VariableUnversioned("p2", procedure, SymbolTypeBasic.BYTE));
procedure.setParameters(parameters);
String json = "{\"@type\":\"program\",\"name\":\"\",\"symbols\":{\"v1\":{\"@type\":\"variable_unversioned\",\"name\":\"v1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":0,\"inferredType\":false},\"main\":{\"@type\":\"procedure\",\"name\":\"main\",\"parameterNames\":[\"p1\",\"p2\"],\"symbols\":{\"v2\":{\"@type\":\"variable_unversioned\",\"name\":\"v2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":0,\"inferredType\":false},\"p1\":{\"@type\":\"variable_unversioned\",\"name\":\"p1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":0,\"inferredType\":false},\"p2\":{\"@type\":\"variable_unversioned\",\"name\":\"p2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":0,\"inferredType\":false}},\"intermediateVarCount\":0,\"intermediateLabelCount\":1,\"returnType\":{\"@type\":\"basic\",\"typeName\":\"void\"}}},\"intermediateVarCount\":0,\"intermediateLabelCount\":1,\"allocation\":null}";
assertJsonSerialization(scope, json, Scope.class);
}
public static void assertJsonSerialization(
Object object,
String json,
Class deserializeClass) throws IOException {
ObjectMapper jsonMapper = IclJacksonFactory.getMapper();
ObjectWriter jsonWriter = jsonMapper.writer();
String serialized = jsonWriter.writeValueAsString(object);
System.out.println(serialized);
TestCase.assertEquals("Serialized Object and Reference Serialized", json, serialized);
ObjectReader reader = jsonMapper.readerFor(deserializeClass);
Object deserialized = reader.readValue(json);
TestCase.assertEquals("Deserialized Object and Reference Object", object, deserialized);
Object redeserialized = reader.readValue(serialized);
TestCase.assertEquals("Re-serialized Object and Reference Object", object, redeserialized);
}
}