/* * SPDX-FileCopyrightText: Dora "cat" * SPDX-License-Identifier: MPL-2.0 * * 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 http://mozilla.org/MPL/2.0/. */ #ifndef GUARD_VARIADICMACHINE_MACHINE_H #define GUARD_VARIADICMACHINE_MACHINE_H #include #include #include #include #include #include #include namespace VariadicMachine { using Command = int; enum : int { // Single Argument NoCommand, MoveLeft, MoveRight, Increment, Decrement, // Two Arguments IncrementBy, DecrementBy, MultiplyBy, DivideBy, ModulusBy, SetTo, JumpTo, Print, // Type AsDigit, AsUnsignedDigit, AsCharacter, AsBinary, AsHex, }; template class VMachine { public: template constexpr void Do(Commands &&...commands) { (Execute(commands), ...); } private: Command State = NoCommand; std::array memory; int W = 0, X = 0, Y = 0, Z = 0; std::size_t currentPosition = 0; void Execute(int command) { switch (State) { case NoCommand: processCommand(command); return; // Arithmetic case SetTo: memory[currentPosition] = command; break; case IncrementBy: memory[currentPosition] += command; break; case DecrementBy: memory[currentPosition] -= command; break; case MultiplyBy: memory[currentPosition] *= command; break; case DivideBy: memory[currentPosition] /= command; break; case ModulusBy: memory[currentPosition] %= command; break; case JumpTo: currentPosition = command; break; case Print: handlePrint(command); break; default: std::terminate(); return; } // This is only called after multi-argument functions are done if (State != NoCommand) { State = NoCommand; return; } } void processCommand(int command) { switch (command) { case MoveLeft: // Underflow wrap if (--currentPosition > maxCells) { currentPosition = maxCells; } return; case MoveRight: // Overflow wrap if (++currentPosition > maxCells) { currentPosition = 0; } return; case Increment: ++memory[currentPosition]; return; case Decrement: --memory[currentPosition]; return; // Double Argument Commands case Print: case JumpTo: case SetTo: case IncrementBy: case DecrementBy: case MultiplyBy: case DivideBy: case ModulusBy: State = static_cast(command); return; default: std::cout << "Here\n"; std::terminate(); return; } } void handlePrint(int Type) { switch (Type) { case AsDigit: std::cout << memory[currentPosition]; return; case AsUnsignedDigit: std::cout << static_cast(memory[currentPosition]); return; case AsCharacter: std::wcout << static_cast(memory[currentPosition]); return; case AsBinary: std::cout << std::bitset(memory[currentPosition]); return; // Ugh hate this, I really should use C++23 case AsHex: std::cout << "0x" << std::setfill('0') << std::setw(sizeof(int)) << std::hex << memory[currentPosition]; // Stupid reset because cout is a dumb dumb thing std::cout << std::dec << std::setfill(' ') << std::setw(0); return; default: std::terminate(); return; } } }; } // namespace VariadicMachine #endif