mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-09-08 17:54:40 +00:00
Fixed infinite recursion
This commit is contained in:
parent
0efe62585b
commit
96f2610d25
@ -1,5 +1,6 @@
|
|||||||
package dk.camelot64.kickc.fragment;
|
package dk.camelot64.kickc.fragment;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.CompileLog;
|
||||||
import dk.camelot64.kickc.parser.KickCLexer;
|
import dk.camelot64.kickc.parser.KickCLexer;
|
||||||
import dk.camelot64.kickc.parser.KickCParser;
|
import dk.camelot64.kickc.parser.KickCParser;
|
||||||
import org.antlr.v4.runtime.*;
|
import org.antlr.v4.runtime.*;
|
||||||
@ -19,6 +20,8 @@ import java.util.regex.Pattern;
|
|||||||
*/
|
*/
|
||||||
public class AsmFragmentManager {
|
public class AsmFragmentManager {
|
||||||
|
|
||||||
|
static boolean verboseFragmentLog = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache for fragment files. Maps signature to the parsed file.
|
* Cache for fragment files. Maps signature to the parsed file.
|
||||||
*/
|
*/
|
||||||
@ -26,8 +29,8 @@ public class AsmFragmentManager {
|
|||||||
|
|
||||||
private static KickCParser.AsmFileContext UNKNOWN = new KickCParser.AsmFileContext(null, 0);
|
private static KickCParser.AsmFileContext UNKNOWN = new KickCParser.AsmFileContext(null, 0);
|
||||||
|
|
||||||
public static AsmFragment getFragment(AsmFragmentSignature signature) {
|
public static AsmFragment getFragment(AsmFragmentSignature signature, CompileLog log) {
|
||||||
KickCParser.AsmFileContext fragmentFile = getFragmentFile(signature.getSignature());
|
KickCParser.AsmFileContext fragmentFile = getFragmentFile(signature.getSignature(), log);
|
||||||
AsmFragment fragment = new AsmFragment(
|
AsmFragment fragment = new AsmFragment(
|
||||||
signature.getProgram(),
|
signature.getProgram(),
|
||||||
signature.getSignature(),
|
signature.getSignature(),
|
||||||
@ -37,14 +40,20 @@ public class AsmFragmentManager {
|
|||||||
return fragment;
|
return fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static KickCParser.AsmFileContext getFragmentFile(String signature) {
|
private static KickCParser.AsmFileContext getFragmentFile(String signature, CompileLog log) {
|
||||||
KickCParser.AsmFileContext fragment = fragmentFileCache.get(signature);
|
KickCParser.AsmFileContext fragment = fragmentFileCache.get(signature);
|
||||||
if (fragment == UNKNOWN) {
|
if (fragment == UNKNOWN) {
|
||||||
|
if (verboseFragmentLog) {
|
||||||
|
log.append("Unknown fragment " + signature);
|
||||||
|
}
|
||||||
throw new UnknownFragmentException(signature);
|
throw new UnknownFragmentException(signature);
|
||||||
}
|
}
|
||||||
if (fragment == null) {
|
if (fragment == null) {
|
||||||
CharStream fragmentCharStream = loadOrSynthesizeFragment(signature);
|
CharStream fragmentCharStream = loadOrSynthesizeFragment(signature, log);
|
||||||
if (fragmentCharStream == null) {
|
if (fragmentCharStream == null) {
|
||||||
|
if (verboseFragmentLog) {
|
||||||
|
log.append("Unknown fragment " + signature);
|
||||||
|
}
|
||||||
fragmentFileCache.put(signature, UNKNOWN);
|
fragmentFileCache.put(signature, UNKNOWN);
|
||||||
throw new UnknownFragmentException(signature);
|
throw new UnknownFragmentException(signature);
|
||||||
}
|
}
|
||||||
@ -54,10 +63,17 @@ public class AsmFragmentManager {
|
|||||||
return fragment;
|
return fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CharStream loadOrSynthesizeFragment(String signature) {
|
private static CharStream loadOrSynthesizeFragment(String signature, CompileLog log) {
|
||||||
CharStream fragmentCharStream = loadFragment(signature);
|
CharStream fragmentCharStream = loadFragment(signature);
|
||||||
if (fragmentCharStream == null) {
|
if (fragmentCharStream == null) {
|
||||||
fragmentCharStream = synthesizeFragment(signature);
|
if (verboseFragmentLog) {
|
||||||
|
log.append("Attempting fragment synthesis " + signature);
|
||||||
|
}
|
||||||
|
fragmentCharStream = synthesizeFragment(signature, log);
|
||||||
|
} else {
|
||||||
|
if (verboseFragmentLog) {
|
||||||
|
log.append("Succesfully loaded fragment " + signature);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return fragmentCharStream;
|
return fragmentCharStream;
|
||||||
}
|
}
|
||||||
@ -68,7 +84,7 @@ public class AsmFragmentManager {
|
|||||||
* @param signature The signature of the fragment to synthesize
|
* @param signature The signature of the fragment to synthesize
|
||||||
* @return The synthesized fragment file contents. Null if the fragment could not be synthesized.
|
* @return The synthesized fragment file contents. Null if the fragment could not be synthesized.
|
||||||
*/
|
*/
|
||||||
private static CharStream synthesizeFragment(String signature) {
|
private static CharStream synthesizeFragment(String signature, CompileLog log) {
|
||||||
|
|
||||||
Map<String, String> mapZpsby = new LinkedHashMap<>();
|
Map<String, String> mapZpsby = new LinkedHashMap<>();
|
||||||
mapZpsby.put("zpsby2", "zpsby1");
|
mapZpsby.put("zpsby2", "zpsby1");
|
||||||
@ -105,12 +121,12 @@ public class AsmFragmentManager {
|
|||||||
synths.add(new FragmentSynthesis("(.*)=zpby1(.*)", ".*=.*as?by.*|zpby1=.*", "lda {zpby1}\n", "$1=aby$2", null, mapZpby));
|
synths.add(new FragmentSynthesis("(.*)=zpby1(.*)", ".*=.*as?by.*|zpby1=.*", "lda {zpby1}\n", "$1=aby$2", null, mapZpby));
|
||||||
synths.add(new FragmentSynthesis("(.*)=zpsby1(.*)", ".*=.*as?by.*|zpsby1=.*", "lda {zpsby1}\n", "$1=aby$2", null, mapZpsby));
|
synths.add(new FragmentSynthesis("(.*)=zpsby1(.*)", ".*=.*as?by.*|zpsby1=.*", "lda {zpsby1}\n", "$1=aby$2", null, mapZpsby));
|
||||||
synths.add(new FragmentSynthesis("(.*)=_deref_cowo1(.*)", ".*=.*as?by.*", "lda {cowo1}\n", "$1=aby$2", null, mapConst));
|
synths.add(new FragmentSynthesis("(.*)=_deref_cowo1(.*)", ".*=.*as?by.*", "lda {cowo1}\n", "$1=aby$2", null, mapConst));
|
||||||
synths.add(new FragmentSynthesis("(.*)=_deref_zpptrby1(.*)", ".*=.*as?by.*|.*=.*ys?by.*", "ldy #0\n"+"lda ({zpptrby1}),y\n", "$1=aby$2", null, mapZpptrby));
|
synths.add(new FragmentSynthesis("(.*)=_deref_zpptrby1(.*)", ".*=.*as?by.*|.*=.*ys?by.*", "ldy #0\n" + "lda ({zpptrby1}),y\n", "$1=aby$2", null, mapZpptrby));
|
||||||
|
|
||||||
synths.add(new FragmentSynthesis("(.*)=(.*)_xby", ".*=[ax]s?by.*xs?by", "txa\n", "$1=$2_aby", null, null));
|
synths.add(new FragmentSynthesis("(.*)=(.*)_xby", ".*=[ax]s?by.*xs?by|.*derefidx_xs?by", "txa\n", "$1=$2_aby", null, null));
|
||||||
synths.add(new FragmentSynthesis("(.*)=(.*)_xsby", ".*=[ax]s?by.*xs?by", "txa\n", "$1=$2_asby", null, null));
|
synths.add(new FragmentSynthesis("(.*)=(.*)_xsby", ".*=[ax]s?by.*xs?by|.*derefidx_xs?by", "txa\n", "$1=$2_asby", null, null));
|
||||||
synths.add(new FragmentSynthesis("(.*)=(.*)_yby", ".*=[ay]s?by.*ys?by", "tya\n", "$1=$2_aby", null, null));
|
synths.add(new FragmentSynthesis("(.*)=(.*)_yby", ".*=[ay]s?by.*ys?by|.*derefidx_ys?by", "tya\n", "$1=$2_aby", null, null));
|
||||||
synths.add(new FragmentSynthesis("(.*)=(.*)_ysby", ".*=[ay]s?by.*ys?by", "tya\n", "$1=$2_asby", null, null));
|
synths.add(new FragmentSynthesis("(.*)=(.*)_ysby", ".*=[ay]s?by.*ys?by|.*derefidx_ys?by", "tya\n", "$1=$2_asby", null, null));
|
||||||
synths.add(new FragmentSynthesis("(.*)=(.*)_zpby1", ".*=.*as?by.*", "lda {zpby1}\n", "$1=$2_aby", null, mapZpby));
|
synths.add(new FragmentSynthesis("(.*)=(.*)_zpby1", ".*=.*as?by.*", "lda {zpby1}\n", "$1=$2_aby", null, mapZpby));
|
||||||
synths.add(new FragmentSynthesis("(.*)=(.*)_zpsby1", ".*=.*as?by.*", "lda {zpsby1}\n", "$1=$2_asby", null, mapZpsby));
|
synths.add(new FragmentSynthesis("(.*)=(.*)_zpsby1", ".*=.*as?by.*", "lda {zpsby1}\n", "$1=$2_asby", null, mapZpsby));
|
||||||
|
|
||||||
@ -125,7 +141,7 @@ public class AsmFragmentManager {
|
|||||||
synths.add(new FragmentSynthesis("zpby1_(lt|gt|le|ge|eq|neq)_(.*)", ".*as?by.*", "lda {zpby1}\n", "aby_$1_$2", null, mapZpby));
|
synths.add(new FragmentSynthesis("zpby1_(lt|gt|le|ge|eq|neq)_(.*)", ".*as?by.*", "lda {zpby1}\n", "aby_$1_$2", null, mapZpby));
|
||||||
synths.add(new FragmentSynthesis("zpsby1_(lt|gt|le|ge|eq|neq)_(.*)", ".*as?by.*", "lda {zpsby1}\n", "asby_$1_$2", null, mapZpsby));
|
synths.add(new FragmentSynthesis("zpsby1_(lt|gt|le|ge|eq|neq)_(.*)", ".*as?by.*", "lda {zpsby1}\n", "asby_$1_$2", null, mapZpsby));
|
||||||
synths.add(new FragmentSynthesis("_deref_cowo1_(lt|gt|le|ge|eq|neq)_(.*)", ".*as?by.*", "lda {cowo1}\n", "aby_$1_$2", null, mapConst));
|
synths.add(new FragmentSynthesis("_deref_cowo1_(lt|gt|le|ge|eq|neq)_(.*)", ".*as?by.*", "lda {cowo1}\n", "aby_$1_$2", null, mapConst));
|
||||||
synths.add(new FragmentSynthesis("_deref_zpptrby1_(lt|gt|le|ge|eq|neq)_(.*)", ".*=.*as?by.*|.*=.*ys?by.*", "ldy #0\n"+"lda ({zpptrby1}),y\n", "aby_$1_$2", null, mapZpptrby));
|
synths.add(new FragmentSynthesis("_deref_zpptrby1_(lt|gt|le|ge|eq|neq)_(.*)", ".*=.*as?by.*|.*=.*ys?by.*", "ldy #0\n" + "lda ({zpptrby1}),y\n", "aby_$1_$2", null, mapZpptrby));
|
||||||
synths.add(new FragmentSynthesis("(.*)_ge_(as?by)_then_(.*)", ".*[a]s?by.*_ge.*", null, "$2_lt_$1_then_$3", null, null));
|
synths.add(new FragmentSynthesis("(.*)_ge_(as?by)_then_(.*)", ".*[a]s?by.*_ge.*", null, "$2_lt_$1_then_$3", null, null));
|
||||||
synths.add(new FragmentSynthesis("(.*)_ge_(xs?by)_then_(.*)", ".*[ax]s?by.*_ge.*", null, "$2_lt_$1_then_$3", null, null));
|
synths.add(new FragmentSynthesis("(.*)_ge_(xs?by)_then_(.*)", ".*[ax]s?by.*_ge.*", null, "$2_lt_$1_then_$3", null, null));
|
||||||
synths.add(new FragmentSynthesis("(.*)_ge_(ys?by)_then_(.*)", ".*[axy]s?by.*_ge.*", null, "$2_lt_$1_then_$3", null, null));
|
synths.add(new FragmentSynthesis("(.*)_ge_(ys?by)_then_(.*)", ".*[axy]s?by.*_ge.*", null, "$2_lt_$1_then_$3", null, null));
|
||||||
@ -146,8 +162,11 @@ public class AsmFragmentManager {
|
|||||||
synths.add(new FragmentSynthesis("(.*)_eq_(ys?by)_then_(.*)", ".*[axy]s?by.*_eq.*", null, "$2_eq_$1_then_$3", null, null));
|
synths.add(new FragmentSynthesis("(.*)_eq_(ys?by)_then_(.*)", ".*[axy]s?by.*_eq.*", null, "$2_eq_$1_then_$3", null, null));
|
||||||
|
|
||||||
for (FragmentSynthesis synth : synths) {
|
for (FragmentSynthesis synth : synths) {
|
||||||
CharStream synthesized = synth.synthesize(signature);
|
CharStream synthesized = synth.synthesize(signature, log);
|
||||||
if(synthesized!=null) {
|
if (synthesized != null) {
|
||||||
|
if (verboseFragmentLog) {
|
||||||
|
log.append("Succesfully synthesized fragment " + signature + " (from " + synth.getSubSignature() + ")");
|
||||||
|
}
|
||||||
return synthesized;
|
return synthesized;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -156,7 +175,9 @@ public class AsmFragmentManager {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** AsmFragment synthesis based on matching fragment signature and reusing another fragment with added prefix/postfix and some bind-mappings*/
|
/**
|
||||||
|
* AsmFragment synthesis based on matching fragment signature and reusing another fragment with added prefix/postfix and some bind-mappings
|
||||||
|
*/
|
||||||
private static class FragmentSynthesis {
|
private static class FragmentSynthesis {
|
||||||
|
|
||||||
private String sigMatch;
|
private String sigMatch;
|
||||||
@ -165,6 +186,7 @@ public class AsmFragmentManager {
|
|||||||
private String sigReplace;
|
private String sigReplace;
|
||||||
private String asmPostfix;
|
private String asmPostfix;
|
||||||
private Map<String, String> bindMappings;
|
private Map<String, String> bindMappings;
|
||||||
|
private String subSignature;
|
||||||
|
|
||||||
public FragmentSynthesis(String sigMatch, String sigAvoid, String asmPrefix, String sigReplace, String asmPostfix, Map<String, String> bindMappings) {
|
public FragmentSynthesis(String sigMatch, String sigAvoid, String asmPrefix, String sigReplace, String asmPostfix, Map<String, String> bindMappings) {
|
||||||
this.sigMatch = sigMatch;
|
this.sigMatch = sigMatch;
|
||||||
@ -175,23 +197,23 @@ public class AsmFragmentManager {
|
|||||||
this.bindMappings = bindMappings;
|
this.bindMappings = bindMappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CharStream synthesize(String signature) {
|
public CharStream synthesize(String signature, CompileLog log) {
|
||||||
if (signature.matches(sigMatch) ) {
|
if (signature.matches(sigMatch)) {
|
||||||
if (sigAvoid == null || !signature.matches(sigAvoid)) {
|
if (sigAvoid == null || !signature.matches(sigAvoid)) {
|
||||||
String subSignature = regexpRewriteSignature(signature, sigMatch, sigReplace);
|
subSignature = regexpRewriteSignature(signature, sigMatch, sigReplace);
|
||||||
if(bindMappings!=null) {
|
if (bindMappings != null) {
|
||||||
for (String bound : bindMappings.keySet()) {
|
for (String bound : bindMappings.keySet()) {
|
||||||
subSignature = subSignature.replace(bound, bindMappings.get(bound));
|
subSignature = subSignature.replace(bound, bindMappings.get(bound));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CharStream subCharStream = loadOrSynthesizeFragment(subSignature);
|
CharStream subCharStream = loadOrSynthesizeFragment(subSignature, log);
|
||||||
if (subCharStream != null) {
|
if (subCharStream != null) {
|
||||||
StringBuilder newFragment = new StringBuilder();
|
StringBuilder newFragment = new StringBuilder();
|
||||||
if(asmPrefix!=null) {
|
if (asmPrefix != null) {
|
||||||
newFragment.append(asmPrefix);
|
newFragment.append(asmPrefix);
|
||||||
}
|
}
|
||||||
String subFragment = subCharStream.toString();
|
String subFragment = subCharStream.toString();
|
||||||
if(bindMappings!=null) {
|
if (bindMappings != null) {
|
||||||
List<String> reverse = new ArrayList<>(bindMappings.keySet());
|
List<String> reverse = new ArrayList<>(bindMappings.keySet());
|
||||||
Collections.reverse(reverse);
|
Collections.reverse(reverse);
|
||||||
for (String bound : reverse) {
|
for (String bound : reverse) {
|
||||||
@ -199,7 +221,7 @@ public class AsmFragmentManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
newFragment.append(subFragment);
|
newFragment.append(subFragment);
|
||||||
if(asmPostfix!=null) {
|
if (asmPostfix != null) {
|
||||||
newFragment.append("\n");
|
newFragment.append("\n");
|
||||||
newFragment.append(asmPostfix);
|
newFragment.append(asmPostfix);
|
||||||
}
|
}
|
||||||
@ -210,6 +232,9 @@ public class AsmFragmentManager {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSubSignature() {
|
||||||
|
return subSignature;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ public class Pass4CodeGeneration {
|
|||||||
}
|
}
|
||||||
StatementAssignment assignment = (StatementAssignment) statement;
|
StatementAssignment assignment = (StatementAssignment) statement;
|
||||||
AsmFragmentSignature signature = new AsmFragmentSignature(assignment, assignmentAlu, program);
|
AsmFragmentSignature signature = new AsmFragmentSignature(assignment, assignmentAlu, program);
|
||||||
AsmFragment asmFragment = AsmFragmentManager.getFragment(signature);
|
AsmFragment asmFragment = AsmFragmentManager.getFragment(signature, program.getLog());
|
||||||
asm.getCurrentSegment().setFragment(asmFragment.getName());
|
asm.getCurrentSegment().setFragment(asmFragment.getName());
|
||||||
asmFragment.generate(asm);
|
asmFragment.generate(asm);
|
||||||
aluState.clear();
|
aluState.clear();
|
||||||
@ -232,14 +232,14 @@ public class Pass4CodeGeneration {
|
|||||||
asm.addComment(lValue.toString(program) + " = " + assignment.getrValue2().toString(program) + " // register copy " + getRegister(lValue));
|
asm.addComment(lValue.toString(program) + " = " + assignment.getrValue2().toString(program) + " // register copy " + getRegister(lValue));
|
||||||
} else {
|
} else {
|
||||||
AsmFragmentSignature asmFragmentSignature = new AsmFragmentSignature(assignment, program);
|
AsmFragmentSignature asmFragmentSignature = new AsmFragmentSignature(assignment, program);
|
||||||
AsmFragment asmFragment = AsmFragmentManager.getFragment(asmFragmentSignature);
|
AsmFragment asmFragment = AsmFragmentManager.getFragment(asmFragmentSignature, program.getLog());
|
||||||
asm.getCurrentSegment().setFragment(asmFragment.getName());
|
asm.getCurrentSegment().setFragment(asmFragment.getName());
|
||||||
asmFragment.generate(asm);
|
asmFragment.generate(asm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (statement instanceof StatementConditionalJump) {
|
} else if (statement instanceof StatementConditionalJump) {
|
||||||
AsmFragmentSignature asmSignature = new AsmFragmentSignature((StatementConditionalJump) statement, block, program, getGraph());
|
AsmFragmentSignature asmSignature = new AsmFragmentSignature((StatementConditionalJump) statement, block, program, getGraph());
|
||||||
AsmFragment asmFragment = AsmFragmentManager.getFragment(asmSignature);
|
AsmFragment asmFragment = AsmFragmentManager.getFragment(asmSignature, program.getLog());
|
||||||
asm.getCurrentSegment().setFragment(asmFragment.getName());
|
asm.getCurrentSegment().setFragment(asmFragment.getName());
|
||||||
asmFragment.generate(asm);
|
asmFragment.generate(asm);
|
||||||
} else if (statement instanceof StatementCall) {
|
} else if (statement instanceof StatementCall) {
|
||||||
@ -349,7 +349,7 @@ public class Pass4CodeGeneration {
|
|||||||
asm.getCurrentSegment().setFragment("register_copy");
|
asm.getCurrentSegment().setFragment("register_copy");
|
||||||
} else {
|
} else {
|
||||||
AsmFragmentSignature asmSignature = new AsmFragmentSignature(lValue, rValue, program, scope);
|
AsmFragmentSignature asmSignature = new AsmFragmentSignature(lValue, rValue, program, scope);
|
||||||
AsmFragment asmFragment = AsmFragmentManager.getFragment(asmSignature);
|
AsmFragment asmFragment = AsmFragmentManager.getFragment(asmSignature, program.getLog());
|
||||||
asm.getCurrentSegment().setFragment(asmFragment.getName());
|
asm.getCurrentSegment().setFragment(asmFragment.getName());
|
||||||
asmFragment.generate(asm);
|
asmFragment.generate(asm);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ byte* SCREEN2 = $0600;
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
for( byte b: 0..100) {
|
for( byte b: 0..100) {
|
||||||
byte b2 = 100-b;
|
byte b2 = 100-b; // Subtract byte from byte (not signed)
|
||||||
SCREEN2[b] = b2;
|
SCREEN2[b] = b2;
|
||||||
signed byte sb = - (signed byte)b;
|
signed byte sb = - (signed byte)b;
|
||||||
SCREEN[b] = (byte)sb;
|
SCREEN[b] = (byte)sb;
|
||||||
|
Loading…
Reference in New Issue
Block a user