Skip to content

Commit af40042

Browse files
committed
Add support for generic assembler to allow derived specialized class
1 parent 537a124 commit af40042

9 files changed

Lines changed: 986 additions & 944 deletions

src/Asm6502.CodeGen/GeneratorApp.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,7 @@ private void GenerateAssemblerFactoryGeneric(string className, string fileName,
836836

837837
writer.WriteLine("namespace Asm6502;");
838838
writer.WriteLine();
839-
writer.WriteLine($"partial class {className}Assembler");
839+
writer.WriteLine($"partial class {className}Assembler<TAsm>");
840840
writer.OpenBraceBlock();
841841

842842
var mnemonicToSignatureToOpcodes = new Dictionary<string, Dictionary<string, OpcodeSignature>>();
@@ -1004,7 +1004,7 @@ private void GenerateAssemblerFactoryGeneric(string className, string fileName,
10041004
{
10051005
writer.WriteLine("[Obsolete(\"This instruction is unstable and may not behave as expected.\", false)]");
10061006
}
1007-
writer.WriteLine($"public {className}Assembler {signature}");
1007+
writer.WriteLine($"public TAsm {signature}");
10081008
writer.Indent();
10091009

10101010
writer.Write($"=> AddInstruction({className}InstructionFactory.{opcodeSignature.Name}(");

src/Asm6502/Mos6502Assembler.gen.cs

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,27 @@ namespace Asm6502;
1111
/// <summary>
1212
/// Represents a 6502 assembler for generating machine code and managing labels.
1313
/// </summary>
14-
public partial class Mos6502Assembler : Mos6502AssemblerBase<Mos6502Assembler>
14+
public partial class Mos6502Assembler : Mos6502Assembler<Mos6502Assembler>
1515
{
1616
/// <summary>
1717
/// Initializes a new instance of the <see cref="Mos6502Assembler"/> class.
1818
/// </summary>
1919
/// <param name="baseAddress">The base address for code generation.</param>
20-
public Mos6502Assembler(ushort baseAddress = 0xC000) : base(baseAddress)
20+
public Mos6502Assembler(ushort baseAddress = 0xC000) : base(baseAddress)
21+
{
22+
}
23+
}
24+
25+
/// <summary>
26+
/// Represents a 6502 assembler base class for generating machine code and managing labels.
27+
/// </summary>
28+
public abstract partial class Mos6502Assembler<TAsm> : Mos6502AssemblerBase<TAsm> where TAsm : Mos6502Assembler<TAsm>
29+
{
30+
/// <summary>
31+
/// Initializes a new instance of the <see cref="Mos6502Assembler"/> class.
32+
/// </summary>
33+
/// <param name="baseAddress">The base address for code generation.</param>
34+
protected Mos6502Assembler(ushort baseAddress = 0xC000) : base(baseAddress)
2135
{
2236
}
2337

@@ -28,7 +42,7 @@ public Mos6502Assembler(ushort baseAddress = 0xC000) : base(baseAddress)
2842
/// <param name="debugFilePath">The file path for debugging information (optional).</param>
2943
/// <param name="debugLineNumber">The line number for debugging information (optional).</param>
3044
/// <returns>The current assembler instance.</returns>
31-
public Mos6502Assembler AddInstruction(Mos6502Instruction instruction, [CallerFilePath] string debugFilePath = "", [CallerLineNumber] int debugLineNumber = 0)
45+
public TAsm AddInstruction(Mos6502Instruction instruction, [CallerFilePath] string debugFilePath = "", [CallerLineNumber] int debugLineNumber = 0)
3246
{
3347
if (!instruction.IsValid) throw new ArgumentException("Invalid instruction", nameof(instruction));
3448

@@ -52,7 +66,7 @@ public Mos6502Assembler AddInstruction(Mos6502Instruction instruction, [CallerFi
5266
debugMap.LogDebugLineInfo(debugLineInfo);
5367
}
5468

55-
return this;
69+
return (TAsm)this;
5670
}
5771

5872
/// <summary>
@@ -63,7 +77,7 @@ public Mos6502Assembler AddInstruction(Mos6502Instruction instruction, [CallerFi
6377
/// <param name="debugFilePath">The file path for debugging information (optional).</param>
6478
/// <param name="debugLineNumber">The line number for debugging information (optional).</param>
6579
/// <returns>The current assembler instance.</returns>
66-
public Mos6502Assembler AddInstruction(Mos6502Instruction instruction, Mos6502Expression expression, [CallerFilePath] string debugFilePath = "", [CallerLineNumber] int debugLineNumber = 0)
80+
public TAsm AddInstruction(Mos6502Instruction instruction, Mos6502Expression expression, [CallerFilePath] string debugFilePath = "", [CallerLineNumber] int debugLineNumber = 0)
6781
{
6882
var currentAddress = CurrentAddress;
6983
var bufferOffset = SizeInBytes;
@@ -73,20 +87,34 @@ public Mos6502Assembler AddInstruction(Mos6502Instruction instruction, Mos6502Ex
7387

7488
Patches.Add(new(currentAddress, (ushort)(bufferOffset + 1), instruction.AddressingMode, expression));
7589

76-
return this;
90+
return (TAsm)this;
7791
}
7892
}
7993

8094
/// <summary>
81-
/// Represents a 6502 assembler for generating machine code and managing labels.
95+
/// Represents a 6510 assembler for generating machine code and managing labels.
96+
/// </summary>
97+
public partial class Mos6510Assembler : Mos6510Assembler<Mos6510Assembler>
98+
{
99+
/// <summary>
100+
/// Initializes a new instance of the <see cref="Mos6510Assembler"/> class.
101+
/// </summary>
102+
/// <param name="baseAddress">The base address for code generation.</param>
103+
public Mos6510Assembler(ushort baseAddress = 0xC000) : base(baseAddress)
104+
{
105+
}
106+
}
107+
108+
/// <summary>
109+
/// Represents a 6510 assembler base class for generating machine code and managing labels.
82110
/// </summary>
83-
public partial class Mos6510Assembler : Mos6502AssemblerBase<Mos6510Assembler>
111+
public abstract partial class Mos6510Assembler<TAsm> : Mos6502AssemblerBase<TAsm> where TAsm : Mos6510Assembler<TAsm>
84112
{
85113
/// <summary>
86114
/// Initializes a new instance of the <see cref="Mos6510Assembler"/> class.
87115
/// </summary>
88116
/// <param name="baseAddress">The base address for code generation.</param>
89-
public Mos6510Assembler(ushort baseAddress = 0xC000) : base(baseAddress)
117+
protected Mos6510Assembler(ushort baseAddress = 0xC000) : base(baseAddress)
90118
{
91119
}
92120

@@ -97,7 +125,7 @@ public Mos6510Assembler(ushort baseAddress = 0xC000) : base(baseAddress)
97125
/// <param name="debugFilePath">The file path for debugging information (optional).</param>
98126
/// <param name="debugLineNumber">The line number for debugging information (optional).</param>
99127
/// <returns>The current assembler instance.</returns>
100-
public Mos6510Assembler AddInstruction(Mos6510Instruction instruction, [CallerFilePath] string debugFilePath = "", [CallerLineNumber] int debugLineNumber = 0)
128+
public TAsm AddInstruction(Mos6510Instruction instruction, [CallerFilePath] string debugFilePath = "", [CallerLineNumber] int debugLineNumber = 0)
101129
{
102130
if (!instruction.IsValid) throw new ArgumentException("Invalid instruction", nameof(instruction));
103131

@@ -121,7 +149,7 @@ public Mos6510Assembler AddInstruction(Mos6510Instruction instruction, [CallerFi
121149
debugMap.LogDebugLineInfo(debugLineInfo);
122150
}
123151

124-
return this;
152+
return (TAsm)this;
125153
}
126154

127155
/// <summary>
@@ -132,7 +160,7 @@ public Mos6510Assembler AddInstruction(Mos6510Instruction instruction, [CallerFi
132160
/// <param name="debugFilePath">The file path for debugging information (optional).</param>
133161
/// <param name="debugLineNumber">The line number for debugging information (optional).</param>
134162
/// <returns>The current assembler instance.</returns>
135-
public Mos6510Assembler AddInstruction(Mos6510Instruction instruction, Mos6502Expression expression, [CallerFilePath] string debugFilePath = "", [CallerLineNumber] int debugLineNumber = 0)
163+
public TAsm AddInstruction(Mos6510Instruction instruction, Mos6502Expression expression, [CallerFilePath] string debugFilePath = "", [CallerLineNumber] int debugLineNumber = 0)
136164
{
137165
var currentAddress = CurrentAddress;
138166
var bufferOffset = SizeInBytes;
@@ -142,6 +170,6 @@ public Mos6510Assembler AddInstruction(Mos6510Instruction instruction, Mos6502Ex
142170

143171
Patches.Add(new(currentAddress, (ushort)(bufferOffset + 1), instruction.AddressingMode, expression));
144172

145-
return this;
173+
return (TAsm)this;
146174
}
147175
}

src/Asm6502/Mos6502Assembler.gen.tt

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,29 @@ namespace Asm6502;
1919
<# foreach(var proc in procs) { #>
2020

2121
/// <summary>
22-
/// Represents a 6502 assembler for generating machine code and managing labels.
22+
/// Represents a <#= proc.Substring(3) #> assembler for generating machine code and managing labels.
2323
/// </summary>
24-
public partial class <#= proc #>Assembler : Mos6502AssemblerBase<<#= proc #>Assembler>
24+
public partial class <#= proc #>Assembler : <#= proc #>Assembler<<#= proc #>Assembler>
2525
{
2626
/// <summary>
2727
/// Initializes a new instance of the <see cref="<#= proc #>Assembler"/> class.
2828
/// </summary>
2929
/// <param name="baseAddress">The base address for code generation.</param>
30-
public <#= proc #>Assembler(ushort baseAddress = 0xC000) : base(baseAddress)
30+
public <#= proc #>Assembler(ushort baseAddress = 0xC000) : base(baseAddress)
31+
{
32+
}
33+
}
34+
35+
/// <summary>
36+
/// Represents a <#= proc.Substring(3) #> assembler base class for generating machine code and managing labels.
37+
/// </summary>
38+
public abstract partial class <#= proc #>Assembler<TAsm> : Mos6502AssemblerBase<TAsm> where TAsm : <#= proc #>Assembler<TAsm>
39+
{
40+
/// <summary>
41+
/// Initializes a new instance of the <see cref="<#= proc #>Assembler"/> class.
42+
/// </summary>
43+
/// <param name="baseAddress">The base address for code generation.</param>
44+
protected <#= proc #>Assembler(ushort baseAddress = 0xC000) : base(baseAddress)
3145
{
3246
}
3347

@@ -38,7 +52,7 @@ public partial class <#= proc #>Assembler : Mos6502AssemblerBase<<#= proc #>Asse
3852
/// <param name="debugFilePath">The file path for debugging information (optional).</param>
3953
/// <param name="debugLineNumber">The line number for debugging information (optional).</param>
4054
/// <returns>The current assembler instance.</returns>
41-
public <#= proc #>Assembler AddInstruction(<#= proc #>Instruction instruction, [CallerFilePath] string debugFilePath = "", [CallerLineNumber] int debugLineNumber = 0)
55+
public TAsm AddInstruction(<#= proc #>Instruction instruction, [CallerFilePath] string debugFilePath = "", [CallerLineNumber] int debugLineNumber = 0)
4256
{
4357
if (!instruction.IsValid) throw new ArgumentException("Invalid instruction", nameof(instruction));
4458

@@ -62,7 +76,7 @@ public partial class <#= proc #>Assembler : Mos6502AssemblerBase<<#= proc #>Asse
6276
debugMap.LogDebugLineInfo(debugLineInfo);
6377
}
6478

65-
return this;
79+
return (TAsm)this;
6680
}
6781

6882
/// <summary>
@@ -73,7 +87,7 @@ public partial class <#= proc #>Assembler : Mos6502AssemblerBase<<#= proc #>Asse
7387
/// <param name="debugFilePath">The file path for debugging information (optional).</param>
7488
/// <param name="debugLineNumber">The line number for debugging information (optional).</param>
7589
/// <returns>The current assembler instance.</returns>
76-
public <#= proc #>Assembler AddInstruction(<#= proc #>Instruction instruction, Mos6502Expression expression, [CallerFilePath] string debugFilePath = "", [CallerLineNumber] int debugLineNumber = 0)
90+
public TAsm AddInstruction(<#= proc #>Instruction instruction, Mos6502Expression expression, [CallerFilePath] string debugFilePath = "", [CallerLineNumber] int debugLineNumber = 0)
7791
{
7892
var currentAddress = CurrentAddress;
7993
var bufferOffset = SizeInBytes;
@@ -83,7 +97,7 @@ public partial class <#= proc #>Assembler : Mos6502AssemblerBase<<#= proc #>Asse
8397

8498
Patches.Add(new(currentAddress, (ushort)(bufferOffset + 1), instruction.AddressingMode, expression));
8599

86-
return this;
100+
return (TAsm)this;
87101
}
88102
}
89103
<# } #>

0 commit comments

Comments
 (0)