// Copyright (c) 2022 bradson // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Reflection.Emit; namespace FisheryLib; public static class FishTranspiler { public struct Container { public Container(OpCode opcode, object? operand = null) { OpCode = opcode; Operand = operand; } public Container(CodeInstruction instruction) { Guard.IsNotNull(instruction, nameof(instruction)); OpCode = instruction.opcode; Operand = instruction.operand; } public Container(Container container) { OpCode = container.OpCode; Operand = container.Operand; } public override string ToString() => $"{OpCode} {Operand}"; public CodeInstruction ToInstruction() => new(OpCode, Operand); public Container Store() => OpCode.LoadsArgument() ? ToStoreArgument() : new( OpCode.LoadsField() || OpCode.StoresField() ? OpCode.ToStoreField() : OpCode.LoadsLocalVariable() || OpCode.StoresLocalVariable() ? OpCode.ToStoreLocalVariable() : OpCode.StoresArgument() ? OpCode : ThrowHelper.ThrowInvalidOperationException($"Cannot determine Store instruction for {OpCode}"), Operand); public Container Load() => OpCode.StoresArgument() ? ToLoadArgument() : new( OpCode.LoadsField() || OpCode.StoresField() ? OpCode.ToLoadField() : OpCode.LoadsLocalVariable() || OpCode.StoresLocalVariable() ? OpCode.ToLoadLocalVariable() : OpCode.LoadsArgument() ? OpCode : ThrowHelper.ThrowInvalidOperationException($"Cannot determine Load instruction for {OpCode}"), Operand); private Container ToStoreArgument() => new(OpCode.ToStoreArgument(), GetIndex()); private Container ToLoadArgument() { var index = GetIndex(); return new(GetLoadArgumentOpCode(index), index > 3 ? index : null); } public Container Address() => new(OpCode.ToAddress(), GetIndex()); public CodeInstruction WithLabels(params Label[] labels) => WithLabels((IEnumerable