enum snv_state { // Primary states. INSERT, MATCH, REMOVE, // Secondary states. FETCH, LITERAL, VARIABLE }; template struct snv_stack { uint32_t data[size] = {}; uint8_t top = 0; uint8_t offset = 0; inline void push(uint32_t symbol) { if(!full()) { data[top] = symbol; top++; } } inline uint32_t pop() { uint32_t result = 0; if(!empty()) { result = data[top]; top--; } return result; } inline uint32_t peek() { if(!empty() && offset < top) { return data[(top - 1) - offset]; } return 0; } inline bool empty() { return top == 0; } inline bool full() { return top >= size; } inline void reset() { offset = 0; } inline void clear() { top = 0; offset = 0; } }; struct snv_variable { uint32_t symbol = 0; bool bound = false; inline void clear() { symbol = 0; bound = false; } inline bool bind(uint32_t symbol) { if(bound) { return symbol == this->symbol; } this->symbol = symbol; bound = true; return true; } }; template struct snv_core { snv_stack stacks[stack_count] = {}; snv_variable variables[variable_count] = {}; char program[program_size] = {}; snv_state primary = snv_state::INSERT; snv_state secondary = snv_state::FETCH; void (*hook)(snv_core*) = nullptr; uint64_t limit = ~0; uint32_t length = 0; uint32_t stack = 0; uint32_t cursor = 0; uint32_t last = program_size; snv_core(const char* program) { uint32_t cursor = 0; while(cursor < program_size && program[cursor] != '\0') { this->program[cursor] = program[cursor]; cursor++; } length = cursor; } inline void seek(char instruction) { while(cursor < program_size) { if(cursor == '`' && instruction != '`') { cursor++; seek('`'); cursor++; } else if(program[cursor] == instruction || instruction == ';') { break; } else { cursor++; } } } inline void clear() { for(uint8_t variable = 0; variable < variable_count; variable++) { variables[variable].clear(); } for(uint8_t stack = 0; stack < stack_count; stack++) { stacks[stack].reset(); } } inline void branch() { clear(); seek('.'); } inline void variable() { Serial.printf("VARIABLE! %c %d\n", program[cursor], cursor); if(secondary == snv_state::LITERAL) { secondary = snv_state::VARIABLE; } cursor++; } inline void reset() { clear(); cursor = 0; primary = snv_state::INSERT; secondary = snv_state::FETCH; seek('?'); if(hook != nullptr) { hook(this); } } inline uint32_t number() { char instruction = program[cursor]; if(instruction >= '0' && instruction <= '9') { return instruction - '0'; } else if(instruction >= 'a' && instruction <= 'f') { return (instruction - 'a') + 10; } else if(instruction >= 'A' && instruction <= 'F') { return (instruction - 'A') + 10; } else { return 0; } } inline void insert() { uint32_t symbol = number(); Serial.printf("INSERT! %c %d\n", program[cursor], cursor); if(secondary == snv_state::LITERAL) { stacks[stack].push(symbol); } else { if(variables[symbol].bound) { stacks[stack].push(variables[symbol].symbol); } else { stacks[stack].push(0); } } secondary = snv_state::FETCH; cursor++; } inline void match() { Serial.printf("MATCH! %c %d\n", program[cursor], cursor); if(stacks[stack].empty() || stacks[stack].offset >= stacks[stack].top) { branch(); } else { uint32_t symbol = number(); if(secondary == snv_state::LITERAL) { if(stacks[stack].peek() != symbol) { branch(); } else { stacks[stack].offset++; } } else if(secondary == snv_state::VARIABLE) { if(!variables[symbol].bind(stacks[stack].peek())) { branch(); } else { stacks[stack].offset++; } } } secondary = snv_state::FETCH; cursor++; } inline void literal() { Serial.printf("LITERAL! %c %d\n", program[cursor], cursor); if(secondary == snv_state::FETCH) { uint32_t symbol = number(); if(primary == snv_state::REMOVE) { stacks[symbol].pop(); } else { stack = symbol; secondary = snv_state::LITERAL; } cursor++; return; } if(primary == snv_state::INSERT) { insert(); } else { match(); } } inline void transition(snv_state state) { Serial.printf("TRANSITION! %c %d\n", program[cursor], cursor); primary = state; secondary = snv_state::FETCH; cursor++; } inline void comment() { Serial.printf("COMMENT! %c %d\n", program[cursor], cursor); cursor++; seek('`'); cursor++; } inline bool step() { if(cursor >= length || cursor >= program_size) { return true; } Serial.printf("%d [%c]\n", cursor, program[cursor]); print(); switch(program[cursor]) { case '+': transition(snv_state::INSERT); break; case '?': transition(snv_state::MATCH); break; case '-': transition(snv_state::REMOVE); break; case '$': variable(); break; case '.': reset(); break; case ';': return true; case '`': comment(); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': literal(); break; default: cursor++; } return false; } inline void run() { bool halt = false; uint64_t steps = 0; while(!halt && steps != limit) { halt = step(); steps++; } } };