/ src / Spv.Generator / InstructionOperands.cs
InstructionOperands.cs
 1  using System;
 2  using System.Collections.Generic;
 3  using System.Linq;
 4  using System.Runtime.InteropServices;
 5  
 6  namespace Spv.Generator
 7  {
 8      public struct InstructionOperands
 9      {
10          private const int InternalCount = 5;
11  
12          public int Count;
13          public IOperand Operand1;
14          public IOperand Operand2;
15          public IOperand Operand3;
16          public IOperand Operand4;
17          public IOperand Operand5;
18          public IOperand[] Overflow;
19  
20          public Span<IOperand> AsSpan()
21          {
22              if (Count > InternalCount)
23              {
24                  return MemoryMarshal.CreateSpan(ref this.Overflow[0], Count);
25              }
26              else
27              {
28                  return MemoryMarshal.CreateSpan(ref this.Operand1, Count);
29              }
30          }
31  
32          public void Add(IOperand operand)
33          {
34              if (Count < InternalCount)
35              {
36                  MemoryMarshal.CreateSpan(ref this.Operand1, Count + 1)[Count] = operand;
37                  Count++;
38              }
39              else
40              {
41                  if (Overflow == null)
42                  {
43                      Overflow = new IOperand[InternalCount * 2];
44                      MemoryMarshal.CreateSpan(ref this.Operand1, InternalCount).CopyTo(Overflow.AsSpan());
45                  }
46                  else if (Count == Overflow.Length)
47                  {
48                      Array.Resize(ref Overflow, Overflow.Length * 2);
49                  }
50  
51                  Overflow[Count++] = operand;
52              }
53          }
54  
55          private readonly IEnumerable<IOperand> AllOperands => new[] { Operand1, Operand2, Operand3, Operand4, Operand5 }
56              .Concat(Overflow ?? Array.Empty<IOperand>())
57              .Take(Count);
58  
59          public readonly override string ToString()
60          {
61              return $"({string.Join(", ", AllOperands)})";
62          }
63  
64          public readonly string ToString(string[] labels)
65          {
66              var labeledParams = AllOperands.Zip(labels, (op, label) => $"{label}: {op}");
67              var unlabeledParams = AllOperands.Skip(labels.Length).Select(op => op.ToString());
68              var paramsToPrint = labeledParams.Concat(unlabeledParams);
69              return $"({string.Join(", ", paramsToPrint)})";
70          }
71      }
72  }