Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump Lib and Assember to .NET 8, apply heaps of C# 12 improvements #3

Merged
merged 3 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions src/MixAssembler/Assembler.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using MixAssembler.Finding;
Expand Down Expand Up @@ -71,12 +71,10 @@ public static InstructionInstanceBase[] Assemble(string[] sourceLines, out PreIn
if (status.Findings.ContainsErrors)
return null;

symbols = new SymbolCollection();
foreach (SymbolBase symbol in status.Symbols.Where(symbol => symbol is ValueSymbol))
symbols.Add(symbol);
symbols = [.. status.Symbols.Where(symbol => symbol is ValueSymbol)];

status.Findings.Add(new AssemblyInfo("assembly completed successfully", int.MinValue, LineSection.EntireLine, 0, 0));
return list.ToArray();
return [.. list];
}

public static InstructionInstanceBase Assemble(string instructionLine, int locationCounter, out ParsedSourceLine parsedLine, SymbolCollection symbols, out AssemblyFindingCollection findings)
Expand Down
2 changes: 1 addition & 1 deletion src/MixAssembler/AssemblingStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace MixAssembler
{
public class AssemblingStatus
{
public AssemblyFindingCollection Findings { get; } = new();
public AssemblyFindingCollection Findings { get; } = [];

public void ReportError(LineSection lineSection, int causeStartIndex, int causeLength, ValidationError error)
=> Findings.Add(new AssemblyError(LineNumber, lineSection, causeStartIndex, causeLength, error));
Expand Down
9 changes: 4 additions & 5 deletions src/MixAssembler/Finding/AssemblyError.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
using MixLib.Misc;
using MixLib.Misc;

namespace MixAssembler.Finding
{
public class AssemblyError : ValidationFinding
public class AssemblyError(int lineNumber, LineSection lineSection, int causeStartIndex, int causeLength, ValidationError error)
: ValidationFinding(Severity.Error, lineNumber, lineSection, causeStartIndex, causeLength, error)
{
public AssemblyError(int lineNumber, LineSection lineSection, int causeStartIndex, int causeLength, ValidationError error)
: base(Severity.Error, lineNumber, lineSection, causeStartIndex, causeLength, error) { }
}
}
}
25 changes: 8 additions & 17 deletions src/MixAssembler/Finding/AssemblyFinding.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,18 @@
using MixLib.Misc;
using MixLib.Misc;

namespace MixAssembler.Finding
{

public abstract class AssemblyFinding
{
public int Length { get; private set; }
public int LineNumber { get; private set; }
public LineSection LineSection { get; private set; }
public Severity Severity { get; private set; }
public int StartCharIndex { get; private set; }
public abstract class AssemblyFinding(Severity severity, int lineNumber, LineSection section, int startCharIndex, int length)
{
public int Length => length;
public int LineNumber => lineNumber;
public LineSection LineSection => section;
public Severity Severity => severity;
public int StartCharIndex => startCharIndex;

public const int NoNumber = int.MinValue;

protected AssemblyFinding(Severity severity, int lineNumber, LineSection section, int startCharIndex, int length)
{
LineSection = section;
StartCharIndex = startCharIndex;
Length = length;
Severity = severity;
LineNumber = lineNumber;
}

public abstract string Message { get; }
}
}
11 changes: 3 additions & 8 deletions src/MixAssembler/Finding/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
namespace MixAssembler.Finding
{
public class AssemblyInfo : AssemblyFinding
public class AssemblyInfo(string message, int lineNumber, LineSection lineSection, int startCharIndex, int length)
: AssemblyFinding(MixLib.Misc.Severity.Info, lineNumber, lineSection, startCharIndex, length)
{
private readonly string message;

public AssemblyInfo(string message, int lineNumber, LineSection lineSection, int startCharIndex, int length)
: base(MixLib.Misc.Severity.Info, lineNumber, lineSection, startCharIndex, length)
=> this.message = message;

public override string Message
=> this.message;
=> message;
}
}
9 changes: 4 additions & 5 deletions src/MixAssembler/Finding/AssemblyWarning.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
using MixLib.Misc;
using MixLib.Misc;

namespace MixAssembler.Finding
{
public class AssemblyWarning : ValidationFinding
public class AssemblyWarning(int lineNumber, LineSection lineSection, int causeStartIndex, int causeLength, ValidationError error)
: ValidationFinding(Severity.Warning, lineNumber, lineSection, causeStartIndex, causeLength, error)
{
public AssemblyWarning(int lineNumber, LineSection lineSection, int causeStartIndex, int causeLength, ValidationError error)
: base(Severity.Warning, lineNumber, lineSection, causeStartIndex, causeLength, error) { }
}
}
}
13 changes: 5 additions & 8 deletions src/MixAssembler/Finding/ValidationFinding.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
using MixLib.Misc;
using MixLib.Misc;

namespace MixAssembler.Finding
{
public class ValidationFinding : AssemblyFinding
public class ValidationFinding(Severity severity, int lineNumber, LineSection lineSection, int causeStartIndex, int causeLength, ValidationError error)
: AssemblyFinding(severity, lineNumber, lineSection, causeStartIndex, causeLength)
{
public ValidationError Error { get; private set; }

public ValidationFinding(Severity severity, int lineNumber, LineSection lineSection, int causeStartIndex, int causeLength, ValidationError error)
: base(severity, lineNumber, lineSection, causeStartIndex, causeLength)
=> Error = error;
public ValidationError Error => error;

public override string Message
=> Error.CompiledMessage;
=> Error.CompiledMessage;

}
}
37 changes: 14 additions & 23 deletions src/MixAssembler/Instruction/LoaderInstructionParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,19 @@

namespace MixAssembler.Instruction
{
/// <summary>
/// This class contains the parameters that are required to create an instance object of a specific loader instruction "template".
///
/// The (static) ParseAddressField method is to be called during the parsing of the MIXAL source (first assembly pass), to create a parameter object based on the loader instruction's address field.
/// The CreateInstance method should be called during the second assembly pass, to create the actual loader instruction instance.
/// </summary>
public class LoaderInstructionParameters : IInstructionParameters
/// <summary>
/// This class contains the parameters that are required to create an instance object of a specific loader instruction "template".
///
/// The (static) ParseAddressField method is to be called during the parsing of the MIXAL source (first assembly pass), to create a parameter object based on the loader instruction's address field.
/// The CreateInstance method should be called during the second assembly pass, to create the actual loader instruction instance.
/// </summary>
/// <remarks>
/// Constructor for this class.
/// </remarks>
/// <param name="value">The parameter value associated with the instruction. The type of the value depends on the loader instruction it is connected with</param>
/// <param name="textLength">The length (character count) of the value in the source code it was parsed from</param>
public class LoaderInstructionParameters(IValue value, int textLength) : IInstructionParameters
{
private readonly int textLength;
private readonly IValue value;

/// <summary>
/// Constructor for this class.
/// </summary>
/// <param name="value">The parameter value associated with the instruction. The type of the value depends on the loader instruction it is connected with</param>
/// <param name="textLength">The length (character count) of the value in the source code it was parsed from</param>
public LoaderInstructionParameters(IValue value, int textLength)
{
this.value = value;
this.textLength = textLength;
}

/// <summary>
/// Create a loader instruction instance with the parameters contained in this object.
/// </summary>
Expand All @@ -40,11 +31,11 @@ public InstructionInstanceBase CreateInstance(InstructionBase instruction, Assem

if (!value.IsValueDefined(status.LocationCounter))
{
status.ReportParsingError(LineSection.AddressField, 0, this.textLength, "value is not defined");
status.ReportParsingError(LineSection.AddressField, 0, textLength, "value is not defined");
return null;
}

return new LoaderInstruction.Instance(loaderInstruction, this.value.GetSign(status.LocationCounter), this.value.GetMagnitude(status.LocationCounter));
return new LoaderInstruction.Instance(loaderInstruction, value.GetSign(status.LocationCounter), value.GetMagnitude(status.LocationCounter));
}

/// <summary>
Expand Down
63 changes: 23 additions & 40 deletions src/MixAssembler/Instruction/MixInstructionParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,42 +11,25 @@ namespace MixAssembler.Instruction
/// The (static) ParseAddressField method is to be called during the parsing of the MIXAL source (first assembly pass), to create a parameter object based on the MIX instruction's address field.
/// The CreateInstance method should be called during the second assembly pass, to create the actual MIX instruction instance.
/// </summary>
public class MixInstructionParameters : IInstructionParameters
public class MixInstructionParameters(IValue address, int indexPartCharIndex, IValue index, int fieldPartCharIndex, IValue field, int textLength) : IInstructionParameters
{
private readonly IValue address;
private readonly IValue field;
private readonly int fieldPartCharIndex;
private readonly IValue index;
private readonly int indexPartCharIndex;
private readonly int textLength;

private MixInstructionParameters(IValue address, int indexPartCharIndex, IValue index, int fieldPartCharIndex, IValue field, int textLength)
{
this.address = address;
this.index = index;
this.field = field;
this.indexPartCharIndex = indexPartCharIndex;
this.fieldPartCharIndex = fieldPartCharIndex;
this.textLength = textLength;
}

private bool AreValuesDefined(AssemblingStatus status)
{
if (!this.address.IsValueDefined(status.LocationCounter))
if (!address.IsValueDefined(status.LocationCounter))
{
status.ReportParsingError(LineSection.AddressField, 0, this.indexPartCharIndex, "address value undefined");
status.ReportParsingError(LineSection.AddressField, 0, indexPartCharIndex, "address value undefined");
return false;
}

if (!this.index.IsValueDefined(status.LocationCounter))
if (!index.IsValueDefined(status.LocationCounter))
{
status.ReportParsingError(LineSection.AddressField, this.indexPartCharIndex, this.fieldPartCharIndex - this.indexPartCharIndex, "index value undefined");
status.ReportParsingError(LineSection.AddressField, indexPartCharIndex, fieldPartCharIndex - indexPartCharIndex, "index value undefined");
return false;
}

if (!this.address.IsValueDefined(status.LocationCounter))
if (!address.IsValueDefined(status.LocationCounter))
{
status.ReportParsingError(LineSection.AddressField, this.fieldPartCharIndex, this.textLength - this.fieldPartCharIndex, "field value undefined");
status.ReportParsingError(LineSection.AddressField, fieldPartCharIndex, textLength - fieldPartCharIndex, "field value undefined");
return false;
}

Expand All @@ -67,11 +50,11 @@ public InstructionInstanceBase CreateInstance(InstructionBase instruction, Assem
if (!AreValuesDefined(status))
return null;

var addressMagnitude = this.address.GetMagnitude(status.LocationCounter);
var addressMagnitude = address.GetMagnitude(status.LocationCounter);
var word = new Word(MixInstruction.AddressByteCount);
if (addressMagnitude > word.MaxMagnitude)
{
status.ReportError(LineSection.AddressField, 0, this.indexPartCharIndex, new MixAssembler.Finding.ParsingError("address value " + addressMagnitude + " invalid", (int)-word.MaxMagnitude, (int)word.MaxMagnitude));
status.ReportError(LineSection.AddressField, 0, indexPartCharIndex, new Finding.ParsingError("address value " + addressMagnitude + " invalid", (int)-word.MaxMagnitude, (int)word.MaxMagnitude));
return null;
}

Expand All @@ -82,13 +65,13 @@ public InstructionInstanceBase CreateInstance(InstructionBase instruction, Assem

var instructionWord = new FullWord
{
Sign = this.address.GetSign(status.LocationCounter)
Sign = address.GetSign(status.LocationCounter)
};

for (int i = 0; i < word.ByteCount; i++)
instructionWord[i] = word[i];

instructionWord[MixInstruction.IndexByte] = (int)this.index.GetValue(status.LocationCounter);
instructionWord[MixInstruction.IndexByte] = (int)index.GetValue(status.LocationCounter);
instructionWord[MixInstruction.FieldSpecByte] = fieldSpecValue;
instructionWord[MixInstruction.OpcodeByte] = mixInstruction.Opcode;

Expand All @@ -100,15 +83,15 @@ public InstructionInstanceBase CreateInstance(InstructionBase instruction, Assem

private MixByte GetFieldSpecValue(AssemblingStatus status, MixInstruction mixInstruction)
{
var fieldValue = this.field.GetValue(status.LocationCounter);
var fieldValue = field.GetValue(status.LocationCounter);

switch (mixInstruction.MetaFieldSpec.Presence)
{
case MetaFieldSpec.Presences.Forbidden:
if (fieldValue == long.MinValue)
return mixInstruction.FieldSpec.MixByteValue;

status.ReportParsingError(LineSection.AddressField, this.fieldPartCharIndex, this.textLength - this.fieldPartCharIndex, "fieldspec forbidden for this instruction");
status.ReportParsingError(LineSection.AddressField, fieldPartCharIndex, textLength - fieldPartCharIndex, "fieldspec forbidden for this instruction");
return null;

case MetaFieldSpec.Presences.Optional:
Expand All @@ -121,7 +104,7 @@ private MixByte GetFieldSpecValue(AssemblingStatus status, MixInstruction mixIns
if (fieldValue != long.MinValue)
return (int)fieldValue;

status.ReportParsingError(LineSection.AddressField, this.fieldPartCharIndex, this.textLength - this.fieldPartCharIndex, "fieldspec mandatory for this instruction");
status.ReportParsingError(LineSection.AddressField, fieldPartCharIndex, textLength - fieldPartCharIndex, "fieldspec mandatory for this instruction");
return null;
}
return null;
Expand All @@ -130,12 +113,12 @@ private MixByte GetFieldSpecValue(AssemblingStatus status, MixInstruction mixIns
/// <summary>
/// Creates an instance of this class by parsing the address field of a MIX instruction.
/// </summary>
/// <param name="instruction">MixInstruction to parse the address field for. This method will throw an exception if this parameter is of a different instruction type.</param>
/// <param name="addressField">The address field to parse.</param>
/// <param name="status">ParsingStatus object reflecting the current state of the parse process</param>
///
/// <returns></returns>
public static IInstructionParameters ParseAddressField(InstructionBase instruction, string addressField, ParsingStatus status)
{
public static IInstructionParameters ParseAddressField(string addressField, ParsingStatus status)
{
var indexCharIndex = addressField.IndexOf(',');
var sectionCharIndex = addressField.IndexOf('(', Math.Max(indexCharIndex, 0));

Expand All @@ -145,7 +128,7 @@ public static IInstructionParameters ParseAddressField(InstructionBase instructi
if (indexCharIndex == -1)
indexCharIndex = sectionCharIndex;

var address = APartValue.ParseValue(addressField.Substring(0, indexCharIndex), 0, status);
var address = APartValue.ParseValue(addressField[..indexCharIndex], 0, status);
if (address == null)
{
status.ReportParsingError(0, indexCharIndex, "unable to parse address");
Expand Down Expand Up @@ -185,17 +168,17 @@ private void ReportInstanceErrors(AssemblingStatus status, MixInstruction.Instan
{
case InstanceValidationError.Sources.Address:
causeStartIndex = 0;
causeLength = this.indexPartCharIndex;
causeLength = indexPartCharIndex;
break;

case InstanceValidationError.Sources.Index:
causeStartIndex = this.indexPartCharIndex;
causeLength = this.fieldPartCharIndex - this.indexPartCharIndex;
causeStartIndex = indexPartCharIndex;
causeLength = fieldPartCharIndex - indexPartCharIndex;
break;

case InstanceValidationError.Sources.FieldSpec:
causeStartIndex = this.fieldPartCharIndex;
causeLength = this.textLength - this.fieldPartCharIndex;
causeStartIndex = fieldPartCharIndex;
causeLength = textLength - fieldPartCharIndex;
break;
}

Expand Down
Loading