mirror of
https://github.com/AppleCommander/bastools.git
synced 2025-01-14 12:33:55 +00:00
Adding an optimization to shorten variable names to 1 or 2 characters.
This allows more useful variable names in the program.
This commit is contained in:
parent
b84896c8cf
commit
9078361a18
@ -4,6 +4,8 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Configuration {
|
||||
@ -11,6 +13,7 @@ public class Configuration {
|
||||
public final int startAddress;
|
||||
public final int maxLineLength;
|
||||
public final PrintStream debugStream;
|
||||
public final Map<String,String >variableReplacements = new HashMap<>();
|
||||
|
||||
private Configuration(Builder b) {
|
||||
this.sourceFile = b.sourceFile;
|
||||
|
@ -38,6 +38,16 @@ public abstract class Directive {
|
||||
this.parameterNames = new TreeSet<>(String::compareToIgnoreCase);
|
||||
this.parameterNames.addAll(Arrays.asList(parameterNames));
|
||||
}
|
||||
|
||||
/** Resolve the given variable name with any variable replacements that should occur. */
|
||||
public String resolve(String originalVariableName) {
|
||||
if (config.variableReplacements.containsKey(originalVariableName)) {
|
||||
String replacementVariableName = config.variableReplacements.get(originalVariableName);
|
||||
config.debugStream.printf("Replacing '%s' with '%s'\n", originalVariableName, replacementVariableName);
|
||||
return replacementVariableName;
|
||||
}
|
||||
return originalVariableName;
|
||||
}
|
||||
|
||||
public Optional<Expression> optionalExpression(String paramName) {
|
||||
return Optional.ofNullable(parameters.get(paramName));
|
||||
|
@ -3,6 +3,7 @@ package io.github.applecommander.bastools.api;
|
||||
import java.util.function.Function;
|
||||
|
||||
import io.github.applecommander.bastools.api.optimizations.ExtractConstantValues;
|
||||
import io.github.applecommander.bastools.api.optimizations.ShortenVariableNames;
|
||||
import io.github.applecommander.bastools.api.optimizations.MergeLines;
|
||||
import io.github.applecommander.bastools.api.optimizations.RemoveEmptyStatements;
|
||||
import io.github.applecommander.bastools.api.optimizations.RemoveRemStatements;
|
||||
@ -15,6 +16,7 @@ import io.github.applecommander.bastools.api.optimizations.Renumber;
|
||||
public enum Optimization {
|
||||
REMOVE_EMPTY_STATEMENTS(RemoveEmptyStatements::new),
|
||||
REMOVE_REM_STATEMENTS(RemoveRemStatements::new),
|
||||
SHORTEN_VARIABLE_NAMES(ShortenVariableNames::new),
|
||||
EXTRACT_CONSTANT_VALUES(ExtractConstantValues::new),
|
||||
MERGE_LINES(MergeLines::new),
|
||||
RENUMBER(Renumber::new);
|
||||
|
@ -42,7 +42,7 @@ public class EmbeddedBinaryDirective extends Directive {
|
||||
|
||||
variableName.ifPresent(var -> {
|
||||
builder.basic()
|
||||
.assign(var, embeddedStart)
|
||||
.assign(resolve(var), embeddedStart)
|
||||
.endStatement();
|
||||
});
|
||||
|
||||
|
@ -67,7 +67,7 @@ public class EmbeddedShapeTable extends Directive {
|
||||
// Setup common code
|
||||
if (poke) basic.POKEW(232, shapeTableStart).endStatement();
|
||||
if (init) basic.ROT(0).endStatement().SCALE(1).endStatement();
|
||||
address.ifPresent(var -> basic.assign(var, shapeTableStart).endStatement());
|
||||
address.ifPresent(var -> basic.assign(resolve(var), shapeTableStart).endStatement());
|
||||
|
||||
// Inject src options
|
||||
assign.ifPresent(expr -> setupVariables(expr, basic, shapeTable));
|
||||
@ -85,7 +85,7 @@ public class EmbeddedShapeTable extends Directive {
|
||||
|
||||
builder.generate(startAddress).writeTo(this.outputStream);
|
||||
}
|
||||
|
||||
|
||||
public void setupVariables(MapExpression expr, BasicBuilder basic, Optional<ShapeTable> shapeTableOptional) {
|
||||
ShapeTable st = shapeTableOptional.orElseThrow(() -> new RuntimeException("ShapeTable source not supplied"));
|
||||
expr.entrySet().forEach(e -> {
|
||||
@ -93,7 +93,7 @@ public class EmbeddedShapeTable extends Directive {
|
||||
.map(SimpleExpression::asString)
|
||||
.orElseThrow(() -> new RuntimeException(
|
||||
String.format("Unexpected format of asignments for variable '%s'", e.getKey())));
|
||||
basic.assign(e.getKey(), st.findPositionByLabel(label)).endStatement();
|
||||
basic.assign(resolve(e.getKey()), st.findPositionByLabel(label)).endStatement();
|
||||
});
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ public class EmbeddedShapeTable extends Directive {
|
||||
ShapeTable st = shapeTableOptional.orElseThrow(() -> new RuntimeException("ShapeTable source not supplied"));
|
||||
for (int i=0; i<st.shapes.size(); i++) {
|
||||
Shape s = st.shapes.get(i);
|
||||
basic.assign(s.getLabel(), i+1);
|
||||
basic.assign(resolve(s.getLabel()), i+1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,68 @@
|
||||
package io.github.applecommander.bastools.api.optimizations;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import io.github.applecommander.bastools.api.Configuration;
|
||||
import io.github.applecommander.bastools.api.Visitors;
|
||||
import io.github.applecommander.bastools.api.model.Program;
|
||||
import io.github.applecommander.bastools.api.model.Statement;
|
||||
import io.github.applecommander.bastools.api.model.Token;
|
||||
import io.github.applecommander.bastools.api.model.Token.Type;
|
||||
import io.github.applecommander.bastools.api.utils.VariableNameGenerator;
|
||||
import io.github.applecommander.bastools.api.visitors.VariableCollectorVisitor;
|
||||
|
||||
/**
|
||||
* Ensure all variable names are 1 or 2 characters long.
|
||||
* This allows the source to use more descriptive variable names, which may
|
||||
* crossover ("PLAYERX" and "PLAYERY" become "PL" as far Applesoft BASIC is
|
||||
* concerned). Somewhat hampers running without this optimization being used,
|
||||
* however.
|
||||
*/
|
||||
public class ShortenVariableNames extends BaseVisitor {
|
||||
private Configuration config;
|
||||
private VariableNameGenerator variableGenerator = new VariableNameGenerator();
|
||||
|
||||
public ShortenVariableNames(Configuration config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Program visit(Program program) {
|
||||
// Find existing variable names so we don't clobber already existing names
|
||||
VariableCollectorVisitor collector = Visitors.variableCollectorVisitor();
|
||||
program.accept(collector);
|
||||
Set<String> existingVariables = collector.getVariableNames();
|
||||
|
||||
// Preassign all variable names
|
||||
for (String originalName : existingVariables) {
|
||||
String newName = originalName;
|
||||
if (newName.replaceAll("[^\\p{Alnum}]","").length() > 2) {
|
||||
String varType = newName.replaceAll("[\\p{Alnum}]","");
|
||||
do {
|
||||
newName = variableGenerator.get().orElseThrow(() -> new RuntimeException("Ran out of variable names to assign"));
|
||||
newName += varType;
|
||||
} while (existingVariables.contains(newName));
|
||||
config.debugStream.printf("Replacing '%s' with '%s'\n", originalName, newName);
|
||||
}
|
||||
config.variableReplacements.put(originalName, newName);
|
||||
}
|
||||
// Continue walking the tree to replace the variables!
|
||||
return super.visit(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement visit(Statement statement) {
|
||||
if (statement.tokens.get(0).type == Type.DIRECTIVE) {
|
||||
return statement;
|
||||
}
|
||||
return super.visit(statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Token visit(Token token) {
|
||||
if (token.type == Type.IDENT) {
|
||||
return Token.ident(token.line, config.variableReplacements.get(token.text));
|
||||
}
|
||||
return super.visit(token);
|
||||
}
|
||||
}
|
@ -79,6 +79,7 @@ public class Main implements Callable<Void> {
|
||||
"Enable specific optimizations.",
|
||||
"* @|green remove-empty-statements|@ - Strip out all '::'-like statements.",
|
||||
"* @|green remove-rem-statements|@ - Remove all REM statements.",
|
||||
"* @|green shorten-variable-names|@ - Ensure all variables are 1 or 2 characters long.",
|
||||
"* @|green extract-constant-values|@ - Assign all constant values first.",
|
||||
"* @|green merge-lines|@ - Merge lines.",
|
||||
"* @|green renumber|@ - Renumber program."
|
||||
|
Loading…
x
Reference in New Issue
Block a user