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 }