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

Added support for compiling multiple C-files using a single command line. Closes #382

This commit is contained in:
jespergravgaard 2020-04-11 13:03:36 +02:00
parent f42a921d2b
commit 1c59ad61fd
12 changed files with 144 additions and 79 deletions

View File

@ -8,6 +8,7 @@ import dk.camelot64.kickc.model.statements.StatementSource;
import dk.camelot64.kickc.model.symbols.Procedure; import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.values.SymbolRef; import dk.camelot64.kickc.model.values.SymbolRef;
import dk.camelot64.kickc.parser.CParser; import dk.camelot64.kickc.parser.CParser;
import dk.camelot64.kickc.parser.KickCLexer;
import dk.camelot64.kickc.parser.KickCParser; import dk.camelot64.kickc.parser.KickCParser;
import dk.camelot64.kickc.passes.*; import dk.camelot64.kickc.passes.*;
import org.antlr.v4.runtime.RuleContext; import org.antlr.v4.runtime.RuleContext;
@ -137,11 +138,16 @@ public class Compiler {
program.getImportPaths().add(path); program.getImportPaths().add(path);
} }
public Program compile(String fileName) { public Program compile(List<Path> files) {
if(fileName.endsWith(".kc")) { if(files.size()==0)
fileName = fileName.substring(0, fileName.length() - 3); throw new CompileError("Error! You must supply at least one file to compile!");
final Path primaryFile = files.get(0);
String primaryFileName = primaryFile.toString();
if(primaryFileName.endsWith(".kc")) {
primaryFileName = primaryFileName.substring(0, primaryFileName.length() - 3);
} }
program.setFileName(fileName); program.setPrimaryFileName(primaryFileName);
try { try {
Path currentPath = new File(".").toPath(); Path currentPath = new File(".").toPath();
@ -150,7 +156,13 @@ public class Compiler {
} }
program.setStatementSequence(new StatementSequence()); program.setStatementSequence(new StatementSequence());
CParser cParser = new CParser(program); CParser cParser = new CParser(program);
KickCParser.FileContext cFileContext = cParser.loadAndParseCFile(fileName, currentPath); for(Path file : files) {
final KickCLexer fileLexer = cParser.loadCFile(file.toString(), currentPath);
cParser.addSourceLast(fileLexer);
}
// Parse the files
KickCParser.FileContext cFileContext = cParser.getParser().file();
if(variableBuilderConfig == null) { if(variableBuilderConfig == null) {
VariableBuilderConfig config = new VariableBuilderConfig(); VariableBuilderConfig config = new VariableBuilderConfig();
@ -159,7 +171,7 @@ public class Compiler {
this.variableBuilderConfig = config; this.variableBuilderConfig = config;
} }
if(callingConvention==null) { if(callingConvention == null) {
callingConvention = Procedure.CallingConvention.PHI_CALL; callingConvention = Procedure.CallingConvention.PHI_CALL;
} }
@ -321,14 +333,26 @@ public class Compiler {
optimizations.add(new PassNTypeIdSimplification(program)); optimizations.add(new PassNTypeIdSimplification(program));
optimizations.add(new PassNSizeOfSimplification(program)); optimizations.add(new PassNSizeOfSimplification(program));
optimizations.add(new PassNStatementIndices(program)); optimizations.add(new PassNStatementIndices(program));
optimizations.add(() -> { program.clearVariableReferenceInfos(); return false; }); optimizations.add(() -> {
program.clearVariableReferenceInfos();
return false;
});
optimizations.add(new Pass2UnaryNotSimplification(program)); optimizations.add(new Pass2UnaryNotSimplification(program));
optimizations.add(new Pass2AliasElimination(program)); optimizations.add(new Pass2AliasElimination(program));
optimizations.add(new Pass2IdenticalPhiElimination(program)); optimizations.add(new Pass2IdenticalPhiElimination(program));
optimizations.add(new Pass2DuplicateRValueIdentification(program)); optimizations.add(new Pass2DuplicateRValueIdentification(program));
optimizations.add(() -> { program.clearStatementIndices(); return false; }); optimizations.add(() -> {
optimizations.add(() -> { program.clearVariableReferenceInfos();return false; }); program.clearStatementIndices();
optimizations.add(() -> { program.clearStatementInfos(); return false; }); return false;
});
optimizations.add(() -> {
program.clearVariableReferenceInfos();
return false;
});
optimizations.add(() -> {
program.clearStatementInfos();
return false;
});
optimizations.add(new PassNStatementIndices(program)); optimizations.add(new PassNStatementIndices(program));
optimizations.add(new Pass2ConditionalJumpSimplification(program)); optimizations.add(new Pass2ConditionalJumpSimplification(program));
optimizations.add(new Pass2ConditionalAndOrRewriting(program)); optimizations.add(new Pass2ConditionalAndOrRewriting(program));
@ -352,10 +376,19 @@ public class Compiler {
optimizations.add(new Pass2EliminateUnusedBlocks(program)); optimizations.add(new Pass2EliminateUnusedBlocks(program));
if(enableLoopHeadConstant) { if(enableLoopHeadConstant) {
optimizations.add(new PassNStatementIndices(program)); optimizations.add(new PassNStatementIndices(program));
optimizations.add(() -> { program.clearDominators(); return false; }); optimizations.add(() -> {
optimizations.add(() -> { program.clearLoopSet(); return false; }); program.clearDominators();
return false;
});
optimizations.add(() -> {
program.clearLoopSet();
return false;
});
optimizations.add(new Pass2LoopHeadConstantIdentification(program)); optimizations.add(new Pass2LoopHeadConstantIdentification(program));
optimizations.add(() -> { program.clearStatementIndices(); return false; }); optimizations.add(() -> {
program.clearStatementIndices();
return false;
});
} }
return optimizations; return optimizations;
} }

View File

@ -37,8 +37,8 @@ import java.util.stream.Collectors;
) )
public class KickC implements Callable<Void> { public class KickC implements Callable<Void> {
@CommandLine.Parameters(index = "0", arity = "0..1", description = "The KickC source file to compile.") @CommandLine.Parameters(index = "0", arity = "0..n", description = "The KickC source files to compile.")
private Path kcFile = null; private List<Path> kcFiles = null;
@CommandLine.Option(names = {"-I", "-libdir"}, description = "Path to a library folder, where the compiler looks for included files. This option can be repeated to add multiple library folders.") @CommandLine.Option(names = {"-I", "-libdir"}, description = "Path to a library folder, where the compiler looks for included files. This option can be repeated to add multiple library folders.")
private List<Path> libDir = null; private List<Path> libDir = null;
@ -46,8 +46,8 @@ public class KickC implements Callable<Void> {
@CommandLine.Option(names = {"-F", "-fragmentdir"}, description = "Path to the ASM fragment folder, where the compiler looks for ASM fragments.") @CommandLine.Option(names = {"-F", "-fragmentdir"}, description = "Path to the ASM fragment folder, where the compiler looks for ASM fragments.")
private Path fragmentDir = null; private Path fragmentDir = null;
@CommandLine.Option(names = {"-o", "-output"}, description = "Name of the output assembler file. By default it is the same as the input file with extension .asm") @CommandLine.Option(names = {"-o", "-output"}, description = "Name of the output file. By default it is the same as the first input file with the proper extension.")
private String asmFileName = null; private String outputFileName = null;
@CommandLine.Option(names = {"-odir"}, description = "Path to the output folder, where the compiler places all generated files. By default the folder of the output file is used.") @CommandLine.Option(names = {"-odir"}, description = "Path to the output folder, where the compiler places all generated files. By default the folder of the output file is used.")
private Path outputDir = null; private Path outputDir = null;
@ -238,11 +238,12 @@ public class KickC implements Callable<Void> {
} }
} }
if(kcFile != null) { if(kcFiles != null && !kcFiles.isEmpty()) {
String fileBaseName = getFileBaseName(kcFile); final Path primaryKcFile = kcFiles.get(0);
String primaryFileBaseName = getFileBaseName(primaryKcFile);
Path kcFileDir = kcFile.getParent(); Path kcFileDir = primaryKcFile.getParent();
if(kcFileDir == null) { if(kcFileDir == null) {
kcFileDir = FileSystems.getDefault().getPath("."); kcFileDir = FileSystems.getDefault().getPath(".");
} }
@ -254,8 +255,15 @@ public class KickC implements Callable<Void> {
Files.createDirectory(outputDir); Files.createDirectory(outputDir);
} }
if(asmFileName == null) { String outputFileNameBase;
asmFileName = fileBaseName + ".asm"; if(outputFileName == null) {
outputFileNameBase = primaryFileBaseName;
} else {
final int extensionIdx = outputFileName.lastIndexOf('.');
if(extensionIdx>0)
outputFileNameBase = outputFileName.substring(0, extensionIdx);
else
outputFileNameBase = outputFileName;
} }
if(optimizeNoUplift) { if(optimizeNoUplift) {
@ -317,16 +325,19 @@ public class KickC implements Callable<Void> {
compiler.setCallingConvention(callingConvention); compiler.setCallingConvention(callingConvention);
} }
System.out.println("Compiling " + kcFile); StringBuilder kcFileNames = new StringBuilder();
kcFiles.stream().forEach(path -> kcFileNames.append(path.toString()).append(" "));
System.out.println("Compiling " + kcFileNames);
Program program = null; Program program = null;
try { try {
program = compiler.compile(kcFile.toString()); program = compiler.compile(kcFiles);
} catch(CompileError e) { } catch(CompileError e) {
// Print the error and exit with compile error // Print the error and exit with compile error
System.err.println(e.getMessage()); System.err.println(e.getMessage());
System.exit(COMPILE_ERROR); System.exit(COMPILE_ERROR);
} }
String asmFileName = outputFileNameBase + ".asm";
Path asmPath = outputDir.resolve(asmFileName); Path asmPath = outputDir.resolve(asmFileName);
System.out.println("Writing asm file " + asmPath); System.out.println("Writing asm file " + asmPath);
FileOutputStream asmOutputStream = new FileOutputStream(asmPath.toFile()); FileOutputStream asmOutputStream = new FileOutputStream(asmPath.toFile());
@ -352,9 +363,10 @@ public class KickC implements Callable<Void> {
} }
// Assemble the asm-file if instructed // Assemble the asm-file if instructed
Path prgPath = outputDir.resolve(fileBaseName + ".prg"); String prgFileName = outputFileNameBase +".prg";
Path prgPath = outputDir.resolve(prgFileName);
if(assemble || execute || debug) { if(assemble || execute || debug) {
Path kasmLogPath = outputDir.resolve(fileBaseName + ".klog"); Path kasmLogPath = outputDir.resolve(outputFileNameBase + ".klog");
System.out.println("Assembling to " + prgPath.toString()); System.out.println("Assembling to " + prgPath.toString());
String[] assembleCommand = {asmPath.toString(), "-log", kasmLogPath.toString(), "-o", prgPath.toString(), "-vicesymbols", "-showmem", "-debugdump"}; String[] assembleCommand = {asmPath.toString(), "-log", kasmLogPath.toString(), "-o", prgPath.toString(), "-vicesymbols", "-showmem", "-debugdump"};
if(verbose) { if(verbose) {
@ -385,7 +397,7 @@ public class KickC implements Callable<Void> {
// Debug the prg-file if instructed // Debug the prg-file if instructed
if(debug) { if(debug) {
System.out.println("Debugging " + prgPath); System.out.println("Debugging " + prgPath);
Path viceSymbolsPath = outputDir.resolve(fileBaseName + ".vs"); Path viceSymbolsPath = outputDir.resolve(outputFileNameBase + ".vs");
String debugCommand = "C64Debugger " + "-symbols " + viceSymbolsPath + " -wait 2500" + " -prg " + prgPath.toString(); String debugCommand = "C64Debugger " + "-symbols " + viceSymbolsPath + " -wait 2500" + " -prg " + prgPath.toString();
if(verbose) { if(verbose) {
System.out.println("Debugging command: " + debugCommand); System.out.println("Debugging command: " + debugCommand);
@ -397,7 +409,7 @@ public class KickC implements Callable<Void> {
// Execute the prg-file if instructed // Execute the prg-file if instructed
if(execute) { if(execute) {
System.out.println("Executing " + prgPath); System.out.println("Executing " + prgPath);
Path viceSymbolsPath = outputDir.resolve(fileBaseName + ".vs"); Path viceSymbolsPath = outputDir.resolve(outputFileNameBase + ".vs");
String executeCommand = "x64sc " + "-moncommands " + viceSymbolsPath + " " + prgPath.toString(); String executeCommand = "x64sc " + "-moncommands " + viceSymbolsPath + " " + prgPath.toString();
if(verbose) { if(verbose) {
System.out.println("Executing command: " + executeCommand); System.out.println("Executing command: " + executeCommand);

View File

@ -19,8 +19,8 @@ public class Program {
/** The log containing information about the compilation process. */ /** The log containing information about the compilation process. */
private CompileLog log; private CompileLog log;
/** The name of the file being compiled. PASS 0-5 (STATIC) */ /** The name of the primary file being compiled. PASS 0-5 (STATIC) */
private String fileName; private String primaryFileName;
/** Paths used for importing files. PASS 0 (STATIC) */ /** Paths used for importing files. PASS 0 (STATIC) */
private List<String> importPaths; private List<String> importPaths;
/** Imported files. PASS 0 (STATIC) */ /** Imported files. PASS 0 (STATIC) */
@ -460,12 +460,12 @@ public class Program {
} }
public void setFileName(String fileName) { public void setPrimaryFileName(String primaryFileName) {
this.fileName = fileName; this.primaryFileName = primaryFileName;
} }
public String getFileName() { public String getPrimaryFileName() {
return fileName; return primaryFileName;
} }
/** /**

View File

@ -97,19 +97,6 @@ public class CParser {
return tokenStream; return tokenStream;
} }
/**
* Load initial C-file and start parsing it.
* This may recursively load other C-files (if they are imported)
*
* @param fileName The file name to look for (in the search path)
* @param currentPath The current path (searched before the search path)
* @return The parse result
*/
public KickCParser.FileContext loadAndParseCFile(String fileName, Path currentPath) {
loadCFile(fileName, currentPath);
return this.parser.file();
}
/** /**
* Get the C parser * Get the C parser
* *
@ -149,23 +136,25 @@ public class CParser {
/** /**
* Loads a C-file (if it has not already been loaded). * Loads a C-file (if it has not already been loaded).
*
* The C-file is inserted into the C token stream at the current parse-point - so the parser will parse the entire content of the file before moving on. * The C-file is inserted into the C token stream at the current parse-point - so the parser will parse the entire content of the file before moving on.
* *
* @param fileName The file name of the file * @param fileName The file name of the file
*/ */
public void loadCFile(String fileName, boolean isSystem) { public void includeCFile(String fileName, boolean isSystem) {
final Path currentSourceFolderPath = isSystem ? null : getCurrentSourceFolderPath(); final Path currentSourceFolderPath = isSystem ? null : getCurrentSourceFolderPath();
loadCFile(fileName, currentSourceFolderPath); final KickCLexer lexer = loadCFile(fileName, currentSourceFolderPath);
addSourceFirst(lexer);
} }
/** /**
* Loads a C-file (if it has not already been loaded). * Loads a C-file (if it has not already been loaded).
* The C-file is inserted into the C token stream at the current parse-point - so the parser will parse the entire content of the file before moving on.
* *
* @param fileName The file name of the file * @param fileName The file name of the file
* @param currentPath The path of the current folder (searched before the search path). * @param currentPath The path of the current folder (searched before the search path).
* @return The lexer to be inserted into the source-list using onw of the {@link #addSourceFirst(KickCLexer)} methods.
*/ */
private void loadCFile(String fileName, Path currentPath) { public KickCLexer loadCFile(String fileName, Path currentPath) {
try { try {
if(fileName.startsWith("\"") || fileName.startsWith("<")) { if(fileName.startsWith("\"") || fileName.startsWith("<")) {
fileName = fileName.substring(1, fileName.length() - 1); fileName = fileName.substring(1, fileName.length() - 1);
@ -176,7 +165,7 @@ public class CParser {
File file = SourceLoader.loadFile(fileName, currentPath, program); File file = SourceLoader.loadFile(fileName, currentPath, program);
List<String> imported = program.getImported(); List<String> imported = program.getImported();
if(imported.contains(file.getAbsolutePath())) { if(imported.contains(file.getAbsolutePath())) {
return; return null;
} }
final CharStream fileStream = CharStreams.fromPath(file.toPath().toAbsolutePath()); final CharStream fileStream = CharStreams.fromPath(file.toPath().toAbsolutePath());
imported.add(file.getAbsolutePath()); imported.add(file.getAbsolutePath());
@ -184,21 +173,22 @@ public class CParser {
program.getLog().append("PARSING " + file.getPath().replace("\\", "/")); program.getLog().append("PARSING " + file.getPath().replace("\\", "/"));
program.getLog().append(fileStream.toString()); program.getLog().append(fileStream.toString());
} }
KickCLexer lexer = addSource(fileStream); KickCLexer lexer = makeLexer(fileStream);
CFile cFile = new CFile(file, lexer); CFile cFile = new CFile(file, lexer);
cFiles.put(file.getAbsolutePath(), cFile); cFiles.put(file.getAbsolutePath(), cFile);
return lexer;
} catch(IOException e) { } catch(IOException e) {
throw new CompileError("Error parsing file " + fileName, e); throw new CompileError("Error parsing file " + fileName, e);
} }
} }
/** /**
* Add source code at the start of the token stream being parsed. * Make a lexer for a char stream
* *
* @param charStream The char stream containing the source code to add * @param charStream the char stream
* @return The lexer for reading the source tokens of the added source * @return the lexer
*/ */
public KickCLexer addSource(CharStream charStream) { public KickCLexer makeLexer(CharStream charStream) {
KickCLexer lexer = new KickCLexer(charStream, this); KickCLexer lexer = new KickCLexer(charStream, this);
lexer.addErrorListener(new BaseErrorListener() { lexer.addErrorListener(new BaseErrorListener() {
@Override @Override
@ -212,8 +202,29 @@ public class CParser {
throw new CompileError("Error parsing file " + charStream.getSourceName() + "\n - Line: " + line + "\n - Message: " + msg); throw new CompileError("Error parsing file " + charStream.getSourceName() + "\n - Line: " + line + "\n - Message: " + msg);
} }
}); });
cTokenSource.addSource(lexer);
return lexer; return lexer;
} }
/**
* Add source code at the start of the token stream being parsed.
*
* @param lexer The lexer for reading the source tokens
*/
public void addSourceFirst(KickCLexer lexer) {
if(lexer != null)
cTokenSource.addSourceFirst(lexer);
}
/**
* Add source code at the end of the token stream being parsed.
*
* @param lexer The lexer for reading the source tokens
*/
public void addSourceLast(KickCLexer lexer) {
if(lexer != null)
cTokenSource.addSourceLast(lexer);
}
} }

View File

@ -21,19 +21,28 @@ public class CTokenSource implements TokenSource {
public CTokenSource(TokenSource tokenSource) { public CTokenSource(TokenSource tokenSource) {
this.subSources = new LinkedList<>(); this.subSources = new LinkedList<>();
addSource(tokenSource); addSourceFirst(tokenSource);
} }
/** /**
* Pushes a token source at the current location ). * Pushes a token source at the current location.
* The pushed source will immediately be used for tokens and only when it is exhausted will tokens resume from the current source * The pushed source will immediately be used for tokens and only when it is exhausted will tokens resume from the current source
* *
* @param source The source to push * @param source The source to push
*/ */
public void addSource(TokenSource source) { public void addSourceFirst(TokenSource source) {
subSources.addFirst(source); subSources.addFirst(source);
} }
/**
* Adds a token source at the end of the source.
*
* @param source The source to add
*/
public void addSourceLast(TokenSource source) {
subSources.addLast(source);
}
public TokenSource getCurrentSource() { public TokenSource getCurrentSource() {
return subSources.peekFirst(); return subSources.peekFirst();
} }
@ -49,7 +58,7 @@ public class CTokenSource implements TokenSource {
// And push it back to the front of the stack // And push it back to the front of the stack
final ArrayList<Token> tokens = new ArrayList<>(); final ArrayList<Token> tokens = new ArrayList<>();
tokens.add(token); tokens.add(token);
addSource(new ListTokenSource(tokens)); addSourceFirst(new ListTokenSource(tokens));
return token; return token;
} }

View File

@ -222,8 +222,8 @@ ASM_COMMENT_BLOCK : '/*' .*? '*/' -> channel(2);
// MODE FOR INCLUDE FILES // MODE FOR INCLUDE FILES
mode IMPORT_MODE; mode IMPORT_MODE;
IMPORT_SYSTEMFILE : '<' [a-zA-Z0-9_./\\\-]+ '>' { popMode();cParser.loadCFile(getText(), true); } ; IMPORT_SYSTEMFILE : '<' [a-zA-Z0-9_./\\\-]+ '>' { popMode();cParser.includeCFile(getText(), true); } ;
IMPORT_LOCALFILE : '"' ('\\"' | ~'"')* '"' { popMode(); cParser.loadCFile(getText(), false); } ; IMPORT_LOCALFILE : '"' ('\\"' | ~'"')* '"' { popMode(); cParser.includeCFile(getText(), false); } ;
// White space on hidden channel 1 // White space on hidden channel 1
IMPORT_WS : [ \t\r\n\u00a0]+ -> channel(1); IMPORT_WS : [ \t\r\n\u00a0]+ -> channel(1);
// Comments on hidden channel 2 // Comments on hidden channel 2

View File

@ -301,14 +301,14 @@ public class KickCLexer extends Lexer {
private void IMPORT_SYSTEMFILE_action(RuleContext _localctx, int actionIndex) { private void IMPORT_SYSTEMFILE_action(RuleContext _localctx, int actionIndex) {
switch (actionIndex) { switch (actionIndex) {
case 7: case 7:
popMode();cParser.loadCFile(getText(), true); popMode();cParser.includeCFile(getText(), true);
break; break;
} }
} }
private void IMPORT_LOCALFILE_action(RuleContext _localctx, int actionIndex) { private void IMPORT_LOCALFILE_action(RuleContext _localctx, int actionIndex) {
switch (actionIndex) { switch (actionIndex) {
case 8: case 8:
popMode(); cParser.loadCFile(getText(), false); popMode(); cParser.includeCFile(getText(), false);
break; break;
} }
} }

View File

@ -80,7 +80,6 @@ public class Pass4CodeGeneration {
asm.startChunk(currentScope, null, "File Comments"); asm.startChunk(currentScope, null, "File Comments");
generateComments(asm, program.getFileComments()); generateComments(asm, program.getFileComments());
String outputPrgPath = new File(program.getFileName()).getName() + ".prg";
asm.startChunk(currentScope, null, "Upstart"); asm.startChunk(currentScope, null, "Upstart");
Number programPc = program.getProgramPc(); Number programPc = program.getProgramPc();
if(TargetPlatform.C64BASIC.equals(program.getTargetPlatform())) { if(TargetPlatform.C64BASIC.equals(program.getTargetPlatform())) {
@ -97,7 +96,7 @@ public class Pass4CodeGeneration {
useSegments = true; useSegments = true;
String linkScriptBody = program.getLinkScriptBody(); String linkScriptBody = program.getLinkScriptBody();
if(linkScriptBody != null) { if(linkScriptBody != null) {
String outputFileName = new File(program.getFileName()).getName(); String outputFileName = new File(program.getPrimaryFileName()).getName();
linkScriptBody = linkScriptBody.replace("%O", outputFileName); linkScriptBody = linkScriptBody.replace("%O", outputFileName);
linkScriptBody = linkScriptBody.replace("%_O", outputFileName.toLowerCase()); linkScriptBody = linkScriptBody.replace("%_O", outputFileName.toLowerCase());
linkScriptBody = linkScriptBody.replace("%^O", outputFileName.toUpperCase()); linkScriptBody = linkScriptBody.replace("%^O", outputFileName.toUpperCase());

View File

@ -60,12 +60,12 @@ public class Pass5FixLongBranches extends Pass5AsmOptimization {
} }
// Generate the ASM file // Generate the ASM file
String fileName = getProgram().getFileName(); String outputFileName = getProgram().getPrimaryFileName();
try { try {
//getLog().append("ASM"); //getLog().append("ASM");
//getLog().append(getProgram().getAsm().toString(false, true)); //getLog().append(getProgram().getAsm().toString(false, true));
writeOutputFile(fileName, ".asm", getProgram().getAsm().toString(new AsmProgram.AsmPrintState(false), null)); writeOutputFile(outputFileName, ".asm", getProgram().getAsm().toString(new AsmProgram.AsmPrintState(false), null));
// Copy Resource Files // Copy Resource Files
for(Path asmResourceFile : getProgram().getAsmResourceFiles()) { for(Path asmResourceFile : getProgram().getAsmResourceFiles()) {
@ -78,8 +78,8 @@ public class Pass5FixLongBranches extends Pass5AsmOptimization {
} }
// Compile using KickAssembler - catch the output in a String // Compile using KickAssembler - catch the output in a String
File asmFile = getTmpFile(fileName, ".asm"); File asmFile = getTmpFile(outputFileName, ".asm");
File asmPrgFile = getTmpFile(fileName, ".prg"); File asmPrgFile = getTmpFile(outputFileName, ".prg");
ByteArrayOutputStream kickAssOut = new ByteArrayOutputStream(); ByteArrayOutputStream kickAssOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(kickAssOut)); System.setOut(new PrintStream(kickAssOut));
int asmRes = -1; int asmRes = -1;

View File

@ -270,7 +270,7 @@ public class CPreprocessor implements TokenSource {
addTokenToExpandedBody(macroBodyToken, macroNameToken, expandedBody); addTokenToExpandedBody(macroBodyToken, macroNameToken, expandedBody);
} }
} }
cTokenSource.addSource(new ListTokenSource(expandedBody)); cTokenSource.addSourceFirst(new ListTokenSource(expandedBody));
return true; return true;
} }
return false; return false;

View File

@ -8,9 +8,6 @@ import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CodePointCharStream; import org.antlr.v4.runtime.CodePointCharStream;
import org.junit.Test; import org.junit.Test;
import java.io.IOException;
import java.net.URISyntaxException;
import static junit.framework.TestCase.fail; import static junit.framework.TestCase.fail;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@ -226,7 +223,7 @@ public class TestPreprocessor {
private String parse(String program) { private String parse(String program) {
CodePointCharStream charStream = CharStreams.fromString(program); CodePointCharStream charStream = CharStreams.fromString(program);
CParser cParser = new CParser(null); CParser cParser = new CParser(null);
cParser.addSource(charStream); cParser.addSourceFirst(cParser.makeLexer(charStream));
KickCParser.StmtSeqContext stmtSeqContext = cParser.getParser().stmtSeq(); KickCParser.StmtSeqContext stmtSeqContext = cParser.getParser().stmtSeq();
ProgramPrinter printVisitor = new ProgramPrinter(); ProgramPrinter printVisitor = new ProgramPrinter();
printVisitor.visit(stmtSeqContext); printVisitor.visit(stmtSeqContext);
@ -241,7 +238,6 @@ public class TestPreprocessor {
return out; return out;
} }
@Override @Override
public Object visitStmtSeq(KickCParser.StmtSeqContext ctx) { public Object visitStmtSeq(KickCParser.StmtSeqContext ctx) {
for(KickCParser.StmtContext stmtContext : ctx.stmt()) { for(KickCParser.StmtContext stmtContext : ctx.stmt()) {

View File

@ -21,6 +21,8 @@ import java.net.URISyntaxException;
import java.nio.file.FileAlreadyExistsException; import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import static junit.framework.TestCase.fail; import static junit.framework.TestCase.fail;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@ -4022,7 +4024,10 @@ public class TestPrograms {
if(upliftCombinations != null) { if(upliftCombinations != null) {
compiler.setUpliftCombinations(upliftCombinations); compiler.setUpliftCombinations(upliftCombinations);
} }
Program program = compiler.compile(fileName); final ArrayList<Path> files = new ArrayList<>();
final Path filePath = Paths.get(fileName);
files.add(filePath);
Program program = compiler.compile(files);
compileAsm(fileName, program); compileAsm(fileName, program);