Wasm/Instructions/IfElseOperator.cs
using System.Collections.Generic;
using WasmBox.Wasm.Binary;
namespace WasmBox.Wasm.Instructions {
/// <summary>
/// Describes an operator that runs one of two blocks
/// </summary>
public sealed class IfElseOperator : Operator {
internal IfElseOperator(byte opCode, WasmType declaringType, string mnemonic)
: base(opCode, declaringType, mnemonic) { }
/// <summary>
/// Reads the immediates (not the opcode) of a WebAssembly instruction
/// for this operator from the given reader and returns the result as an
/// instruction.
/// </summary>
/// <param name="reader">The WebAssembly file reader to read immediates from.</param>
/// <returns>A WebAssembly instruction.</returns>
public override Instruction ReadImmediates(BinaryWasmReader reader) {
var type = reader.ReadWasmType();
return ReadBlockContents(type, reader);
}
/// <summary>
/// Reads the child instructions of a WebAssembly block from the given reader.
/// </summary>
/// <param name="blockType">The type of value returned by the resulting block.</param>
/// <param name="reader">The WebAssembly file reader.</param>
/// <returns>A WebAssembly block instruction.</returns>
public static IfElseInstruction ReadBlockContents(WasmType blockType, BinaryWasmReader reader) {
var ifBranch = new List<Instruction>();
List<Instruction> elseBranch = null;
while (true) {
byte opCode = reader.ReadByte();
if (opCode == Operators.EndOpCode) {
return new IfElseInstruction(blockType, ifBranch, elseBranch);
}
else if (opCode == Operators.ElseOpCode) {
if (elseBranch != null) {
throw new WasmException("More than one 'else' opcode in an 'if' instruction");
}
elseBranch = new List<Instruction>();
}
else {
Operator op;
if ( Operators.IsPrefix( opCode ) ) {
var unsignedInt = reader.ReadVarUInt32(); // seven?
op = Operators.GetPrefixedOperatorByUInt( opCode, unsignedInt );
}
else {
op = Operators.GetOperatorByOpCode( opCode );
}
(elseBranch == null ? ifBranch : elseBranch).Add(op.ReadImmediates(reader));
}
}
}
/// <summary>
/// Creates an if-else instruction from the given type, if-branch and
/// else-branch.
/// </summary>
/// <param name="type">The type of value returned by the if-else instruction.</param>
/// <param name="ifBranch">The if-else instruction's 'if' branch.</param>
/// <param name="elseBranch">The if-else instruction's 'else' branch.</param>
public IfElseInstruction Create(
WasmType type,
IEnumerable<Instruction> ifBranch,
IEnumerable<Instruction> elseBranch) {
return new IfElseInstruction(type, ifBranch, elseBranch);
}
/// <summary>
/// Casts the given instruction to this operator's instruction type.
/// </summary>
/// <param name="value">The instruction to cast.</param>
/// <returns>The given instruction as this operator's instruction type.</returns>
public IfElseInstruction CastInstruction(Instruction value) {
return (IfElseInstruction)value;
}
}
}