mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-19 15:29:48 +00:00
Implemented fragment tests - first for assignment to unsigned bytes.
This commit is contained in:
parent
a047fedebf
commit
a6e75ffcb0
@ -35,7 +35,7 @@ public class CompileLog {
|
||||
/**
|
||||
* Should the log be output to System.out while being built
|
||||
*/
|
||||
private boolean sysOut = true;
|
||||
private boolean sysOut = false;
|
||||
|
||||
public CompileLog() {
|
||||
this.log = new StringBuilder();
|
||||
|
@ -66,7 +66,7 @@ public class AsmFragmentInstance {
|
||||
}
|
||||
|
||||
if(boundValue == null) {
|
||||
throw new RuntimeException("Binding '" + name + "' not found in fragment " + this.name + ".asm");
|
||||
throw new RuntimeException("Binding '" + name + "' not found in fragment " + this.name );
|
||||
}
|
||||
if(boundValue instanceof Variable) {
|
||||
Variable boundVar = (Variable) boundValue;
|
||||
|
@ -379,7 +379,7 @@ class AsmFragmentTemplateSynthesisRule {
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuxx=(.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "sta {c1},x", mapC, "xx"));
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuz2=(.*)", ".*z1.*z1.*|.*z2.*z2.*", null, "vb$1aa=$2", "ldy {z2}\n" + "sta ({z1}),y", mapZ2));
|
||||
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=_deref_pb(.)c1(.*)", ".*=.*aa.*", "lda {c1}", "$1=vb$2aa$3", null, mapC));
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=_deref_pb(.)c1(.*)", ".*=.*aa.*|.*c1.*c1.*", "lda {c1}", "$1=vb$2aa$3", null, mapC));
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("(.*)=_deref_pb(.)z1(.*)", ".*z1.*z1.*|.*=.*aa.*|.*yy.*", "ldy #0\n" + "lda ({z1}),y", "$1=vb$2aa$3", null, mapZ));
|
||||
|
||||
// Convert array indexing with A register to X/Y register by prefixing tax/tay (..._derefidx_vbuaa... -> ..._derefidx_vbuxx... /... _derefidx_vbuyy... )
|
||||
|
@ -43,7 +43,12 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
/** Special singleton representing that the fragment can not be synthesized or loaded. */
|
||||
private AsmFragmentTemplate UNKNOWN = new AsmFragmentTemplate("UNKNOWN", null);
|
||||
|
||||
public static AsmFragmentInstance getFragmentInstance(AsmFragmentInstanceSpec instanceSpec, CompileLog log) {
|
||||
public static void clearCaches() {
|
||||
SYNTHESIZER = new AsmFragmentTemplateSynthesizer();
|
||||
}
|
||||
|
||||
|
||||
public static AsmFragmentInstance getFragmentInstance(AsmFragmentInstanceSpec instanceSpec, CompileLog log) {
|
||||
String signature = instanceSpec.getSignature();
|
||||
AsmFragmentTemplate fragmentTemplate = SYNTHESIZER.getFragmentTemplate(signature, log);
|
||||
// Return the resulting fragment instance
|
||||
|
@ -10,7 +10,7 @@ public class Operator {
|
||||
public static final Operator POS = new Operator("+", "_pos_", Type.UNARY, 2);
|
||||
public static final Operator NEG = new Operator("-", "_neg_", Type.UNARY, 2);
|
||||
public static final Operator BOOL_NOT = new Operator("~", "_not_", Type.UNARY, 2);
|
||||
public static final Operator NOT = new Operator("!", "_not_", Type.UNARY, 2);
|
||||
public static final Operator LOGIC_NOT = new Operator("!", "_not_", Type.UNARY, 2);
|
||||
public static final Operator DEREF = new Operator("*", "_deref_", Type.UNARY, 2);
|
||||
public static final Operator WORD = new Operator("w=", "_word_", Type.BINARY, 2);
|
||||
public static final Operator DEREF_IDX = new Operator("*idx", "_derefidx_", Type.BINARY, 2);
|
||||
@ -109,7 +109,7 @@ public class Operator {
|
||||
case "--":
|
||||
return DECREMENT;
|
||||
case "!":
|
||||
return NOT;
|
||||
return LOGIC_NOT;
|
||||
case "~":
|
||||
return BOOL_NOT;
|
||||
case "*":
|
||||
|
@ -227,7 +227,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
PrePostModifierHandler.addPreModifiers(this, ctx.expr());
|
||||
RValue rValue = (RValue) this.visit(ctx.expr());
|
||||
VariableRef notExprVar = getCurrentSymbols().addVariableIntermediate().getRef();
|
||||
sequence.addStatement(new StatementAssignment(notExprVar, null, Operator.NOT, rValue));
|
||||
sequence.addStatement(new StatementAssignment(notExprVar, null, Operator.LOGIC_NOT, rValue));
|
||||
PrePostModifierHandler.addPostModifiers(this, ctx.expr());
|
||||
|
||||
Label elseJumpLabel = getCurrentSymbols().addLabelIntermediate();
|
||||
|
313
src/test/java/dk/camelot64/kickc/test/TestFragments.java
Normal file
313
src/test/java/dk/camelot64/kickc/test/TestFragments.java
Normal file
@ -0,0 +1,313 @@
|
||||
package dk.camelot64.kickc.test;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplate;
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer;
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages;
|
||||
import dk.camelot64.kickc.model.Operator;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import static junit.framework.TestCase.fail;
|
||||
|
||||
/** Test the ASM fragment sub-system by loading/synthesizing a lot of different fragments and comparing with reference fragments. */
|
||||
public class TestFragments {
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() throws Exception {
|
||||
CompileLog log = new CompileLog();
|
||||
log.setSysOut(true);
|
||||
AsmFragmentTemplateUsages.logUsages(log, false, false, false, false, false, false);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAssignmentsBu() throws IOException, URISyntaxException {
|
||||
testFragments("fragments-assignment-copy", assignmentsBu());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAssignmentsUnaryBu() throws IOException, URISyntaxException {
|
||||
testFragments("fragments-assignment-unary", assignmentsUnaryBu());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAssignmentsBinaryBu() throws IOException, URISyntaxException {
|
||||
testFragments("fragments-assignment-binary", assignmentsBinaryBu());
|
||||
}
|
||||
|
||||
private void testFragments(String fileName, Collection<String> signatures) throws IOException, URISyntaxException {
|
||||
CompileLog log = new CompileLog();
|
||||
int cnt = 0;
|
||||
for(String signature : signatures) {
|
||||
if(++cnt % 1000 == 0) System.out.println(""+cnt+"/"+signatures.size());
|
||||
Collection<AsmFragmentTemplate> templates =
|
||||
AsmFragmentTemplateSynthesizer.getFragmentTemplates(signature, log);
|
||||
if(templates.size() == 0) {
|
||||
log.append("CANNOT SYNTHESIZE " + signature);
|
||||
}
|
||||
for(AsmFragmentTemplate template : templates) {
|
||||
log.append((template.isFile() ? "*" : "") + template.getName() + " - clobber:" + template.getClobber().toString() + " cycles:" + template.getCycles());
|
||||
log.append(" " + template.getBody().replace("\n", "\n "));
|
||||
}
|
||||
}
|
||||
ReferenceHelper helper = new ReferenceHelper("dk/camelot64/kickc/test/ref/");
|
||||
boolean success = helper.testOutput(fileName, ".log", log.toString());
|
||||
if(!success) {
|
||||
fail("Output does not match reference!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Collection<String> assignmentsBu() {
|
||||
ArrayList<String> signatures = new ArrayList<>();
|
||||
Collection<Value> lVals = lValuesBu(new ArrayList<>());
|
||||
for(Value lValue : lVals) {
|
||||
Collection<Value> rVals = rValuesBu(lValue.getAllValues());
|
||||
for(Value rValue : rVals) {
|
||||
signatures.add(lValue.getSignature() + "=" + rValue.getSignature());
|
||||
}
|
||||
}
|
||||
return signatures;
|
||||
}
|
||||
|
||||
|
||||
private Collection<String> assignmentsUnaryBu() {
|
||||
ArrayList<String> signatures = new ArrayList<>();
|
||||
Collection<Value> lVals = lValuesBu(new ArrayList<>());
|
||||
for(Value lValue : lVals) {
|
||||
Collection<Value> rVals = rValuesBu(lValue.getAllValues());
|
||||
for(Value rValue : rVals) {
|
||||
for(String unary : unaryBu()) {
|
||||
signatures.add(lValue.getSignature() + "=" + unary + rValue.getSignature());
|
||||
}
|
||||
}
|
||||
}
|
||||
return signatures;
|
||||
}
|
||||
|
||||
private Collection<String> assignmentsBinaryBu() {
|
||||
ArrayList<String> signatures = new ArrayList<>();
|
||||
Collection<Value> lVals = lValuesBu(new ArrayList<>());
|
||||
for(Value lValue : lVals) {
|
||||
Collection<Value> rVal1s = rValuesBu(lValue.getAllValues());
|
||||
for(Value rVal1 : rVal1s) {
|
||||
ArrayList<Value> used = new ArrayList<>();
|
||||
used.addAll(lValue.getAllValues());
|
||||
used.addAll(rVal1.getAllValues());
|
||||
Collection<Value> rVal2s = rValuesBu(used);
|
||||
for(Value rVal2 : rVal2s) {
|
||||
for(String binary : binaryBu()) {
|
||||
signatures.add(lValue.getSignature() + "=" + rVal1.getSignature() + binary + rVal2.getSignature());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return signatures;
|
||||
}
|
||||
|
||||
private Collection<String> unaryBu() {
|
||||
ArrayList<String> unaries = new ArrayList<>();
|
||||
unaries.add(Operator.BOOL_NOT.getAsmOperator());
|
||||
unaries.add(Operator.DECREMENT.getAsmOperator());
|
||||
unaries.add(Operator.INCREMENT.getAsmOperator());
|
||||
unaries.add(Operator.NEG.getAsmOperator());
|
||||
unaries.add(Operator.POS.getAsmOperator());
|
||||
return unaries;
|
||||
}
|
||||
|
||||
private Collection<String> binaryBu() {
|
||||
ArrayList<String> unaries = new ArrayList<>();
|
||||
unaries.add(Operator.BOOL_AND.getAsmOperator());
|
||||
unaries.add(Operator.BOOL_OR.getAsmOperator());
|
||||
unaries.add(Operator.BOOL_XOR.getAsmOperator());
|
||||
unaries.add(Operator.MINUS.getAsmOperator());
|
||||
unaries.add(Operator.PLUS.getAsmOperator());
|
||||
return unaries;
|
||||
}
|
||||
|
||||
|
||||
private Collection<Value> lValuesBu(Collection<Value> usedValues) {
|
||||
ArrayList<Value> values = new ArrayList<>();
|
||||
values.addAll(lValuesVbu(usedValues));
|
||||
Collection<Value> pbus = rValuesPbu(usedValues);
|
||||
for(Value pbu : pbus) {
|
||||
values.add(new Value("_deref_" + pbu.getSignature(), pbu));
|
||||
}
|
||||
for(Value pbu : pbus) {
|
||||
Collection<Value> used = new ArrayList<>();
|
||||
used.addAll(usedValues);
|
||||
used.addAll(pbu.getAllValues());
|
||||
Collection<Value> idxs = rValuesVbu(used);
|
||||
for(Value idx : idxs) {
|
||||
values.add(new Value(pbu.getSignature() + "_derefidx_" + idx.getSignature(), Arrays.asList(pbu, idx)));
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
private Collection<Value> rValuesBu(Collection<Value> usedValues) {
|
||||
ArrayList<Value> values = new ArrayList<>();
|
||||
values.addAll(lValuesBu(usedValues));
|
||||
values.add(new Value("vbuc1"));
|
||||
if(contains(usedValues, "c1")) {
|
||||
values.add(new Value("vbuc2"));
|
||||
}
|
||||
if(contains(usedValues, "c2")) {
|
||||
values.add(new Value("vbuc3"));
|
||||
}
|
||||
if(contains(usedValues, "c3")) {
|
||||
values.add(new Value("vbuc4"));
|
||||
}
|
||||
if(contains(usedValues, "c4")) {
|
||||
values.add(new Value("vbuc5"));
|
||||
}
|
||||
if(contains(usedValues, "c5")) {
|
||||
values.add(new Value("vbuc6"));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
private Collection<Value> lValuesVbu(Collection<Value> usedValues) {
|
||||
ArrayList<Value> values = new ArrayList<>();
|
||||
values.add(new Value("vbuaa"));
|
||||
values.add(new Value("vbuxx"));
|
||||
values.add(new Value("vbuyy"));
|
||||
values.add(new Value("vbuz1"));
|
||||
if(contains(usedValues, "z1")) {
|
||||
values.add(new Value("vbuz2"));
|
||||
}
|
||||
if(contains(usedValues, "z2")) {
|
||||
values.add(new Value("vbuz3"));
|
||||
}
|
||||
if(contains(usedValues, "z3")) {
|
||||
values.add(new Value("vbuz4"));
|
||||
}
|
||||
if(contains(usedValues, "z4")) {
|
||||
values.add(new Value("vbuz5"));
|
||||
}
|
||||
if(contains(usedValues, "z5")) {
|
||||
values.add(new Value("vbuz6"));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
private Collection<Value> rValuesVbu(Collection<Value> usedValues) {
|
||||
ArrayList<Value> values = new ArrayList<>();
|
||||
values.addAll(lValuesVbu(usedValues));
|
||||
values.add(new Value("vbuc1"));
|
||||
if(contains(usedValues, "c1")) {
|
||||
values.add(new Value("vbuc2"));
|
||||
}
|
||||
if(contains(usedValues, "c2")) {
|
||||
values.add(new Value("vbuc3"));
|
||||
}
|
||||
if(contains(usedValues, "c3")) {
|
||||
values.add(new Value("vbuc4"));
|
||||
}
|
||||
if(contains(usedValues, "c4")) {
|
||||
values.add(new Value("vbuc5"));
|
||||
}
|
||||
if(contains(usedValues, "c5")) {
|
||||
values.add(new Value("vbuc6"));
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
private Collection<Value> lValuesPbu(Collection<Value> usedValues) {
|
||||
ArrayList<Value> values = new ArrayList<>();
|
||||
values.add(new Value("pbuz1"));
|
||||
if(contains(usedValues, "z1")) {
|
||||
values.add(new Value("pbuz2"));
|
||||
}
|
||||
if(contains(usedValues, "z2")) {
|
||||
values.add(new Value("pbuz3"));
|
||||
}
|
||||
if(contains(usedValues, "z3")) {
|
||||
values.add(new Value("pbuz4"));
|
||||
}
|
||||
if(contains(usedValues, "z4")) {
|
||||
values.add(new Value("pbuz5"));
|
||||
}
|
||||
if(contains(usedValues, "z5")) {
|
||||
values.add(new Value("pbuz6"));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
private Collection<Value> rValuesPbu(Collection<Value> usedValues) {
|
||||
ArrayList<Value> values = new ArrayList<>();
|
||||
values.addAll(lValuesPbu(usedValues));
|
||||
values.add(new Value("pbuc1"));
|
||||
if(contains(usedValues, "c1")) {
|
||||
values.add(new Value("pbuc2"));
|
||||
}
|
||||
if(contains(usedValues, "c2")) {
|
||||
values.add(new Value("pbuc3"));
|
||||
}
|
||||
if(contains(usedValues, "c3")) {
|
||||
values.add(new Value("pbuc4"));
|
||||
}
|
||||
if(contains(usedValues, "c4")) {
|
||||
values.add(new Value("pbuc5"));
|
||||
}
|
||||
if(contains(usedValues, "c5")) {
|
||||
values.add(new Value("pbuc6"));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
private boolean contains(Collection<Value> usedValues, String subString) {
|
||||
for(Value usedValue : usedValues) {
|
||||
if(usedValue.getSignature().contains(subString)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** A signature that is part of a fragment signature. The signature may have sub-values (eg. if. it is a _derefidx_ signature */
|
||||
public static class Value {
|
||||
|
||||
private String signature;
|
||||
|
||||
private Collection<Value> subValues;
|
||||
|
||||
public Value(String signature) {
|
||||
this(signature, new ArrayList<Value>());
|
||||
}
|
||||
|
||||
public Value(String signature, Collection<Value> subValues) {
|
||||
this.signature = signature;
|
||||
this.subValues = subValues;
|
||||
}
|
||||
|
||||
public Value(String signature, Value subVal) {
|
||||
this(signature, Arrays.asList(subVal));
|
||||
}
|
||||
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public Collection<Value> getAllValues() {
|
||||
ArrayList<Value> values = new ArrayList<>();
|
||||
values.add(this);
|
||||
if(subValues != null) {
|
||||
values.addAll(subValues);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -2,10 +2,12 @@ package dk.camelot64.kickc.test;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.Compiler;
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer;
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages;
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -28,6 +30,11 @@ public class TestPrograms {
|
||||
helper = new ReferenceHelper("dk/camelot64/kickc/test/ref/");
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() {
|
||||
AsmFragmentTemplateSynthesizer.clearCaches();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() throws Exception {
|
||||
CompileLog log = new CompileLog();
|
||||
|
185383
src/test/java/dk/camelot64/kickc/test/ref/fragments-assignment-binary.log
Normal file
185383
src/test/java/dk/camelot64/kickc/test/ref/fragments-assignment-binary.log
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user