mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-10 13:38:18 +00:00
Added fragment manager with ability to do fragment synthesis from sub-fragments. Added more fragments.
This commit is contained in:
parent
2a19c52c1d
commit
d640c53033
@ -2,15 +2,9 @@ package dk.camelot64.kickc.asm;
|
||||
|
||||
import dk.camelot64.kickc.NumberParser;
|
||||
import dk.camelot64.kickc.asm.parser.Asm6502BaseVisitor;
|
||||
import dk.camelot64.kickc.asm.parser.Asm6502Lexer;
|
||||
import dk.camelot64.kickc.asm.parser.Asm6502Parser;
|
||||
import dk.camelot64.kickc.icl.*;
|
||||
import org.antlr.v4.runtime.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ -345,8 +339,6 @@ public class AsmFragment {
|
||||
return bound;
|
||||
}
|
||||
|
||||
/** Cache for fragment files. Maps signature to the parsed file. */
|
||||
private static Map<String, Asm6502Parser.FileContext> fragmentFileCache = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Generate assembler code for the assembler fragment.
|
||||
@ -355,36 +347,9 @@ public class AsmFragment {
|
||||
*/
|
||||
public void generate(AsmProgram asm) {
|
||||
String signature = this.getSignature();
|
||||
Asm6502Parser.FileContext fragmentFile = fragmentFileCache.get(signature);
|
||||
if(fragmentFile==null) {
|
||||
ClassLoader classLoader = this.getClass().getClassLoader();
|
||||
final URL fragmentResource = classLoader.getResource("dk/camelot64/kickc/asm/fragment/" + signature + ".asm");
|
||||
if (fragmentResource == null) {
|
||||
throw new UnknownFragmentException(signature);
|
||||
}
|
||||
|
||||
try {
|
||||
InputStream fragmentStream = fragmentResource.openStream();
|
||||
Asm6502Lexer lexer = new Asm6502Lexer(CharStreams.fromStream(fragmentStream));
|
||||
Asm6502Parser parser = new Asm6502Parser(new CommonTokenStream(lexer));
|
||||
parser.addErrorListener(new BaseErrorListener() {
|
||||
@Override
|
||||
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
|
||||
throw new RuntimeException("Error parsing fragment fragmentFile " + fragmentResource + "\n - Line: " + line + "\n - Message: " + msg);
|
||||
}
|
||||
});
|
||||
parser.setBuildParseTree(true);
|
||||
fragmentFile = parser.file();
|
||||
fragmentStream.close();
|
||||
fragmentFileCache.put(signature, fragmentFile);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error reading code fragment " + fragmentResource);
|
||||
}
|
||||
}
|
||||
|
||||
Asm6502Parser.FileContext fragmentFile = AsmFragmentManager.getFragment(signature);
|
||||
AsmSequenceGenerator asmSequenceGenerator = new AsmSequenceGenerator(signature, this, asm);
|
||||
asmSequenceGenerator.generate(fragmentFile);
|
||||
|
||||
}
|
||||
|
||||
private static class AsmSequenceGenerator extends Asm6502BaseVisitor {
|
||||
|
149
src/main/java/dk/camelot64/kickc/asm/AsmFragmentManager.java
Normal file
149
src/main/java/dk/camelot64/kickc/asm/AsmFragmentManager.java
Normal file
@ -0,0 +1,149 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.asm.parser.Asm6502Lexer;
|
||||
import dk.camelot64.kickc.asm.parser.Asm6502Parser;
|
||||
import org.antlr.v4.runtime.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Provides fragments from their signature.
|
||||
* <p>
|
||||
* The first priority is loading a fragment file from the fragment-folder.
|
||||
* If no fragment file is found for the signature the manager attempts to synthesise a fragment from another fragment.
|
||||
*/
|
||||
public class AsmFragmentManager {
|
||||
|
||||
/**
|
||||
* Cache for fragment files. Maps signature to the parsed file.
|
||||
*/
|
||||
private static Map<String, Asm6502Parser.FileContext> fragmentFileCache = new HashMap<>();
|
||||
|
||||
private static Asm6502Parser.FileContext UNKNOWN = new Asm6502Parser.FileContext(null, 0);
|
||||
|
||||
public static Asm6502Parser.FileContext getFragment(String signature) {
|
||||
Asm6502Parser.FileContext fragment = fragmentFileCache.get(signature);
|
||||
if(fragment==UNKNOWN) {
|
||||
throw new AsmFragment.UnknownFragmentException(signature);
|
||||
}
|
||||
if (fragment == null) {
|
||||
CharStream fragmentCharStream = loadOrSynthesizeFragment(signature);
|
||||
if (fragmentCharStream == null) {
|
||||
fragmentFileCache.put(signature, UNKNOWN);
|
||||
throw new AsmFragment.UnknownFragmentException(signature);
|
||||
}
|
||||
fragment = parseFragment(fragmentCharStream, signature);
|
||||
fragmentFileCache.put(signature, fragment);
|
||||
}
|
||||
return fragment;
|
||||
}
|
||||
|
||||
private static CharStream loadOrSynthesizeFragment(String signature) {
|
||||
CharStream fragmentCharStream = loadFragment(signature);
|
||||
if (fragmentCharStream == null) {
|
||||
fragmentCharStream = synthesizeFragment(signature);
|
||||
}
|
||||
return fragmentCharStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to synthesize a fragment from other fragments
|
||||
*
|
||||
* @param signature The signature of the fragment to synthesize
|
||||
* @return The synthesized fragment file contents. Null if the fragment could not be synthesized.
|
||||
*/
|
||||
private static CharStream synthesizeFragment(String signature) {
|
||||
if(signature.startsWith("xby=")) {
|
||||
String subSignature = "aby="+signature.substring(4);
|
||||
CharStream subCharStream = loadOrSynthesizeFragment(subSignature);
|
||||
if(subCharStream!=null) {
|
||||
CharStream result = CharStreams.fromString(subCharStream.toString()+"\ntax\n");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if(signature.startsWith("yby=")) {
|
||||
String subSignature = "aby="+signature.substring(4);
|
||||
CharStream subCharStream = loadOrSynthesizeFragment(subSignature);
|
||||
if(subCharStream!=null) {
|
||||
CharStream result = CharStreams.fromString(subCharStream.toString()+"\ntay\n");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if(signature.startsWith("zpby1=")) {
|
||||
String subSignature = "aby="+signature.substring(6).replace("zpby2", "zpby1");
|
||||
CharStream subCharStream = loadOrSynthesizeFragment(subSignature);
|
||||
if(subCharStream!=null) {
|
||||
CharStream result = CharStreams.fromString(subCharStream.toString().replace("zpby1", "zpby2")+"\nsta {zpby1}\n");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if(signature.contains("_lt_xby_then_")) {
|
||||
int pos = signature.indexOf("_lt_xby_then_");
|
||||
String subSignature = "xby_gte_"+signature.substring(0, pos)+"_then_"+signature.substring(pos+13);
|
||||
return loadOrSynthesizeFragment(subSignature);
|
||||
}
|
||||
if(signature.contains("_lt_yby_then_")) {
|
||||
int pos = signature.indexOf("_lt_yby_then_");
|
||||
String subSignature = "yby_gte_"+signature.substring(0, pos)+"_then_"+signature.substring(pos+13);
|
||||
return loadOrSynthesizeFragment(subSignature);
|
||||
}
|
||||
if(signature.contains("_lt_aby_then_")) {
|
||||
int pos = signature.indexOf("_lt_aby_then_");
|
||||
String subSignature = "aby_gte_"+signature.substring(0, pos)+"_then_"+signature.substring(pos+13);
|
||||
return loadOrSynthesizeFragment(subSignature);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Look for a fragment on the disk.
|
||||
*
|
||||
* @param signature The fragment signature
|
||||
* @return The fragment file contents. Null if the fragment is not on the disk.
|
||||
*/
|
||||
private static CharStream loadFragment(String signature) {
|
||||
ClassLoader classLoader = AsmFragmentManager.class.getClassLoader();
|
||||
URL fragmentUrl = classLoader.getResource("dk/camelot64/kickc/asm/fragment/" + signature + ".asm");
|
||||
if(fragmentUrl==null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
InputStream fragmentStream = fragmentUrl.openStream();
|
||||
return CharStreams.fromStream(fragmentStream);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error loading fragment file " + fragmentUrl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an ASM fragment.
|
||||
*
|
||||
* @param fragmentCharStream The stream containing the fragment syntax
|
||||
* @param fragmentFileName The filename (used in error messages)
|
||||
* @return The parsed fragment ready for generating
|
||||
* @throws IOException if the parsing/loading fails
|
||||
*/
|
||||
private static Asm6502Parser.FileContext parseFragment(CharStream fragmentCharStream, final String fragmentFileName) {
|
||||
Asm6502Parser.FileContext fragmentFile;
|
||||
Asm6502Lexer lexer = new Asm6502Lexer(fragmentCharStream);
|
||||
Asm6502Parser parser = new Asm6502Parser(new CommonTokenStream(lexer));
|
||||
parser.addErrorListener(new BaseErrorListener() {
|
||||
@Override
|
||||
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
|
||||
throw new RuntimeException("Error parsing fragment fragmentFile " + fragmentFileName + "\n - Line: " + line + "\n - Message: " + msg);
|
||||
}
|
||||
});
|
||||
parser.setBuildParseTree(true);
|
||||
fragmentFile = parser.file();
|
||||
return fragmentFile;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1 @@
|
||||
lda #0
|
@ -0,0 +1,3 @@
|
||||
stx $ff
|
||||
sec
|
||||
sbc $ff
|
@ -0,0 +1,3 @@
|
||||
sty $ff
|
||||
sec
|
||||
sbc $ff
|
@ -0,0 +1,2 @@
|
||||
sec
|
||||
sbc {zpby1}
|
@ -0,0 +1,4 @@
|
||||
sta $ff
|
||||
txa
|
||||
sec
|
||||
sbc $ff
|
@ -0,0 +1 @@
|
||||
lda #0
|
@ -0,0 +1,4 @@
|
||||
txa
|
||||
sty $ff
|
||||
sec
|
||||
sbc $ff
|
@ -0,0 +1,3 @@
|
||||
txa
|
||||
sec
|
||||
sbc {zpby1}
|
@ -0,0 +1,4 @@
|
||||
sta $ff
|
||||
tya
|
||||
sec
|
||||
sbc $ff
|
@ -0,0 +1,4 @@
|
||||
tya
|
||||
stx $ff
|
||||
sec
|
||||
sbc $ff
|
@ -0,0 +1 @@
|
||||
lda #0
|
@ -0,0 +1,3 @@
|
||||
tya
|
||||
sec
|
||||
sbc {zpby1}
|
@ -0,0 +1,3 @@
|
||||
eor #$ff
|
||||
sec
|
||||
adc {zpby1}
|
@ -0,0 +1,4 @@
|
||||
stx $ff
|
||||
lda {zpby1}
|
||||
sec
|
||||
sbc $ff
|
@ -0,0 +1,4 @@
|
||||
sty $ff
|
||||
lda {zpby1}
|
||||
sec
|
||||
sbc $ff
|
@ -0,0 +1,2 @@
|
||||
cmp #{coby1}
|
||||
bcs {la1}
|
@ -0,0 +1,2 @@
|
||||
cmp {zpby1}
|
||||
bcs {la1}
|
@ -0,0 +1,2 @@
|
||||
sec
|
||||
sbc {zpby1}
|
@ -0,0 +1 @@
|
||||
tax
|
@ -0,0 +1,3 @@
|
||||
sta $ff
|
||||
cpx $ff
|
||||
bcs {la1}
|
@ -0,0 +1,2 @@
|
||||
cpx #{coby1}
|
||||
bcs {la1}
|
@ -0,0 +1,2 @@
|
||||
cpx {zpby1}
|
||||
bcs {la1}
|
@ -0,0 +1,3 @@
|
||||
sta $ff
|
||||
cpx $ff
|
||||
bcc {la1}
|
@ -0,0 +1,3 @@
|
||||
sty $ff
|
||||
cpx $ff
|
||||
bcc {la1}
|
@ -0,0 +1,2 @@
|
||||
cpx {zpby1}
|
||||
bcc {la1}
|
@ -0,0 +1,3 @@
|
||||
txa
|
||||
sec
|
||||
sbc {zpby1}
|
@ -0,0 +1 @@
|
||||
tay
|
@ -0,0 +1,3 @@
|
||||
sta $ff
|
||||
cpy $ff
|
||||
bcs {la1}
|
@ -0,0 +1,2 @@
|
||||
cpy #{coby1}
|
||||
bcs {la1}
|
@ -0,0 +1,2 @@
|
||||
cpy {zpby1}
|
||||
bcs {la1}
|
@ -0,0 +1,3 @@
|
||||
sta $ff
|
||||
cpy $ff
|
||||
bcc {la1}
|
@ -0,0 +1,3 @@
|
||||
stx $ff
|
||||
cpy $ff
|
||||
bcc {la1}
|
@ -0,0 +1,2 @@
|
||||
cpy {zpby1}
|
||||
bcc {la1}
|
@ -0,0 +1,3 @@
|
||||
tya
|
||||
sec
|
||||
sbc {zpby1}
|
@ -70,20 +70,25 @@ render__B1_from_render:
|
||||
render__B1_from_B3:
|
||||
render__B1:
|
||||
render__B2_from_B1:
|
||||
ldy #0
|
||||
lda #0
|
||||
sta 7
|
||||
render__B2_from_B5:
|
||||
render__B2:
|
||||
sty 10
|
||||
lda 7
|
||||
sta 10
|
||||
lda 2
|
||||
sta 11
|
||||
jsr findcol
|
||||
render__B5:
|
||||
lda 9
|
||||
ldy 7
|
||||
sta (3),y
|
||||
lda #230
|
||||
ldy 7
|
||||
sta (5),y
|
||||
iny
|
||||
cpy #40
|
||||
inc 7
|
||||
lda 7
|
||||
cmp #40
|
||||
bcc render__B2_from_B5
|
||||
render__B3:
|
||||
lda 5
|
||||
@ -110,8 +115,7 @@ findcol:
|
||||
findcol__B1_from_findcol:
|
||||
lda #0
|
||||
sta 9
|
||||
lda #255
|
||||
sta 7
|
||||
ldy #255
|
||||
ldx #0
|
||||
findcol__B1_from_B13:
|
||||
findcol__B1:
|
||||
@ -145,9 +149,8 @@ findcol__B10:
|
||||
sta 8
|
||||
findcol__B11_from_B10:
|
||||
findcol__B11:
|
||||
lda 8
|
||||
cmp 7
|
||||
bcc findcol__B12
|
||||
cpy 8
|
||||
bcs findcol__B12
|
||||
findcol__B13_from_B11:
|
||||
findcol__B13:
|
||||
inx
|
||||
@ -163,8 +166,7 @@ findcol__Breturn:
|
||||
findcol__B12:
|
||||
lda 4608,x
|
||||
sta 9
|
||||
lda 8
|
||||
sta 7
|
||||
ldy 8
|
||||
findcol__B13_from_B12:
|
||||
jmp findcol__B13
|
||||
findcol__B9:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,7 @@
|
||||
(byte) findcol::diff
|
||||
(byte) findcol::diff#0 zp byte:8 20002.0
|
||||
(byte) findcol::diff#1 zp byte:8 20002.0
|
||||
(byte~) findcol::diff#13 zp byte:7 20002.0
|
||||
(byte~) findcol::diff#13 reg byte y 20002.0
|
||||
(byte) findcol::diff#2 zp byte:8 20002.0
|
||||
(byte) findcol::diff#3 zp byte:8 20002.0
|
||||
(byte) findcol::diff#4 zp byte:8 10001.0
|
||||
@ -47,8 +47,8 @@
|
||||
(byte) findcol::mincol#11 zp byte:9 1250.125
|
||||
(byte) findcol::mincol#2 zp byte:9 13334.666666666666
|
||||
(byte) findcol::mindiff
|
||||
(byte) findcol::mindiff#10 zp byte:7 1875.1875
|
||||
(byte) findcol::mindiff#11 zp byte:7 10001.0
|
||||
(byte) findcol::mindiff#10 reg byte y 1875.1875
|
||||
(byte) findcol::mindiff#11 reg byte y 10001.0
|
||||
(byte) findcol::return
|
||||
(byte) findcol::return#0 zp byte:9 343.8125
|
||||
(byte) findcol::x
|
||||
@ -84,8 +84,8 @@
|
||||
(byte*) render::colline#1 zp ptr byte:3 67.33333333333333
|
||||
(byte*) render::colline#2 zp ptr byte:3 35.38235294117647
|
||||
(byte) render::x
|
||||
(byte) render::x#1 reg byte y 1501.5
|
||||
(byte) render::x#2 reg byte y 166.83333333333334
|
||||
(byte) render::x#1 zp byte:7 1501.5
|
||||
(byte) render::x#2 zp byte:7 166.83333333333334
|
||||
(byte) render::y
|
||||
(byte) render::y#1 zp byte:2 151.5
|
||||
(byte) render::y#2 zp byte:2 34.371428571428574
|
||||
@ -93,9 +93,9 @@
|
||||
zp byte:2 [ render::y#2 render::y#1 addpoint::c#6 ]
|
||||
zp ptr byte:3 [ render::colline#2 render::colline#1 ]
|
||||
zp ptr byte:5 [ render::chrline#2 render::chrline#1 ]
|
||||
reg byte y [ render::x#2 render::x#1 ]
|
||||
zp byte:7 [ render::x#2 render::x#1 ]
|
||||
reg byte x [ findcol::i#12 findcol::i#1 ]
|
||||
zp byte:7 [ findcol::mindiff#10 findcol::mindiff#11 findcol::diff#13 ]
|
||||
reg byte y [ findcol::mindiff#10 findcol::mindiff#11 findcol::diff#13 ]
|
||||
zp byte:8 [ findcol::diff#4 findcol::diff#0 findcol::diff#1 findcol::diff#6 findcol::diff#3 findcol::diff#2 findcol::xp#0 ]
|
||||
zp byte:9 [ findcol::return#0 findcol::mincol#11 findcol::mincol#2 findcol::mincol#1 ]
|
||||
reg byte a [ addpoint::x#6 ]
|
||||
|
Loading…
x
Reference in New Issue
Block a user