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>> gotoLines = new TreeMap<> ();
final Map<Integer, List<Integer>> gosubLines = new TreeMap<> (); final Map<Integer, List<Integer>> gosubLines = new TreeMap<> ();
final Map<String, List<Integer>> symbolLines = new TreeMap<> (); private final Map<String, List<Integer>> symbolLines = new TreeMap<> ();
final Map<String, List<String>> uniqueSymbols = new TreeMap<> (); private final Map<String, List<String>> uniqueSymbols = new TreeMap<> ();
final List<Integer> stringsLine = new ArrayList<> (); final List<Integer> stringsLine = new ArrayList<> ();
final List<String> stringsText = new ArrayList<> (); final List<String> stringsText = new ArrayList<> ();
@ -46,10 +46,54 @@ public class ApplesoftBasicProgram extends BasicProgram
sourceLines.add (line); sourceLines.add (line);
ptr += line.length; ptr += line.length;
currentAddress = nextAddress; 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; 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 @Override
public String getText () public String getText ()
@ -67,9 +111,10 @@ public class ApplesoftBasicProgram extends BasicProgram
StringBuilder fullText = new StringBuilder (); StringBuilder fullText = new StringBuilder ();
Stack<String> loopVariables = new Stack<> (); Stack<String> loopVariables = new Stack<> ();
if (basicPreferences.showHeader) if (basicPreferences.showHeader)
addHeader (fullText); addHeader (fullText);
int alignPos = 0; int alignEqualsPos = 0;
StringBuilder text; StringBuilder text;
int baseOffset = basicPreferences.showTargets ? 12 : 8; int baseOffset = basicPreferences.showTargets ? 12 : 8;
@ -136,7 +181,7 @@ public class ApplesoftBasicProgram extends BasicProgram
// Align assign statements if required // Align assign statements if required
if (basicPreferences.alignAssign) if (basicPreferences.alignAssign)
alignPos = alignEqualsPosition (subline, alignPos); alignEqualsPos = alignEqualsPosition (subline, alignEqualsPos);
int column = indent * indentSize + baseOffset; int column = indent * indentSize + baseOffset;
while (text.length () < column) while (text.length () < column)
@ -144,8 +189,7 @@ public class ApplesoftBasicProgram extends BasicProgram
} }
// Add the current text, then reset it // Add the current text, then reset it
int pos = subline.is (ApplesoftConstants.TOKEN_REM) ? 0 : alignPos; String lineText = subline.getAlignedText (alignEqualsPos);
String lineText = subline.getAlignedText (pos);
if (subline.is (ApplesoftConstants.TOKEN_REM) if (subline.is (ApplesoftConstants.TOKEN_REM)
&& basicPreferences.deleteExtraRemSpace) && basicPreferences.deleteExtraRemSpace)
@ -155,7 +199,7 @@ public class ApplesoftBasicProgram extends BasicProgram
&& basicPreferences.deleteExtraDataSpace) && basicPreferences.deleteExtraDataSpace)
lineText = lineText.replaceFirst ("DATA ", "DATA "); 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) // (see SEA BATTLE on DISK283.DSK)
int inset = Math.max (text.length (), getIndent (fullText)) + 1; int inset = Math.max (text.length (), getIndent (fullText)) + 1;
if (subline.is (ApplesoftConstants.TOKEN_REM) if (subline.is (ApplesoftConstants.TOKEN_REM)
@ -196,11 +240,15 @@ public class ApplesoftBasicProgram extends BasicProgram
ifIndent = ++indent; ifIndent = ++indent;
else if (subline.is (ApplesoftConstants.TOKEN_FOR)) else if (subline.is (ApplesoftConstants.TOKEN_FOR))
{ {
loopVariables.push (subline.forVariable); String latestLoopVar = loopVariables.size () > 0 ? loopVariables.peek () : "";
++indent; if (!subline.forVariable.equals (latestLoopVar)) // don't add repeated loop
{
loopVariables.push (subline.forVariable);
++indent;
}
} }
else if (basicPreferences.blankAfterReturn else if (basicPreferences.blankAfterReturn
&& subline.is (ApplesoftConstants.TOKEN_RETURN)) && subline.is (ApplesoftConstants.TOKEN_RETURN) && subline.isFirst ())
insertBlankLine = true; 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 // Reset alignment value if we just left an IF - the indentation will be different now
if (ifIndent > 0) if (ifIndent > 0)
alignPos = 0; alignEqualsPos = 0;
} }
int ptr = endPtr + 2; int ptr = endPtr + 2;
@ -238,7 +286,7 @@ public class ApplesoftBasicProgram extends BasicProgram
int longestVarName = getLongestVarName (); int longestVarName = getLongestVarName ();
String format = 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 ()) for (String symbol : symbolLines.keySet ())
{ {
@ -569,7 +617,7 @@ public class ApplesoftBasicProgram extends BasicProgram
private int alignEqualsPosition (SubLine subline, int currentAlignPosition) 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) if (currentAlignPosition == 0)
currentAlignPosition = findHighest (subline); // examine following sublines currentAlignPosition = findHighest (subline); // examine following sublines
@ -585,7 +633,7 @@ public class ApplesoftBasicProgram extends BasicProgram
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
boolean started = false; boolean started = false;
int highestAssign = startSubline.assignEqualPos; int highestAssign = startSubline.equalsPosition;
fast: for (SourceLine line : sourceLines) 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). // Stop when we come to a line without an equals sign (except for non-split REMs).
// Lines that start with a REM always break. // Lines that start with a REM always break.
if (subline.assignEqualPos == 0 if (subline.equalsPosition == 0
// && (splitRem || !subline.is (TOKEN_REM) || subline.isFirst ())) // && (splitRem || !subline.is (TOKEN_REM) || subline.isFirst ()))
&& (basicPreferences.splitRem || !subline.isJoinableRem ())) && (basicPreferences.splitRem || !subline.isJoinableRem ()))
break fast; // of champions break fast; // of champions
if (subline.assignEqualPos > highestAssign) if (subline.equalsPosition > highestAssign)
highestAssign = subline.assignEqualPos; highestAssign = subline.equalsPosition;
} }
else if (subline == startSubline) else if (subline == startSubline)
started = true; started = true;
@ -717,11 +765,39 @@ public class ApplesoftBasicProgram extends BasicProgram
private boolean sameVariable (String v1, String v2) private boolean sameVariable (String v1, String v2)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
if (v1.equals (v2)) return getUniqueName (v1).equals (getUniqueName (v2));
return true; }
if (v1.length () >= 2 && v2.length () >= 2 && v1.charAt (0) == v2.charAt (0)
&& v1.charAt (1) == v2.charAt (1)) // ---------------------------------------------------------------------------------//
return true; private void checkUniqueName (String symbol)
return false; // ---------------------------------------------------------------------------------//
{
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.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import com.bytezone.diskbrowser.utilities.Utility; import com.bytezone.diskbrowser.utilities.Utility;
@ -16,13 +15,12 @@ public class SubLine
int length; int length;
String[] nextVariables; String[] nextVariables;
String forVariable = ""; String forVariable = "";
int assignEqualPos; // used for aligning the equals sign int equalsPosition; // used for aligning the equals sign
byte[] buffer; byte[] buffer;
private final Map<Integer, List<Integer>> gotoLines; private final List<Integer> gotoLines = new ArrayList<> ();
private final Map<Integer, List<Integer>> gosubLines; private final List<Integer> gosubLines = new ArrayList<> ();
private final Map<String, List<Integer>> symbolLines; private final List<String> symbols = new ArrayList<> ();
private final Map<String, List<String>> uniqueSymbols;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
SubLine (SourceLine parent, int startPtr, int length) SubLine (SourceLine parent, int startPtr, int length)
@ -33,13 +31,9 @@ public class SubLine
this.length = length; this.length = length;
program = parent.parent; program = parent.parent;
this.gotoLines = program.gotoLines;
this.gosubLines = program.gosubLines;
this.symbolLines = program.symbolLines;
this.uniqueSymbols = program.uniqueSymbols;
this.buffer = parent.buffer; this.buffer = parent.buffer;
byte firstByte = parent.buffer[startPtr]; byte firstByte = buffer[startPtr];
if (Utility.isHighBitSet (firstByte)) if (Utility.isHighBitSet (firstByte))
doToken (firstByte); doToken (firstByte);
@ -58,7 +52,7 @@ public class SubLine
while (length-- > 0) while (length-- > 0)
{ {
byte b = parent.buffer[ptr++]; byte b = buffer[ptr++];
if (inQuote && b != Utility.ASCII_QUOTE) if (inQuote && b != Utility.ASCII_QUOTE)
continue; 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) if (var.length () == 0)
return; return;
if (term == Utility.ASCII_LEFT_BRACKET) if (terminator == Utility.ASCII_LEFT_BRACKET)
var += "("; var += "(";
if (Utility.isLetter ((byte) var.charAt (0))) if (Utility.isLetter ((byte) var.charAt (0)) && !symbols.contains (var))
{ symbols.add (var);
List<Integer> lines = symbolLines.get (var); }
if (lines == null)
{ // ---------------------------------------------------------------------------------//
lines = new ArrayList<> (); List<String> getSymbols ()
symbolLines.put (var, lines); // ---------------------------------------------------------------------------------//
} {
if (lines.size () == 0) return symbols;
lines.add (parent.lineNumber); }
else
{ // ---------------------------------------------------------------------------------//
int lastLine = lines.get (lines.size () - 1); List<Integer> getGotoLines ()
if (lastLine != parent.lineNumber) // ---------------------------------------------------------------------------------//
lines.add (parent.lineNumber); {
} return gotoLines;
checkUniqueName (var); }
}
// ---------------------------------------------------------------------------------//
List<Integer> getGosubLines ()
// ---------------------------------------------------------------------------------//
{
return gosubLines;
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -115,8 +114,8 @@ public class SubLine
{ {
case ApplesoftConstants.TOKEN_FOR: case ApplesoftConstants.TOKEN_FOR:
int p = startPtr + 1; int p = startPtr + 1;
while (parent.buffer[p] != ApplesoftConstants.TOKEN_EQUALS) while (buffer[p] != ApplesoftConstants.TOKEN_EQUALS)
forVariable += (char) parent.buffer[p++]; forVariable += (char) buffer[p++];
break; break;
case ApplesoftConstants.TOKEN_NEXT: case ApplesoftConstants.TOKEN_NEXT:
@ -124,7 +123,7 @@ public class SubLine
nextVariables = new String[0]; nextVariables = new String[0];
else else
{ {
String varList = new String (parent.buffer, startPtr + 1, length - 2); String varList = new String (buffer, startPtr + 1, length - 2);
nextVariables = varList.split (","); nextVariables = varList.split (",");
} }
break; break;
@ -134,31 +133,31 @@ public class SubLine
break; break;
case ApplesoftConstants.TOKEN_GOTO: case ApplesoftConstants.TOKEN_GOTO:
int targetLine = getLineNumber (parent.buffer, startPtr + 1); int targetLine = getLineNumber (buffer, startPtr + 1);
addXref (targetLine, gotoLines); addXref (targetLine, gotoLines);
break; break;
case ApplesoftConstants.TOKEN_GOSUB: case ApplesoftConstants.TOKEN_GOSUB:
targetLine = getLineNumber (parent.buffer, startPtr + 1); targetLine = getLineNumber (buffer, startPtr + 1);
addXref (targetLine, gosubLines); addXref (targetLine, gosubLines);
break; break;
case ApplesoftConstants.TOKEN_ON: case ApplesoftConstants.TOKEN_ON:
p = startPtr + 1; p = startPtr + 1;
int max = startPtr + length - 1; int max = startPtr + length - 1;
while (p < max && parent.buffer[p] != ApplesoftConstants.TOKEN_GOTO while (p < max && buffer[p] != ApplesoftConstants.TOKEN_GOTO
&& parent.buffer[p] != ApplesoftConstants.TOKEN_GOSUB) && buffer[p] != ApplesoftConstants.TOKEN_GOSUB)
p++; p++;
switch (parent.buffer[p++]) switch (buffer[p++])
{ {
case ApplesoftConstants.TOKEN_GOSUB: case ApplesoftConstants.TOKEN_GOSUB:
for (int destLine : getLineNumbers (parent.buffer, p)) for (int destLine : getLineNumbers (buffer, p))
addXref (destLine, gosubLines); addXref (destLine, gosubLines);
break; break;
case ApplesoftConstants.TOKEN_GOTO: case ApplesoftConstants.TOKEN_GOTO:
for (int destLine : getLineNumbers (parent.buffer, p)) for (int destLine : getLineNumbers (buffer, p))
addXref (destLine, gotoLines); addXref (destLine, gotoLines);
break; break;
@ -170,43 +169,18 @@ public class SubLine
case ApplesoftConstants.TOKEN_ONERR: case ApplesoftConstants.TOKEN_ONERR:
if (buffer[startPtr + 1] == ApplesoftConstants.TOKEN_GOTO) if (buffer[startPtr + 1] == ApplesoftConstants.TOKEN_GOTO)
{ {
targetLine = getLineNumber (parent.buffer, startPtr + 2); targetLine = getLineNumber (buffer, startPtr + 2);
addXref (targetLine, gotoLines); addXref (targetLine, gotoLines);
} }
break; 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 () private void doDigit ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
int targetLine = getLineNumber (parent.buffer, startPtr); int targetLine = getLineNumber (buffer, startPtr);
addXref (targetLine, gotoLines); addXref (targetLine, gotoLines);
} }
@ -217,6 +191,14 @@ public class SubLine
recordEqualsPosition (); recordEqualsPosition ();
} }
// ---------------------------------------------------------------------------------//
private void addXref (int targetLine, List<Integer> list)
// ---------------------------------------------------------------------------------//
{
if (!list.contains (targetLine))
list.add (targetLine);
}
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
private List<Integer> getLineNumbers (byte[] buffer, int ptr) private List<Integer> getLineNumbers (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -259,24 +241,11 @@ public class SubLine
return lineNumber; 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 () boolean isImpliedGoto ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
byte b = parent.buffer[startPtr]; byte b = buffer[startPtr];
if (Utility.isHighBitSet (b)) if (Utility.isHighBitSet (b))
return false; return false;
return (Utility.isDigit (b)); return (Utility.isDigit (b));
@ -289,10 +258,10 @@ public class SubLine
{ {
int p = startPtr + 1; int p = startPtr + 1;
int max = startPtr + length; int max = startPtr + length;
while (parent.buffer[p] != ApplesoftConstants.TOKEN_EQUALS && p < max) while (buffer[p] != ApplesoftConstants.TOKEN_EQUALS && p < max)
p++; p++;
if (buffer[p] == ApplesoftConstants.TOKEN_EQUALS) 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) boolean is (byte token)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
return parent.buffer[startPtr] == token; return buffer[startPtr] == token;
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -325,7 +294,7 @@ public class SubLine
while (ptr < max) while (ptr < max)
{ {
if (parent.buffer[ptr++] == token) if (buffer[ptr++] == token)
return true; return true;
} }
return false; 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) // insert spaces before '=' until it lines up with the other assignment lines
line.insert (assignEqualPos, ' '); if (!is (ApplesoftConstants.TOKEN_REM))
while (alignEqualsPos-- > equalsPosition)
line.insert (equalsPosition, ' ');
return line.toString (); return line.toString ();
} }