Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <algorithm>
- #include <string>
- #include <vector>
- #include <cassert>
- namespace tf
- {
- /* Threadful - The threadiest esoteric language.
- Every thread lives only one generation, but often creates new ones.
- Threads have their own instruction pointer which also is their memory pointer, even if the program and the memory are separated.
- The memory is initialized to zero. (i.e. 0x0, not the '0' ASCII character)
- The memory available to the program holds 8-bit unsigned cells. The underflow and overflow behaviour is wrapping.
- The width of the program is typically defined by the size of the first line.
- Threads also have an origin pointer, which is used by most instructions to perform a calculation between the previous and the current cell.
- Those pointers triggers undefined behaviour or an interpreter crash if they're pointing to an value out of the program/memory.
- Threads may not interfere with others. When two or more threads at a time try to write on the same cell, that cell is zeroed out. It still allows two thread creation on the same cell.
- Threads cannot create a thread on their direct origin pointer, one exception is '!'.
- A thread must point to a valid instruction. Else, undefined behaviour is triggered, or the interpreter crashes.
- */
- // 'x' : Multiply
- // Create threads multiplying the current cell with the top left, top right, bottom right and bottom left cells.
- // '/' : Divide
- // Create threads dividing the current cell with the bottom left and top right cells.
- // Division by zero triggers undefined behaviour or an interpreter crash.
- // '%' : Modulo
- // Create threads performing a modulo with the current cell and the bottom left and top right cells.
- // '+' : Add
- // Create threads adding the current cell with the top, right, bottom and left cells.
- // '-' : Subtract
- // Create threads subtracting the current cell with the left and right cells.
- // 'p' : Print
- // Prints the current cell's value as an ASCII character. Creates a no-operation thread to the bottom cell.
- // 'g' : Get character
- // Gets a character from the user and sets the current cell's value to it. Creates a no-operation thread to the left cell.
- // '=' : Copy
- // Creates threads copying the current cell to the left and right cells.
- // '$' : Gate
- // If the origin pointer is the left cell, a no-operation thread will be created on the left.
- // If the origin pointer is the right cell, a no-operation thread will be created on the right.
- // BUT in those previous cases, if the value of the current cell is zero, a new gate will be created on the other direction instead.
- // If the origin pointer is the top cell, a no-operation thread will be created to the bottom.
- // If the origin pointer is the bottom cell, a no-operation thread will be created to the top.
- // '}' : '>' comparator
- // Conditional gate. Acts the same as the '$' gate, but it will open instead if the current cell is bigger than the origin cell.
- // '{' : '<' comparator
- // Conditional gate. Acts the same as the '$' gate, but it will open instead if the current cell is smaller than the origin cell.
- // '^' : Initializer cell
- // Defines the program start.
- // Creates a no-operation thread to the top cell, and sets its value to the value represented by the cell on the bottom (i.e. an ASCII character).
- // May be used for other reasons than defining program startup points.
- // '*' : Propagator
- // Creates no-operation threads to the top left, top, top right, right, bottom right, bottom, bottom left and left cells.
- // Reminder : As stated by the language rules, it cannot create a thread on its origin cell.
- // '#' : Bridge
- // If the origin pointer is the top cell, a no-operation thread will be created to the bottom.
- // If the origin pointer is the left cell, a no-operation thread will be created to the right.
- // etc.
- // '!' : One-way vertical bridge
- // If the origin pointer is the top cell, a no-operation thread will be created to the bottom.
- // Else, threads are "bounced" back to their origin cell.
- struct Cell
- {
- unsigned char instruction;
- uint8_t memory_value;
- uint8_t future_value;
- bool was_changed = false;
- void set_future_value(const uint8_t future)
- {
- if (was_changed) // If two threads write on the same cell, then it's zeroed out.
- {
- future_value = 0;
- return;
- }
- was_changed = true;
- future_value = future;
- }
- };
- template<typename T>
- struct Vec2
- {
- T x, y;
- };
- typedef Vec2<unsigned> Vec2u;
- typedef Vec2<int> Vec2i;
- struct Position
- {
- unsigned at;
- Vec2u to_position(const unsigned width)
- {
- return Vec2u{at / width, at % width};
- }
- Cell& get_cell(std::vector<Cell>& memory, const unsigned width) const
- {
- return memory[at];
- }
- Position operator+(const Position& other) const
- {
- static Position new_pos = Position{at + other.at};
- return new_pos;
- }
- Position operator-(const Position& other) const
- {
- static Position new_pos = Position{at - other.at};
- return new_pos;
- }
- template<typename T>
- Position add_vec(const Vec2<T> other, const unsigned width) const
- {
- static Position new_pos = Position{at + (other.x + (other.y * width))};
- return new_pos;
- }
- template<typename T>
- Position sub_vec(const Vec2<T> other, const unsigned width) const
- {
- static Position new_pos = Position{at - (other.x + (other.y * width))};
- return new_pos;
- }
- bool operator==(const Position& other) const
- {
- return at == other.at;
- }
- // Necessary?
- bool operator!=(const Position& other) const
- {
- return at != other.at;
- }
- };
- struct Thread
- {
- Position current, origin;
- };
- class Interpreter
- {
- std::vector<Thread> m_threads;
- size_t m_width = 0;
- std::vector<Cell> m_memory;
- public:
- Interpreter(const std::string& program)
- {
- auto first_linefeed = std::find(begin(program), end(program), '\n');
- assert(first_linefeed != end(program)); // Can't have a one-line program
- m_width = first_linefeed - begin(program); // Get the position of the first line jump and set it as the size
- {
- unsigned x = 0;
- for (const char& instr : program)
- {
- if (instr != '\n')
- {
- m_memory.push_back({static_cast<unsigned char>(instr), 0});
- }
- else
- {
- m_memory.resize(m_memory.size() + (m_width - x)); // Leave empty space
- x = 0; // Reset the x coord
- }
- assert(x++ < m_width);
- }
- }
- }
- void preload()
- {
- // Fill the thread vector from initializer cells
- for (unsigned i = 0; i < m_memory.size(); ++i)
- {
- if (m_memory[i].instruction == '^')
- {
- Position pos{i};
- m_threads.push_back(Thread{pos, pos});
- }
- }
- }
- inline void thread_create(const Position& position, // New thread's cell
- const Position& origin, // New thread's original position
- const Position& origin_origin, // Origin's original position
- const bool allow_eq_grandpa = false) // Allow the original's original position to be the same as the new position.
- {
- if (allow_eq_grandpa || position != origin_origin)
- {
- m_threads.push_back(Thread{position, origin});
- }
- }
- void interprete()
- {
- while (m_threads.size()) // While there are still threads left
- {
- for (Thread& thread : m_threads)
- {
- Cell& current_cell = thread.current.get_cell(m_memory, m_width);
- Cell& original_cell = thread.origin.get_cell(m_memory, m_width);
- switch(current_cell.instruction)
- {
- case 'x': // Multiply
- for (const Position& cpos : // thread creation pos
- { thread.current.add_vec(Vec2i{1, -1}, m_width), // Top right
- thread.current.add_vec(Vec2i{1, 1}, m_width), // Bottom right
- thread.current.add_vec(Vec2i{1, -1}, m_width), // Bottom left
- thread.current.add_vec(Vec2i{-1, 1}, m_width) }) // Top left
- {
- Cell& new_cell = cpos.get_cell(m_memory, m_width);
- new_cell.future_value = current_cell.memory_value * new_cell.memory_value;
- thread_create(cpos, thread.current, thread.origin);
- }
- default:
- std::cerr << "Unknown instruction detected. Aborting." << std::endl;
- return;
- }
- }
- }
- }
- };
- }
- int main()
- {
- const std::string program =
- "";
- tf::Interpreter inter(program);
- inter.preload();
- //inter.interprete();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement