1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Added fragment manager with ability to do fragment synthesis from sub-fragments. Added more fragments.

This commit is contained in:
jespergravgaard 2017-08-07 16:35:10 +02:00
parent 2a19c52c1d
commit d640c53033
43 changed files with 9542 additions and 10223 deletions

View File

@ -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 {

View 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;
}
}

View File

@ -0,0 +1 @@
lda #0

View File

@ -0,0 +1,3 @@
stx $ff
sec
sbc $ff

View File

@ -0,0 +1,3 @@
sty $ff
sec
sbc $ff

View File

@ -0,0 +1,2 @@
sec
sbc {zpby1}

View File

@ -0,0 +1,4 @@
sta $ff
txa
sec
sbc $ff

View File

@ -0,0 +1 @@
lda #0

View File

@ -0,0 +1,4 @@
txa
sty $ff
sec
sbc $ff

View File

@ -0,0 +1,3 @@
txa
sec
sbc {zpby1}

View File

@ -0,0 +1,4 @@
sta $ff
tya
sec
sbc $ff

View File

@ -0,0 +1,4 @@
tya
stx $ff
sec
sbc $ff

View File

@ -0,0 +1 @@
lda #0

View File

@ -0,0 +1,3 @@
tya
sec
sbc {zpby1}

View File

@ -0,0 +1,3 @@
eor #$ff
sec
adc {zpby1}

View File

@ -0,0 +1,4 @@
stx $ff
lda {zpby1}
sec
sbc $ff

View File

@ -0,0 +1,4 @@
sty $ff
lda {zpby1}
sec
sbc $ff

View File

@ -0,0 +1,2 @@
cmp #{coby1}
bcs {la1}

View File

@ -0,0 +1,2 @@
cmp {zpby1}
bcs {la1}

View File

@ -0,0 +1,2 @@
sec
sbc {zpby1}

View File

@ -0,0 +1 @@
tax

View File

@ -0,0 +1,3 @@
sta $ff
cpx $ff
bcs {la1}

View File

@ -0,0 +1,2 @@
cpx #{coby1}
bcs {la1}

View File

@ -0,0 +1,2 @@
cpx {zpby1}
bcs {la1}

View File

@ -0,0 +1,3 @@
sta $ff
cpx $ff
bcc {la1}

View File

@ -0,0 +1,3 @@
sty $ff
cpx $ff
bcc {la1}

View File

@ -0,0 +1,2 @@
cpx {zpby1}
bcc {la1}

View File

@ -0,0 +1,3 @@
txa
sec
sbc {zpby1}

View File

@ -0,0 +1 @@
tay

View File

@ -0,0 +1,3 @@
sta $ff
cpy $ff
bcs {la1}

View File

@ -0,0 +1,2 @@
cpy #{coby1}
bcs {la1}

View File

@ -0,0 +1,2 @@
cpy {zpby1}
bcs {la1}

View File

@ -0,0 +1,3 @@
sta $ff
cpy $ff
bcc {la1}

View File

@ -0,0 +1,3 @@
stx $ff
cpy $ff
bcc {la1}

View File

@ -0,0 +1,2 @@
cpy {zpby1}
bcc {la1}

View File

@ -0,0 +1,3 @@
tya
sec
sbc {zpby1}

View File

@ -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

View File

@ -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 ]