unique variable names

This commit is contained in:
Denis Molony 2021-01-03 13:04:24 +10:00
parent bda2e3358a
commit a0d702be73
2 changed files with 161 additions and 114 deletions

View File

@ -20,8 +20,8 @@ public class ApplesoftBasicProgram extends BasicProgram
final Map<Integer, List<Integer>> gotoLines = new TreeMap<> ();
final Map<Integer, List<Integer>> gosubLines = new TreeMap<> ();
final Map<String, List<Integer>> symbolLines = new TreeMap<> ();
final Map<String, List<String>> uniqueSymbols = new TreeMap<> ();
private final Map<String, List<Integer>> symbolLines = new TreeMap<> ();
private final Map<String, List<String>> uniqueSymbols = new TreeMap<> ();
final List<Integer> stringsLine = new ArrayList<> ();
final List<String> stringsText = new ArrayList<> ();
@ -46,10 +46,54 @@ public class ApplesoftBasicProgram extends BasicProgram
sourceLines.add (line);
ptr += line.length;
currentAddress = nextAddress;
for (SubLine subline : line.sublines)
{
for (String symbol : subline.getSymbols ())
checkVar (symbol, line.lineNumber);
for (int targetLine : subline.getGosubLines ())
addXref (line.lineNumber, targetLine, gosubLines);
for (int targetLine : subline.getGotoLines ())
addXref (line.lineNumber, targetLine, gotoLines);
}
}
endPtr = ptr;
}
// ---------------------------------------------------------------------------------//
void checkVar (String var, int lineNumber)
// ---------------------------------------------------------------------------------//
{
List<Integer> lines = symbolLines.get (var);
if (lines == null)
{
lines = new ArrayList<> ();
symbolLines.put (var, lines);
}
if (lines.size () == 0)
lines.add (lineNumber);
else
{
int lastLine = lines.get (lines.size () - 1);
if (lastLine != lineNumber)
lines.add (lineNumber);
}
checkUniqueName (var);
}
// ---------------------------------------------------------------------------------//
private void addXref (int sourceLine, int targetLine, Map<Integer, List<Integer>> map)
// ---------------------------------------------------------------------------------//
{
List<Integer> lines = map.get (targetLine);
if (lines == null)
{
lines = new ArrayList<> ();
map.put (targetLine, lines);
}
lines.add (sourceLine);
}
// ---------------------------------------------------------------------------------//
@Override
public String getText ()
@ -67,9 +111,10 @@ public class ApplesoftBasicProgram extends BasicProgram
StringBuilder fullText = new StringBuilder ();
Stack<String> loopVariables = new Stack<> ();
if (basicPreferences.showHeader)
addHeader (fullText);
int alignPos = 0;
int alignEqualsPos = 0;
StringBuilder text;
int baseOffset = basicPreferences.showTargets ? 12 : 8;
@ -136,7 +181,7 @@ public class ApplesoftBasicProgram extends BasicProgram
// Align assign statements if required
if (basicPreferences.alignAssign)
alignPos = alignEqualsPosition (subline, alignPos);
alignEqualsPos = alignEqualsPosition (subline, alignEqualsPos);
int column = indent * indentSize + baseOffset;
while (text.length () < column)
@ -144,8 +189,7 @@ public class ApplesoftBasicProgram extends BasicProgram
}
// Add the current text, then reset it
int pos = subline.is (ApplesoftConstants.TOKEN_REM) ? 0 : alignPos;
String lineText = subline.getAlignedText (pos);
String lineText = subline.getAlignedText (alignEqualsPos);
if (subline.is (ApplesoftConstants.TOKEN_REM)
&& basicPreferences.deleteExtraRemSpace)
@ -155,7 +199,7 @@ public class ApplesoftBasicProgram extends BasicProgram
&& basicPreferences.deleteExtraDataSpace)
lineText = lineText.replaceFirst ("DATA ", "DATA ");
// Check for a wrappable REM statement
// Check for a wrappable REM/DATA/DIM statement
// (see SEA BATTLE on DISK283.DSK)
int inset = Math.max (text.length (), getIndent (fullText)) + 1;
if (subline.is (ApplesoftConstants.TOKEN_REM)
@ -196,11 +240,15 @@ public class ApplesoftBasicProgram extends BasicProgram
ifIndent = ++indent;
else if (subline.is (ApplesoftConstants.TOKEN_FOR))
{
loopVariables.push (subline.forVariable);
++indent;
String latestLoopVar = loopVariables.size () > 0 ? loopVariables.peek () : "";
if (!subline.forVariable.equals (latestLoopVar)) // don't add repeated loop
{
loopVariables.push (subline.forVariable);
++indent;
}
}
else if (basicPreferences.blankAfterReturn
&& subline.is (ApplesoftConstants.TOKEN_RETURN))
&& subline.is (ApplesoftConstants.TOKEN_RETURN) && subline.isFirst ())
insertBlankLine = true;
}
@ -212,7 +260,7 @@ public class ApplesoftBasicProgram extends BasicProgram
// Reset alignment value if we just left an IF - the indentation will be different now
if (ifIndent > 0)
alignPos = 0;
alignEqualsPos = 0;
}
int ptr = endPtr + 2;
@ -238,7 +286,7 @@ public class ApplesoftBasicProgram extends BasicProgram
int longestVarName = getLongestVarName ();
String format =
longestVarName > 6 ? "%-" + longestVarName + "s %s%n" : "%-6s %s%n";
longestVarName > 6 ? "%-" + longestVarName + "s %s%n" : "%-6s %s%n";
for (String symbol : symbolLines.keySet ())
{
@ -569,7 +617,7 @@ public class ApplesoftBasicProgram extends BasicProgram
private int alignEqualsPosition (SubLine subline, int currentAlignPosition)
// ---------------------------------------------------------------------------------//
{
if (subline.assignEqualPos > 0) // does the line have an equals sign?
if (subline.equalsPosition > 0) // does the line have an equals sign?
{
if (currentAlignPosition == 0)
currentAlignPosition = findHighest (subline); // examine following sublines
@ -585,7 +633,7 @@ public class ApplesoftBasicProgram extends BasicProgram
// ---------------------------------------------------------------------------------//
{
boolean started = false;
int highestAssign = startSubline.assignEqualPos;
int highestAssign = startSubline.equalsPosition;
fast: for (SourceLine line : sourceLines)
{
@ -596,13 +644,13 @@ public class ApplesoftBasicProgram extends BasicProgram
{
// Stop when we come to a line without an equals sign (except for non-split REMs).
// Lines that start with a REM always break.
if (subline.assignEqualPos == 0
if (subline.equalsPosition == 0
// && (splitRem || !subline.is (TOKEN_REM) || subline.isFirst ()))
&& (basicPreferences.splitRem || !subline.isJoinableRem ()))
break fast; // of champions
if (subline.assignEqualPos > highestAssign)
highestAssign = subline.assignEqualPos;
if (subline.equalsPosition > highestAssign)
highestAssign = subline.equalsPosition;
}
else if (subline == startSubline)
started = true;
@ -717,11 +765,39 @@ public class ApplesoftBasicProgram extends BasicProgram
private boolean sameVariable (String v1, String v2)
// ---------------------------------------------------------------------------------//
{
if (v1.equals (v2))
return true;
if (v1.length () >= 2 && v2.length () >= 2 && v1.charAt (0) == v2.charAt (0)
&& v1.charAt (1) == v2.charAt (1))
return true;
return false;
return getUniqueName (v1).equals (getUniqueName (v2));
}
// ---------------------------------------------------------------------------------//
private void checkUniqueName (String symbol)
// ---------------------------------------------------------------------------------//
{
String uniqueName = getUniqueName (symbol);
List<String> usage = uniqueSymbols.get (uniqueName);
if (usage == null)
{
usage = new ArrayList<> ();
uniqueSymbols.put (uniqueName, usage);
}
if (!usage.contains (symbol))
usage.add (symbol);
}
// ---------------------------------------------------------------------------------//
private String getUniqueName (String symbol)
// ---------------------------------------------------------------------------------//
{
int ptr = symbol.length () - 1;
if (symbol.charAt (ptr) == Utility.ASCII_LEFT_BRACKET) // array
ptr--;
if (symbol.charAt (ptr) == Utility.ASCII_DOLLAR // string
|| symbol.charAt (ptr) == Utility.ASCII_PERCENT) // integer
ptr--;
String unique =
(ptr <= 1) ? symbol : symbol.substring (0, 2) + symbol.substring (ptr + 1);
return unique;
}
}

View File

@ -2,7 +2,6 @@ package com.bytezone.diskbrowser.applefile;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.bytezone.diskbrowser.utilities.Utility;
@ -16,13 +15,12 @@ public class SubLine
int length;
String[] nextVariables;
String forVariable = "";
int assignEqualPos; // used for aligning the equals sign
int equalsPosition; // used for aligning the equals sign
byte[] buffer;
private final Map<Integer, List<Integer>> gotoLines;
private final Map<Integer, List<Integer>> gosubLines;
private final Map<String, List<Integer>> symbolLines;
private final Map<String, List<String>> uniqueSymbols;
private final List<Integer> gotoLines = new ArrayList<> ();
private final List<Integer> gosubLines = new ArrayList<> ();
private final List<String> symbols = new ArrayList<> ();
// ---------------------------------------------------------------------------------//
SubLine (SourceLine parent, int startPtr, int length)
@ -33,13 +31,9 @@ public class SubLine
this.length = length;
program = parent.parent;
this.gotoLines = program.gotoLines;
this.gosubLines = program.gosubLines;
this.symbolLines = program.symbolLines;
this.uniqueSymbols = program.uniqueSymbols;
this.buffer = parent.buffer;
byte firstByte = parent.buffer[startPtr];
byte firstByte = buffer[startPtr];
if (Utility.isHighBitSet (firstByte))
doToken (firstByte);
@ -58,7 +52,7 @@ public class SubLine
while (length-- > 0)
{
byte b = parent.buffer[ptr++];
byte b = buffer[ptr++];
if (inQuote && b != Utility.ASCII_QUOTE)
continue;
@ -78,33 +72,38 @@ public class SubLine
}
// ---------------------------------------------------------------------------------//
private void checkVar (String var, byte term)
private void checkVar (String var, byte terminator)
// ---------------------------------------------------------------------------------//
{
if (var.length () == 0)
return;
if (term == Utility.ASCII_LEFT_BRACKET)
if (terminator == Utility.ASCII_LEFT_BRACKET)
var += "(";
if (Utility.isLetter ((byte) var.charAt (0)))
{
List<Integer> lines = symbolLines.get (var);
if (lines == null)
{
lines = new ArrayList<> ();
symbolLines.put (var, lines);
}
if (lines.size () == 0)
lines.add (parent.lineNumber);
else
{
int lastLine = lines.get (lines.size () - 1);
if (lastLine != parent.lineNumber)
lines.add (parent.lineNumber);
}
checkUniqueName (var);
}
if (Utility.isLetter ((byte) var.charAt (0)) && !symbols.contains (var))
symbols.add (var);
}
// ---------------------------------------------------------------------------------//
List<String> getSymbols ()
// ---------------------------------------------------------------------------------//
{
return symbols;
}
// ---------------------------------------------------------------------------------//
List<Integer> getGotoLines ()
// ---------------------------------------------------------------------------------//
{
return gotoLines;
}
// ---------------------------------------------------------------------------------//
List<Integer> getGosubLines ()
// ---------------------------------------------------------------------------------//
{
return gosubLines;
}
// ---------------------------------------------------------------------------------//
@ -115,8 +114,8 @@ public class SubLine
{
case ApplesoftConstants.TOKEN_FOR:
int p = startPtr + 1;
while (parent.buffer[p] != ApplesoftConstants.TOKEN_EQUALS)
forVariable += (char) parent.buffer[p++];
while (buffer[p] != ApplesoftConstants.TOKEN_EQUALS)
forVariable += (char) buffer[p++];
break;
case ApplesoftConstants.TOKEN_NEXT:
@ -124,7 +123,7 @@ public class SubLine
nextVariables = new String[0];
else
{
String varList = new String (parent.buffer, startPtr + 1, length - 2);
String varList = new String (buffer, startPtr + 1, length - 2);
nextVariables = varList.split (",");
}
break;
@ -134,31 +133,31 @@ public class SubLine
break;
case ApplesoftConstants.TOKEN_GOTO:
int targetLine = getLineNumber (parent.buffer, startPtr + 1);
int targetLine = getLineNumber (buffer, startPtr + 1);
addXref (targetLine, gotoLines);
break;
case ApplesoftConstants.TOKEN_GOSUB:
targetLine = getLineNumber (parent.buffer, startPtr + 1);
targetLine = getLineNumber (buffer, startPtr + 1);
addXref (targetLine, gosubLines);
break;
case ApplesoftConstants.TOKEN_ON:
p = startPtr + 1;
int max = startPtr + length - 1;
while (p < max && parent.buffer[p] != ApplesoftConstants.TOKEN_GOTO
&& parent.buffer[p] != ApplesoftConstants.TOKEN_GOSUB)
while (p < max && buffer[p] != ApplesoftConstants.TOKEN_GOTO
&& buffer[p] != ApplesoftConstants.TOKEN_GOSUB)
p++;
switch (parent.buffer[p++])
switch (buffer[p++])
{
case ApplesoftConstants.TOKEN_GOSUB:
for (int destLine : getLineNumbers (parent.buffer, p))
for (int destLine : getLineNumbers (buffer, p))
addXref (destLine, gosubLines);
break;
case ApplesoftConstants.TOKEN_GOTO:
for (int destLine : getLineNumbers (parent.buffer, p))
for (int destLine : getLineNumbers (buffer, p))
addXref (destLine, gotoLines);
break;
@ -170,43 +169,18 @@ public class SubLine
case ApplesoftConstants.TOKEN_ONERR:
if (buffer[startPtr + 1] == ApplesoftConstants.TOKEN_GOTO)
{
targetLine = getLineNumber (parent.buffer, startPtr + 2);
targetLine = getLineNumber (buffer, startPtr + 2);
addXref (targetLine, gotoLines);
}
break;
}
}
// ---------------------------------------------------------------------------------//
private void checkUniqueName (String symbol)
// ---------------------------------------------------------------------------------//
{
int ptr = symbol.length () - 1;
if (symbol.charAt (ptr) == Utility.ASCII_LEFT_BRACKET) // array
ptr--;
if (symbol.charAt (ptr) == Utility.ASCII_DOLLAR
|| symbol.charAt (ptr) == Utility.ASCII_PERCENT)
ptr--;
String unique =
(ptr <= 1) ? symbol : symbol.substring (0, 2) + symbol.substring (ptr + 1);
List<String> usage = uniqueSymbols.get (unique);
if (usage == null)
{
usage = new ArrayList<> ();
uniqueSymbols.put (unique, usage);
}
if (!usage.contains (symbol))
usage.add (symbol);
}
// ---------------------------------------------------------------------------------//
private void doDigit ()
// ---------------------------------------------------------------------------------//
{
int targetLine = getLineNumber (parent.buffer, startPtr);
int targetLine = getLineNumber (buffer, startPtr);
addXref (targetLine, gotoLines);
}
@ -217,6 +191,14 @@ public class SubLine
recordEqualsPosition ();
}
// ---------------------------------------------------------------------------------//
private void addXref (int targetLine, List<Integer> list)
// ---------------------------------------------------------------------------------//
{
if (!list.contains (targetLine))
list.add (targetLine);
}
// ---------------------------------------------------------------------------------//
private List<Integer> getLineNumbers (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------//
@ -259,24 +241,11 @@ public class SubLine
return lineNumber;
}
// ---------------------------------------------------------------------------------//
private void addXref (int targetLine, Map<Integer, List<Integer>> map)
// ---------------------------------------------------------------------------------//
{
List<Integer> lines = map.get (targetLine);
if (lines == null)
{
lines = new ArrayList<> ();
map.put (targetLine, lines);
}
lines.add (parent.lineNumber);
}
// ---------------------------------------------------------------------------------//
boolean isImpliedGoto ()
// ---------------------------------------------------------------------------------//
{
byte b = parent.buffer[startPtr];
byte b = buffer[startPtr];
if (Utility.isHighBitSet (b))
return false;
return (Utility.isDigit (b));
@ -289,10 +258,10 @@ public class SubLine
{
int p = startPtr + 1;
int max = startPtr + length;
while (parent.buffer[p] != ApplesoftConstants.TOKEN_EQUALS && p < max)
while (buffer[p] != ApplesoftConstants.TOKEN_EQUALS && p < max)
p++;
if (buffer[p] == ApplesoftConstants.TOKEN_EQUALS)
assignEqualPos = toString ().indexOf ('='); // use expanded line
equalsPosition = toString ().indexOf ('='); // use expanded line
}
// ---------------------------------------------------------------------------------//
@ -313,7 +282,7 @@ public class SubLine
boolean is (byte token)
// ---------------------------------------------------------------------------------//
{
return parent.buffer[startPtr] == token;
return buffer[startPtr] == token;
}
// ---------------------------------------------------------------------------------//
@ -325,7 +294,7 @@ public class SubLine
while (ptr < max)
{
if (parent.buffer[ptr++] == token)
if (buffer[ptr++] == token)
return true;
}
return false;
@ -403,13 +372,15 @@ public class SubLine
}
// ---------------------------------------------------------------------------------//
public String getAlignedText (int alignPosition)
public String getAlignedText (int alignEqualsPos)
// ---------------------------------------------------------------------------------//
{
StringBuilder line = toStringBuilder ();
StringBuilder line = toStringBuilder (); // get line
while (alignPosition-- > assignEqualPos)
line.insert (assignEqualPos, ' ');
// insert spaces before '=' until it lines up with the other assignment lines
if (!is (ApplesoftConstants.TOKEN_REM))
while (alignEqualsPos-- > equalsPosition)
line.insert (equalsPosition, ' ');
return line.toString ();
}