История изменений
Исправление quasimoto, (текущая версия) :
Добавим безусловных циклов, чтоб пример anonymous-а с зависанием был
#include <cstddef>
#include <cassert>
using Reg = size_t;
enum Op : Reg {
    HLT = 0,
    PLS = 1,
    DBL = 2
};
Op JMP(Reg label) {
    return Op(label + 3);
}
Reg label(Op op) {
    assert(op >= 3);
    return op - 3;
}
Reg run(const Op code[]) {
    for (Reg i = 0, reg = 0;;)
        switch (code[i]) {
        case HLT:
            return reg;
        case PLS:
            ++reg;
            ++i;
            break;
        case DBL:
            reg *= 2;
            ++i;
            break;
        default: // JMP
            i = label(code[i]);
            break;
        }
}
int main() {
    const Op code[] = { PLS, DBL, JMP(5), DBL, HLT, PLS, DBL, JMP(3) };
    return run(code);
}
Теперь трейсинг control flow с накоплением инструкций не прокатит, так как control flow может продолжаться сколько угодно долго.
Исходная версия quasimoto, :
Добавим безусловных циклов, чтоб пример anonymous-а с зависанием был
#include <cstddef>
#include <cassert>
using Reg = size_t;
enum Op : Reg {
    HLT = 0,
    PLS = 1,
    DBL = 2
};
Op JMP(Reg label) {
    return Op(label + 3);
}
Reg label(Op op) {
    assert(op >= 3);
    return op - 3;
}
Reg run(Op code[]) {
    for (Reg i = 0, reg = 0;;)
        switch (code[i]) {
        case HLT:
            return reg;
        case PLS:
            ++reg;
            ++i;
            break;
        case DBL:
            reg *= 2;
            ++i;
            break;
        default: // JMP
            i = label(code[i]);
            break;
        }
}
int main() {
    Op code[] = { PLS, DBL, JMP(5), DBL, HLT, PLS, DBL, JMP(3) };
    return run(code);
}
Теперь трейсинг control flow с накоплением инструкций не прокатит, так как control flow может продолжаться сколько угодно долго.