bastools/api/src/main/java/io/github/applecommander/bastools/api/code/CodeBuilder.java

55 lines
1.9 KiB
Java

package io.github.applecommander.bastools.api.code;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* {@code CodeBuilder} allows dynamic generation of combined BASIC and Assembly code with dynamic
* {@code CodeMark} capability. This allows forward references to unknown address in a (mostly) safe
* manner.
*/
public class CodeBuilder {
private CodeGenerator generatorChain = (os) -> {};
/**
* Generate this set of code beginning at the starting address.
* @return ByteArrayOutputStream which allows {@code ByteArrayOutputStream#writeTo(java.io.OutputStream)}
* and {@code ByteArrayOutputStream#toByteArray()}
*/
public ByteArrayOutputStream generate(int startAddress) throws IOException {
GeneratorState state = new GeneratorState(startAddress);
do {
state.reset();
generatorChain.generate(state);
} while (state.hasMarkMoved());
return state.outputStream();
}
/** Start generating BASIC code. */
public BasicBuilder basic() {
return new BasicBuilder(this);
}
/** Start generating Assembly code. */
public AsmBuilder asm() {
return new AsmBuilder(this);
}
/** Helper method to chain in a {@code CodeGenerator}. */
public CodeBuilder add(CodeGenerator generator) {
generatorChain = generatorChain.andThen(generator);
return this;
}
/** Set a {@code CodeMark}'s value. */
public CodeBuilder set(CodeMark mark) {
return add(state -> {
// A bit twisted, but this allows the GeneratorState and CodeMark to interact without our intervention.
state.update(mark);
});
}
/** Add a {@code byte[]} to this stream. */
public CodeBuilder addBinary(byte[] data) {
return add(state -> {
state.write(data);
});
}
}