1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-06-24 08:29:29 +00:00

Show variable tables in line list

Multi-line item, with one .eq line per variable definition.  Add
one header line if "clear previous" is set.

Also, limit variable values to 0-255 in the editor.  This is
somewhat arbitrary, but I think a focus on DP is useful.
This commit is contained in:
Andy McFadden 2019-08-27 16:45:37 -07:00
parent 0eeb36f59a
commit c4c67757c0
7 changed files with 106 additions and 6 deletions

View File

@ -224,6 +224,10 @@ namespace SourceGen {
private List<Tag> mSelectionTags = new List<Tag>();
/// <summary>
/// Holds data that helps us position the scroll view at the correct position
/// after changes have been applied.
/// </summary>
private class Top {
// File offset of line.
public int FileOffset { get; private set; }
@ -496,6 +500,9 @@ namespace SourceGen {
case Line.Type.Data:
parts = GenerateDataLine(line.FileOffset, line.SubLineIndex);
break;
case Line.Type.LocalVariableTable:
parts = GenerateLvTableLine(line.FileOffset, line.SubLineIndex);
break;
case Line.Type.Blank:
// Nothing to do.
parts = FormattedParts.CreateBlankLine();
@ -937,6 +944,23 @@ namespace SourceGen {
longComment.BackgroundColor, lines);
}
// Local variable tables come next. Defer rendering.
if (mProject.LvTables.TryGetValue(offset, out LocalVariableTable lvt)) {
int count = lvt.Variables.Count;
// If "clear previous" is set, we output an additional line.
if (lvt.ClearPrevious) {
count++;
}
if (count == 0) {
// Need to show something so the user will know an empty table is here.
count = 1;
}
for (int i = 0; i < count; i++) {
Line line = new Line(offset, 0, Line.Type.LocalVariableTable, i);
lines.Add(line);
}
}
if (attr.IsInstructionStart) {
// Generate reg width directive, if necessary.
if (mProject.CpuDef.HasEmuFlag) {
@ -1270,6 +1294,48 @@ namespace SourceGen {
return parts;
}
private FormattedParts GenerateLvTableLine(int offset, int subLineIndex) {
if (!mProject.LvTables.TryGetValue(offset, out LocalVariableTable lvt)) {
Debug.Assert(false);
return FormattedParts.CreateLongComment("BAD OFFSET +" + offset.ToString("x6") +
" sub=" + subLineIndex);
}
if (lvt.ClearPrevious) {
if (subLineIndex == 0) {
return FormattedParts.CreateLongComment(
Res.Strings.LOCAL_VARIABLE_TABLE_CLEAR);
} else {
// adjust for previously output "clear" line
subLineIndex--;
}
}
if (lvt.Variables.Count == 0) {
// If ClearPrevious is set, we returned the "clear" line for index zero.
// So this is an empty table without a clear. We want to show something so
// the user knows there's dead weight here.
Debug.Assert(subLineIndex == 0 && !lvt.ClearPrevious);
return FormattedParts.CreateLongComment(
Res.Strings.LOCAL_VARIABLE_TABLE_EMPTY);
}
if (subLineIndex >= lvt.Variables.Values.Count) {
return FormattedParts.CreateLongComment("BAD INDEX +" + offset.ToString("x6") +
" sub=" + subLineIndex);
} else {
DefSymbol defSym = lvt.Variables.Values[subLineIndex];
// Use an operand length of 1 so things are shown as concisely as possible.
string addrStr = PseudoOp.FormatNumericOperand(mFormatter, mProject.SymbolTable,
null, defSym.DataDescriptor, defSym.Value, 1,
PseudoOp.FormatNumericOpFlags.None);
string comment = mFormatter.FormatEolComment(defSym.Comment);
return FormattedParts.CreateEquDirective(defSym.Label,
mFormatter.FormatPseudoOp(mPseudoOpNames.EquDirective),
addrStr, comment);
}
}
private FormattedParts[] GenerateStringLines(int offset, string popcode,
List<string> operands) {
FormattedParts[] partsArray = new FormattedParts[operands.Count];

View File

@ -25,6 +25,10 @@ namespace SourceGen {
/// The class is mutable, but may only be modified by the LvTable editor (which makes
/// changes to a work object that moves through the undo/redo buffer) or the
/// deserializer.
///
/// (Referring to these as "local" variables is a bit of a misnomer, since they have
/// global scope from the point where they're defined. The name reflects their intended
/// usage, rather than how the assembler will treat them.)
/// </summary>
public class LocalVariableTable {
/// <summary>
@ -38,10 +42,15 @@ namespace SourceGen {
/// table is encountered.
/// </summary>
/// <remarks>
/// Might be useful to allow addresses (DP ops) and constants (StackRel ops) to be
/// This does not correspond to any output in generated assembly code. We simply stop
/// trying to associate the symbols with instructions. The code will either use a
/// less tightly-scoped value (e.g. project symbol) or output as hex. There is no need
/// to tell the assembler to forget the symbol.
///
/// It might be useful to allow addresses (DP ops) and constants (StackRel ops) to be
/// cleared independently, but I suspect the typical compiled-language scenario will
/// involve StackRel for args and a sliding DP for locals, so generally it makes
/// sense to just clear both.
/// sense to just clear everything.
/// </remarks>
public bool ClearPrevious { get; set; }

View File

@ -1455,6 +1455,11 @@ namespace SourceGen {
EditNote();
}
break;
case LineListGen.Line.Type.LocalVariableTable:
if (CanEditLocalVariableTable()) {
EditLocalVariableTable();
}
break;
case LineListGen.Line.Type.Code:
case LineListGen.Line.Type.Data:
@ -3179,6 +3184,14 @@ namespace SourceGen {
extraStr = "Source: " + sourceStr;
}
break;
case LineListGen.Line.Type.LocalVariableTable:
lineTypeStr = "variable table";
if (mProject.LvTables.TryGetValue(line.FileOffset,
out LocalVariableTable lvt)) {
extraStr = string.Format("{0} entries, clear-previous={1}",
lvt.Variables.Count, lvt.ClearPrevious);
}
break;
default:
lineTypeStr = "???";
break;

View File

@ -84,6 +84,8 @@ limitations under the License.
<system:String x:Key="str_InvalidFormatWordSelCaption">Invalid Selection</system:String>
<system:String x:Key="str_InvalidFormatWordSelNon1" xml:space="preserve">Unable to format as word: selection must be an even number of bytes that have not previously been formatted as multi-byte values.&#x0d;&#x0d;Use Toggle Data Scan (Ctrl+D) to turn off auto-detection of strings and memory fill.</system:String>
<system:String x:Key="str_InvalidFormatWordSelUnevenFmt">Unable to format as word: each selected region must have an even number of bytes ({0} region(s) are selected).</system:String>
<system:String x:Key="str_LocalVariableTableClear">• Clear variables</system:String>
<system:String x:Key="str_LocalVariableTableEmpty">• Empty variable table</system:String>
<system:String x:Key="str_NoFilesAvailable">no files available</system:String>
<system:String x:Key="str_OpenDataDoesntExist">The file doesn't exist.</system:String>
<system:String x:Key="str_OpenDataEmpty">File is empty</system:String>

View File

@ -149,6 +149,10 @@ namespace SourceGen.Res {
(string)Application.Current.FindResource("str_InvalidFormatWordSelNon1");
public static string INVALID_FORMAT_WORD_SEL_UNEVEN_FMT =
(string)Application.Current.FindResource("str_InvalidFormatWordSelUnevenFmt");
public static string LOCAL_VARIABLE_TABLE_CLEAR =
(string)Application.Current.FindResource("str_LocalVariableTableClear");
public static string LOCAL_VARIABLE_TABLE_EMPTY =
(string)Application.Current.FindResource("str_LocalVariableTableEmpty");
public static string NO_FILES_AVAILABLE =
(string)Application.Current.FindResource("str_NoFilesAvailable");
public static string OPEN_DATA_DOESNT_EXIST =

View File

@ -52,6 +52,7 @@ limitations under the License.
<StackPanel Grid.Column="1" Grid.Row="1">
<TextBox Margin="0,1,0,0" Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}"
FontFamily="{StaticResource GeneralMonoFont}"/>
<TextBlock Name="valueRangeLabel" Text="• Value between 0-255" Margin="0,4,0,0"/>
<TextBlock Name="valueNotesLabel" Text="• Decimal, hex ($), or binary (%)" Margin="0,4,0,16"/>
</StackPanel>
@ -59,7 +60,7 @@ limitations under the License.
<StackPanel Name="widthEntry2" Grid.Column="1" Grid.Row="2">
<TextBox Margin="0,1,0,0" Text="{Binding VarWidth, UpdateSourceTrigger=PropertyChanged}"
FontFamily="{StaticResource GeneralMonoFont}"/>
<TextBlock Name="widthNotesLabel" Text="• Decimal, 1-4" Margin="0,4,0,16"/>
<TextBlock Name="widthNotesLabel" Text="• Decimal value, 1-4" Margin="0,4,0,16"/>
</StackPanel>
<TextBlock Grid.Column="0" Grid.Row="3" Text="Comment:" Margin="0,0,8,0"/>

View File

@ -127,6 +127,7 @@ namespace SourceGen.WpfGui {
widthEntry1.Visibility = widthEntry2.Visibility = labelUniqueLabel.Visibility =
Visibility.Collapsed;
labelUniqueLabel.Visibility = Visibility.Collapsed;
valueRangeLabel.Visibility = Visibility.Collapsed;
}
}
@ -178,10 +179,14 @@ namespace SourceGen.WpfGui {
// Value must be blank, meaning "erase any earlier definition", or valid value.
// (Hmm... don't currently have a way to specify "no symbol" in DefSymbol.)
//if (!string.IsNullOrEmpty(valueTextBox.Text)) {
bool valueValid = ParseValue(out int unused1, out int unused2);
bool valueValid = ParseValue(out int value, out int unused2);
//} else {
// valueValid = true;
//}
bool valueRangeValid = true;
if (mIsVariable && valueValid && (value < 0 || value > 255)) {
valueRangeValid = false;
}
bool widthValid = true;
if (widthEntry1.Visibility == Visibility.Visible) {
@ -191,14 +196,14 @@ namespace SourceGen.WpfGui {
}
}
// TODO(maybe): do this the XAML way, with properties and Styles
labelNotesLabel.Foreground = labelValid ? mDefaultLabelColor : Brushes.Red;
labelUniqueLabel.Foreground = projectLabelUniqueLabel.Foreground =
labelUnique ? mDefaultLabelColor : Brushes.Red;
valueNotesLabel.Foreground = valueValid ? mDefaultLabelColor : Brushes.Red;
valueRangeLabel.Foreground = valueRangeValid ? mDefaultLabelColor : Brushes.Red;
widthNotesLabel.Foreground = widthValid ? mDefaultLabelColor : Brushes.Red;
IsValid = labelValid && labelUnique && valueValid && widthValid;
IsValid = labelValid && labelUnique && valueValid && valueRangeValid && widthValid;
}
private bool ParseValue(out int value, out int numBase) {