Rendere i messaggi futuri eseguibili online con frammenti di stack


134

Stack Snippet sono stati recentemente aggiunti a PPCG ! Ricordando JSFiddle , Stack Snippet consentono a HTML, CSS e JavaScript di essere eseguiti direttamente nei post !

Ecco un frammento di stack molto semplice:

alert('This is JavaScript')
h3 { color: red } /* This is CSS */
<h3>This is HTML</h3>

Questa funzionalità di Stack Exchange sarebbe molto utile per noi se fossero supportate lingue oltre a JavaScript. (Le risposte alle sfide potrebbero essere testate sul posto, esempi di input potrebbero essere generati dinamicamente, ecc.) Qui è dove entri.

Sfida

L'obiettivo di questa sfida è scrivere un interprete per alcuni linguaggi di programmazione usando Stack Snippet e JavaScript. Il punto è creare qualcosa che possa essere facilmente copiato e utilizzato nelle future domande e risposte PPCG.

Più o meno, devi creare uno snippet di stack con un pulsante "Esegui" e due caselle di testo, una per il codice e una per l'input. Facendo clic sul pulsante Esegui verrà eseguito il codice (scritto nella lingua che si sta interpretando) sull'input e verrà visualizzato il risultato (probabilmente in un'altra casella di testo). Lo snippet dovrebbe essere simile a cjam.aditsu.net o alla risposta di esempio .

Per la maggior parte delle lingue sarebbe logico che input e output rappresentassero rispettivamente stdin e sdout e potresti avere un'altra casella di input per la riga di comando. Ma non tutte le lingue hanno meccanismi I / O così tradizionali. HQ9 + , ad esempio, non ha nemmeno input, rendendo inutile una casella di testo. Quindi sentiti libero di prenderti alcune libertà, progettare in base alla lingua, non a questa specifica. Il requisito principale è che la tua lingua sia "eseguibile" in uno snippet di stack nel senso accettato del termine.

Appunti

  • L'implementazione di ogni singola funzionalità della tua lingua, sebbene ideale, non è richiesta. Alcune cose come leggere e scrivere file o importare librerie possono essere ingombranti o impossibili. Concentrati sulla creazione di un interprete che massimizzi l'utilità per l'uso su questo sito.
  • Pubblicare un interprete "lingua X in JavaScript" che non hai scritto va bene (con attribuzione).
  • Stack Exchange limita le risposte a 30.000 caratteri , quindi pianifica di conseguenza se è probabile che il tuo interprete sia lungo.
  • È meglio rendere una versione dell'interprete il più semplice possibile da includere nei post futuri. Ad esempio, nella risposta di esempio , viene fornito il Markdown grezzo per l'intero snippet, con posizioni ovvie in cui inserire codice e input.

Sebbene questa domanda sia più un compendio di interpreti che una vera e propria sfida, è comunque una , quindi vince la risposta più votata.

Elenco degli interpreti attuali

(in ordine alfabetico per nome della lingua)

  1. Fascio
  2. Befunge-93
  3. Brainfuck
  4. Brainfuck
  5. CHIQRSX9 +
  6. Pesce morto
  7. Deadfish (esegue solo il codice preimpostato)
  8. Fourier
  9. FRACTRAN
  10. Ciao ++
  11. HQ9 +
  12. Insonnia
  13. Japt
  14. JavaScript (risposta di esempio)
  15. JavaScript ES2015
  16. Marbelous
  17. Neoscript
  18. oOo CODICE
  19. Ouroboros
  20. Preludio
  21. Python 2
  22. STATA
  23. TI-Basic
  24. Unario (si traduce in BF)

(Questa domanda potrebbe essere più adatta a Meta, ma sarà più visibile qui. Le persone potrebbero effettivamente produrre interpreti molto utili, penso che meritino il rappresentante per questo.)


2
Non sarebbe molto divertente, ma la risposta più pratica per le lingue più difficili come Python sarebbe probabilmente quella di esternalizzarla.
Sp3000,

7
Non ho idea di come eseguire questi frammenti utilizzando l'app di scambio di stack.
Jerry Jeremiah,

1
Spero che qualcuno affronti C con questa sfida. Ecco un vantaggio: stackoverflow.com/questions/6142193/…
Adam Davis,


1
@ Sp3000: Oppure cerca le librerie ... come sotto.
ArtOfCode

Risposte:


48

Python 2 (No STDIN)

Grazie a Skulpt , è diventato molto facile scrivere un interprete Python.

function out(text) {
  var output = document.getElementById("output");
  output.innerHTML = output.innerHTML + text;
}

function builtinRead(x) {
  if(Sk.builtinFiles === undefined || Sk.builtinFiles["files"][x] === undefined)
    throw "File not found: '" + x + "'";
  return Sk.builtinFiles["files"][x];
}

function run() {
  var program = document.getElementById("python-in").value;
  var output = document.getElementById("output");
  
  output.innerHTML = "";
  
  Sk.canvas = "canvas";
  Sk.pre = "output";
  
  Sk.configure({
    output: out,
    read: builtinRead
  });
  
  try {
    Sk.importMainWithBody("<stdin>", false, program);
  }
  catch(e) {
    throw new Error(e.toString());
  }
}
#python-in {
  border-radius: 3px;
  background: rgb(250, 250, 250);
  width: 95%;
  height: 200px;
}

#output {
  border-radius: 3px;
  background: lightgray;
  width: 95%;
  height: 200px;
  overflow: auto;
}

#canvas {
  border: 1px solid gray;
  border-radius: 3px;
  height: 400px;
  width: 400px;
}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://www.skulpt.org/static/skulpt.min.js"></script>
<script src="http://www.skulpt.org/static/skulpt-stdlib.js"></script>

Python code:<br/>
<textarea id="python-in" name="python-in" rows="10" cols="80"></textarea><br/>
<button id="run-code" onclick="run()">Run</button><br/>
<br/>

Output:<br/>
<pre id="output" name="output" rows="10" cols="10" disabled></pre><br/>

Canvas for turtles:<br/>
<canvas height="400" width="400" id="canvas">Your browser does not support HTML5 Canvas!</canvas>

No STDIN, ma è un'implementazione abbastanza completa di Python in JS. Vorrei caricare le librerie da qualche altra parte ma non riesco a trovarne una serie.


1
Caspita, from random import randrangefunziona anche. Bello!
Maniglia della porta

20
Ora carica la fonte Marbelous in questo interprete e ti procuri un interprete Marbelous!
Ingo Bürk,

3
Sembra essere Python2 poiché print 2funziona. Vale la pena menzionare, immagino.
ReyCharles,

2
Non sono sicuro se sia più divertente o più bello pensare a Marbelous che corre all'interno di un interprete Python che gira all'interno di javascript che corre all'interno di un browser web
vijrox,

1
Questo non funziona più, presumibilmente perché i collegamenti nei <script>tag sono morti :(
oldmud0

33

Befunge-93

Modifica: ho rielaborato l'intera GUI ora. Ne sono molto più felice. Una sorta di funzione breakpoint sarebbe interessante, ma probabilmente è troppo per questo. Punti aperti che probabilmente rivisiterò:

  • Consenti una scheda infinita
  • Visualizzare lo stack quando si passa attraverso il programma sarebbe pulito

Da quando ho appena implementato questo interprete per questa sfida, non è stato ampiamente testato. Tuttavia, l'ho provato ora con una varietà di programmi diversi e sembra funzionare bene.

L'ultima versione è disponibile all'ultima revisione di questo violino .

function BefungeBoard(source, constraints) {
    constraints = constraints || {
        width: 80,
        height: 25
    };

    this.constraints = constraints;
    this.grid = source.split(/\r\n|[\n\v\f\r\x85\u2028\u2029]/).map(function (line) {
        return (line + String.repeat(' ', constraints.width - line.length)).split('');
    });
    for (var i = this.grid.length; i < constraints.height; i++) {
        this.grid[i] = String.repeat(' ', constraints.width).split('');
    }

    this.pointer = {
        x: 0,
        y: 0
    };

    this.direction = Direction.RIGHT;
}

BefungeBoard.prototype.nextPosition = function () {
    var vector = this.direction.toVector(),
        nextPosition = {
            x: this.pointer.x + vector[0],
            y: this.pointer.y + vector[1]
        };

    nextPosition.x = nextPosition.x < 0 ? this.constraints.width - 1 : nextPosition.x;
    nextPosition.y = nextPosition.y < 0 ? this.constraints.height - 1 : nextPosition.y;

    nextPosition.x = nextPosition.x >= this.constraints.width ? 0 : nextPosition.x;
    nextPosition.y = nextPosition.y >= this.constraints.height ? 0 : nextPosition.y;

    return nextPosition;
};

BefungeBoard.prototype.advance = function () {
    this.pointer = this.nextPosition();
    if (this.onAdvance) {
        this.onAdvance.call(null, this.pointer);
    }
};

BefungeBoard.prototype.currentToken = function () {
    return this.grid[this.pointer.y][this.pointer.x];
};

BefungeBoard.prototype.nextToken = function () {
    var nextPosition = this.nextPosition();
    return this.grid[nextPosition.y][nextPosition.x];
};

var Direction = (function () {
    var vectors = [
        [1, 0],
        [-1, 0],
        [0, -1],
        [0, 1]
    ];

    function Direction(value) {
        this.value = value;
    }

    Direction.prototype.toVector = function () {
        return vectors[this.value];
    };

    return {
        UP: new Direction(2),
        DOWN: new Direction(3),
        RIGHT: new Direction(0),
        LEFT: new Direction(1)
    };
})();

function BefungeStack() {
    this.stack = [];
}

BefungeStack.prototype.pushAscii = function (item) {
    this.pushNumber(item.charCodeAt());
};

BefungeStack.prototype.pushNumber = function (item) {
    if (isNaN(+item)) {
        throw new Error(typeof item + " | " + item + " is not a number");
    }

    this.stack.push(+item);
};

BefungeStack.prototype.popAscii = function () {
    return String.fromCharCode(this.popNumber());
};

BefungeStack.prototype.popNumber = function () {
    return this.stack.length === 0 ? 0 : this.stack.pop();
};

function Befunge(source, constraints) {
    this.board = new BefungeBoard(source, constraints);
    this.stack = new BefungeStack();
    this.stringMode = false;
    this.terminated = false;

    this.digits = "0123456789".split('');
}

Befunge.prototype.run = function () {
    for (var i = 1; i <= (this.stepsPerTick || 10); i++) {
        this.step();
        if (this.terminated) {
            return;
        }
    }

    requestAnimationFrame(this.run.bind(this));
};

Befunge.prototype.step = function () {
    this.processCurrentToken();
    this.board.advance();
};

Befunge.prototype.processCurrentToken = function () {
    var token = this.board.currentToken();
    if (this.stringMode && token !== '"') {
        return this.stack.pushAscii(token);
    }

    if (this.digits.indexOf(token) !== -1) {
        return this.stack.pushNumber(token);
    }

    switch (token) {
        case ' ':
            while ((token = this.board.nextToken()) == ' ') {
                this.board.advance();
            }
            return;
        case '+':
            return this.stack.pushNumber(this.stack.popNumber() + this.stack.popNumber());
        case '-':
            return this.stack.pushNumber(-this.stack.popNumber() + this.stack.popNumber());
        case '*':
            return this.stack.pushNumber(this.stack.popNumber() * this.stack.popNumber());
        case '/':
            var denominator = this.stack.popNumber(),
                numerator = this.stack.popNumber(),
                result;
            if (denominator === 0) {
                result = +prompt("Illegal division by zero. Please enter the result to use:");
            } else {
                result = Math.floor(numerator / denominator);
            }

            return this.stack.pushNumber(result);
        case '%':
            var modulus = this.stack.popNumber(),
                numerator = this.stack.popNumber(),
                result;
            if (modulus === 0) {
                result = +prompt("Illegal division by zero. Please enter the result to use:");
            } else {
                result = Math.floor(numerator / modulus);
            }

            return this.stack.pushNumber(result);
        case '!':
            return this.stack.pushNumber(this.stack.popNumber() === 0 ? 1 : 0);
        case '`':
            return this.stack.pushNumber(this.stack.popNumber() < this.stack.popNumber() ? 1 : 0);
        case '>':
            this.board.direction = Direction.RIGHT;
            return;
        case '<':
            this.board.direction = Direction.LEFT;
            return;
        case '^':
            this.board.direction = Direction.UP;
            return;
        case 'v':
            this.board.direction = Direction.DOWN;
            return;
        case '?':
            this.board.direction = [Direction.RIGHT, Direction.UP, Direction.LEFT, Direction.DOWN][Math.floor(4 * Math.random())];
            return;
        case '_':
            this.board.direction = this.stack.popNumber() === 0 ? Direction.RIGHT : Direction.LEFT;
            return;
        case '|':
            this.board.direction = this.stack.popNumber() === 0 ? Direction.DOWN : Direction.UP;
            return;
        case '"':
            this.stringMode = !this.stringMode;
            return;
        case ':':
            var top = this.stack.popNumber();
            this.stack.pushNumber(top);
            return this.stack.pushNumber(top);
        case '\\':
            var first = this.stack.popNumber(),
                second = this.stack.popNumber();
            this.stack.pushNumber(first);
            return this.stack.pushNumber(second);
        case '$':
            return this.stack.popNumber();
        case '#':
            return this.board.advance();
        case 'p':
            return this.board.grid[this.stack.popNumber()][this.stack.popNumber()] = this.stack.popAscii();
        case 'g':
            return this.stack.pushAscii(this.board.grid[this.stack.popNumber()][this.stack.popNumber()]);
        case '&':
            return this.stack.pushNumber(+prompt("Please enter a number:"));
        case '~':
            return this.stack.pushAscii(prompt("Please enter a character:")[0]);
        case '.':
            return this.print(this.stack.popNumber());
        case ',':
            return this.print(this.stack.popAscii());
        case '@':
            this.terminated = true;
            return;
    }
};

Befunge.prototype.withStdout = function (printer) {
    this.print = printer;
    return this;
};

Befunge.prototype.withOnAdvance = function (onAdvance) {
    this.board.onAdvance = onAdvance;
    return this;
};

String.repeat = function (str, count) {
    var repeated = "";
    for (var i = 1; i <= count; i++) {
        repeated += str;
    }

    return repeated;
};

window['requestAnimationFrame'] = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) {
    window.setTimeout(callback, 1000 / 60);
};

(function () {
    var currentInstance = null;

    function resetInstance() {
        currentInstance = null;
    }

    function getOrCreateInstance() {
        if (currentInstance !== null && currentInstance.terminated) {
            resetInstance();
        }

        if (currentInstance === null) {
            var boardSize = Editor.getBoardSize();
            currentInstance = new Befunge(Editor.getSource(), {
                width: boardSize.width,
                height: boardSize.height
            });
            currentInstance.stepsPerTick = Editor.getStepsPerTick();

            currentInstance.withStdout(Editor.append);
            currentInstance.withOnAdvance(function (position) {
                Editor.highlight(currentInstance.board.grid, position.x, position.y);
            });
        }

        return currentInstance;
    }

    var Editor = (function (onExecute, onStep, onReset) {
        var source = document.getElementById('source'),
            sourceDisplay = document.getElementById('source-display'),
            sourceDisplayWrapper = document.getElementById('source-display-wrapper'),
            stdout = document.getElementById('stdout');
        var execute = document.getElementById('execute'),
            step = document.getElementById('step'),
            reset = document.getElementById('reset');
        var boardWidth = document.getElementById('board-width'),
            boardHeight = document.getElementById('board-height'),
            stepsPerTick = document.getElementById('steps-per-tick');

        function showEditor() {
            source.style.display = "block";
            sourceDisplayWrapper.style.display = "none";
            source.focus();
        }

        function hideEditor() {
            source.style.display = "none";
            sourceDisplayWrapper.style.display = "block";

            var computedHeight = getComputedStyle(source).height;
            sourceDisplayWrapper.style.minHeight = computedHeight;
            sourceDisplayWrapper.style.maxHeight = computedHeight;

            sourceDisplay.textContent = source.value;
        }

        function resetOutput() {
            stdout.value = null;
        }

        function escapeEntities(input) {
            return input.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
        }

        sourceDisplayWrapper.onclick = function () {
            resetOutput();
            showEditor();
            onReset && onReset.call(null);
        };
        execute.onclick = function () {
            resetOutput();
            hideEditor();
            onExecute && onExecute.call(null);
        };
        step.onclick = function () {
            hideEditor();
            onStep && onStep.call(null);
        };
        reset.onclick = function () {
            resetOutput();
            showEditor();
            onReset && onReset.call(null);
        };

        return {
            getSource: function () {
                return source.value;
            },

            append: function (content) {
                stdout.value = stdout.value + content;
            },

            highlight: function (grid, x, y) {
                var highlighted = [];
                for (var row = 0; row < grid.length; row++) {
                    highlighted[row] = [];
                    for (var column = 0; column < grid[row].length; column++) {
                        highlighted[row][column] = escapeEntities(grid[row][column]);
                    }
                }

                highlighted[y][x] = '<span class="activeToken">' + highlighted[y][x] + '</span>';
                sourceDisplay.innerHTML = highlighted.map(function (lineTokens) {
                    return lineTokens.join('');
                }).join('\n');
            },

            getBoardSize: function () {
                return {
                    width: +boardWidth.innerHTML,
                    height: +boardHeight.innerHTML
                };
            },

            getStepsPerTick: function () {
                return +stepsPerTick.innerHTML;
            }
        };
    })(function () {
        getOrCreateInstance().run();
    }, function () {
        getOrCreateInstance().step();
    }, resetInstance);
})();
.container {
    width: 100%;
}
.so-box {
    font-family:'Helvetica Neue', Arial, sans-serif;
    font-weight: bold;
    color: #fff;
    text-align: center;
    padding: .3em .7em;
    font-size: 1em;
    line-height: 1.1;
    border: 1px solid #c47b07;
    -webkit-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3), 0 2px 0 rgba(255, 255, 255, 0.15) inset;
    text-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
    background: #f88912;
    box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3), 0 2px 0 rgba(255, 255, 255, 0.15) inset;
}
.control {
    display: inline-block;
    border-radius: 6px;
    float: left;
    margin-right: 25px;
    cursor: pointer;
}
.option {
    padding: 10px 20px;
    margin-right: 25px;
    float: left;
}
input, textarea {
    box-sizing: border-box;
}
textarea {
    display: block;
    white-space: pre;
    overflow: auto;
    height: 75px;
    width: 100%;
    max-width: 100%;
    min-height: 25px;
}
span[contenteditable] {
    padding: 2px 6px;
    background: #cc7801;
    color: #fff;
}
#controls-container, #options-container {
    height: auto;
    padding: 6px 0;
}
#stdout {
    height: 50px;
}
#reset {
    float: right;
}
#source-display-wrapper {
    display: none;
    width: 100%;
    height: 100%;
    overflow: auto;
    border: 1px solid black;
    box-sizing: border-box;
}
#source-display {
    font-family: monospace;
    white-space: pre;
    padding: 2px;
}
.activeToken {
    background: #f88912;
}
.clearfix:after {
    content:".";
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
}
.clearfix {
    display: inline-block;
}
* html .clearfix {
    height: 1%;
}
.clearfix {
    display: block;
}
<div class="container">
    <textarea id="source" placeholder="Enter your Befunge-93 program here" wrap="off">"39-egnufeB">:#,_@</textarea>
    <div id="source-display-wrapper">
        <div id="source-display"></div>
    </div>
</div>
<div id="controls-container" class="container clearfix">
    <input type="button" id="execute" class="control so-box" value="► Execute" />
    <input type="button" id="step" class="control so-box" value="Step" />
    <input type="button" id="reset" class="control so-box" value="Reset" />
</div>
<div id="stdout-container" class="container">
    <textarea id="stdout" placeholder="Output" wrap="off" readonly></textarea>
</div>
<div id="options-container" class="container">
    <div class="option so-box">Steps per Tick: <span id="steps-per-tick" contenteditable>500</span>

    </div>
    <div class="option so-box">Board Size: <span id="board-width" contenteditable>80</span> x <span id="board-height" contenteditable>25</span>

    </div>
</div>


Bello! Dobbiamo inserire manualmente le dimensioni della scheda? Sembra che se non lo facciamo, l'evidenziazione tende ad andare ovunque. (test con il primo programma qui: en.wikipedia.org/wiki/Befunge#Sample_Befunge-93_code )
Sp3000

@ Sp3000 Devi solo inserirlo se vuoi cambiarlo (il default è 80x25 originale). Il programma funziona bene per me. "All over the place" è tutto ciò che riguarda Befunge. L'unica cosa non così bella è che devi passare attraverso tutti gli spazi bianchi del tabellone individualmente, ma lo risolverò. È tecnicamente corretto, però. Se ritieni che qualcosa sia strano, forse puoi fare un gif / video su come ti guarda?
Ingo Bürk,

@ Sp3000 Una cosa: se premi "Esegui", l'evidenziazione sembra strana perché sta andando troppo veloce. Se non l'hai mai fatto prima, prova "Step" per scorrere il comando del programma per comando. In alternativa, imposta i passaggi per tick su 1 e premi Esegui per un'animazione più fluida.
Ingo Bürk,

Ahaha sì, per "ovunque" intendevo il fatto che tutto lo spazio bianco è stato attraversato. Stai pensando di fare in modo che il programma rilevi le dimensioni della scheda in futuro? (Se hai tempo)
Sp3000,

1
@ Sp3000 La dimensione della scheda è di proprietà dell'interprete, non del programma. Inizialmente, le schede Befunge hanno una dimensione fissa. Ma puoi consentire dimensioni infinite che sto pensando di fare. Ho anche intenzione di saltare spazi bianchi consecutivi in ​​un solo passaggio.
Ingo Bürk,

33

TI-BASIC

perché a chi non piace TI-Basic?

Volevo contribuire a questo, quindi ho scelto una lingua che (secondo la mia modesta opinione) è leggermente più complicata di, diciamo, Deadfish, ma sotto il mio controllo. So molto della mia calcolatrice, quindi ho scelto questo.

Tuttavia, non ho alcuna esperienza con JavaScript / CSS / HTML. Questo è stato il mio primo programma. Questo significa...

Per favore, segnala gli errori che trovi nel mio codice!

Detto questo, questa è una versione limitata di TI-Basic. Continuerò a implementare le cose man mano che mi aggirerò.

Funzionalità al momento

  • parole chiave di controllo comuni (se, quindi, altrimenti, fine)
  • Tutti i loop disponibili (while, repeat, for)
  • comando disp
  • Operatori aritmetici JavaScript, via eval
  • elenchi
  • Costruito nel colon-ator automatico (vedi di persona)
  • Valori casuali di variabili non inizializzate, proprio come la tua calcolatrice
  • matematica limitata - sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, log, ln, int, round, abs.
  • costanti pi ed e come variabili
  • Chiedi, inserisci, metti in pausa (Yay!)
  • scrive sull'output durante l'esecuzione (grazie a pseudonimo117)
  • semplici funzionalità pixel-on / off / clear screen

Libertà prese

  • supporta nomi di variabili multi-carattere. Sfortunatamente, questo significa che abè una variabile, non il valore a*b. Questo limite di nomi di variabili univoco mi ha fatto impazzire sulla mia calcolatrice.
  • ignorando "goto" e "lbl". Erano buggy anche sulla calcolatrice a meno che tu non lo facessi in un certo modo.
  • Andando a ignorare prgm, OpenLib ed ExecLib perché non ci sono file esterni / altri

Cosa deve ancora essere fatto

  • Una sorta di tela per disegnare (presto disponibile!) Altre cose di disegno
  • In qualche modo per prompte inputcomandi nella finestra di testo (suggerimenti, qualcuno?)
  • Supporto per (il resto di) operazioni matematiche con la calcolatrice (ci sono SECCHI)
  • Supporta la Ansparola chiave shenanigans.
  • Supporto per il resto delle parole chiave CTL
  • Un modo per supportare una forma di getkey, anche se la maggior parte delle lingue al giorno d'oggi sono guidate da eventi ... Forse potrebbe essere l'ultimo tasto premuto.
  • Non so se questo sia vero, ma JavaScript sembra pensare prima, quindi visualizzare in un'area di testo, piuttosto che visualizzare come va.
  • Non ci sono bellezze CSS / HTML

Ancora non so molto su JavaScript. Se una delle precedenti è possibile / impossibile, per favore fatemelo sapere.

function inputChanged() {
    var codeText = document.getElementById('code-block');
    if (codeText.value.charAt(0) !== ':') {
        codeText.value = ':' + codeText.value;
    }
    var cursor = codeText.selectionEnd;
    if (lastText.length < codeText.value.length) { //adding characters
        if (/(\n)$/.test(codeText.value) === true || /(\n)(\n)/.test(codeText.value) === true) {
            cursor++;
        }
        codeText.value = codeText.value.replace(/(\n)$/, '\n:');
        codeText.value = codeText.value.replace(/(\n)(\n)/, '\n:\n');
    } else { //removing characters
        if (/(\n)$/.test(codeText.value) === true || /(\n)(\n)/.test(codeText.value) === true) {
            cursor--;
        }
        codeText.value = codeText.value.replace(/(\n)$/, '');
        codeText.value = codeText.value.replace(/(\n)(\n)/, '\n');
    }
    codeText.setSelectionRange(cursor, cursor);
    lastText = codeText.value;
}
function onUserInput(e){
    var output = document.getElementById('output');
    //enter has code 13
    if(awaitingInput && e.keyCode===13){
        var lines = output.value.split('\n');
        var input = lines[lines.length-1];
        if(input.indexOf('?')!==-1){
            input = input.substring(input.indexOf('?')+1,input.length);
        }
        if(newInputVarName !== null){
            var iValue = replaceVars(input);
            variables[newInputVarName]= eval(iValue);
        }else{
           output.value = output.value.substring(0,output.value.length-1);  
        }
        awaitingInput = false;
    }
}
var lastText = ':';
var L1 = [],
    L2 = [],
    L3 = [],
    L4 = [],
    L5 = [],
    L6 = []; //note - these are special. They're like variables, and are considered in replaceVars.
var tokens = [':', '-->', 'if', 'then',
    'else', 'for', 'while', ',',
    'repeat', 'end', 'disp','prompt','input',
    'pause','pxl-on','pxl-off','clrdraw'];
var variables = [];
var loopStack = []; //holds line numbers
var ifStack = [true]; //holds true or false
var typeStack = ['if'];
var repeatStack = []; //holds current iteration for repeats. NOTE: starts at 1 to accomidate repeat 0
var awaitingInput = false;
var newInputVarName=null;
var pixels = []; //96*64
var running = false;
var lineProcessing;
function run() {
    if(running===false){
        for(var pixelX=0;pixelX<96;pixelX++){
            for(var pixelY=0;pixelY<64;pixelY++){
                pixels[(pixelX,pixelY)]=0;         //doesn't work
            }
        }
        variables = [];
        loopStack = [];
        ifStack = [true];
        typeStack = ['if'];
        repeatStack = [];
        clear();
        var code = document.getElementById('code-block');
        var lines = code.value.split('\n');
        var currentLine = 0;
        variables['e'] = Math.E;
        variables['pi'] = Math.PI;
        L1.push(3);
        L1.push(4);
        lineProcessing = setInterval(function(){
            if(!awaitingInput){
                running = true;
                if(currentLine < lines.length || loopStack.length !== 0){
                    currentLine = processLine(lines,currentLine);
                    currentLine++;
                }
                else{
                    running = false;
                    lineProcessing.clearInterval();
                }
            }
        },10);
    }
}
function processLine(lines, currentLine) {
    var tokens = tokenize(lines[currentLine]);
    if (ifStack[ifStack.length - 1] === true){
        if (tokens.indexOf('-->') !== -1) {
            var index = tokens.indexOf('-->');
            for (var i = 0; i < index; i++) {
                tokens[i] = replaceVars(tokens[i]);
            }
            var value = eval(tokens[index - 1]);
            var name = tokens[index + 1];
            var listElement = false;
            if (name.length > 4) {
                if (/L[1-6]\(/.test(name) === true) {
                    var nextP = matchParenthese(name, 2);
                    var innerStuff = name.substring(3, nextP);
                    var value2 = eval(replaceVars(innerStuff));
                    var listNum = name.substring(0, 2);
                    if (value2 === Math.round(value2)) {
                        if (value2 > 0) {
                            if (listNum === 'L1') {
                                L1[value2] = value;
                            }
                            if (listNum === 'L2') {
                                L2[value2] = value;
                            }
                            if (listNum === 'L3') {
                                L3[value2] = value;
                            }
                            if (listNum === 'L4') {
                                L4[value2] = value;
                            }
                            if (listNum === 'L5') {
                                L5[value2] = value;
                            }
                            if (listNum === 'L6') {
                                L6[value2] = value;
                            }
                        } else {
                            printE('Arrays can only have positive indexes, and by some weird quirk of Texas Instruments, indexes start at 1, not 0.');
                            throw new Error();
                        }
                    } else {
                        printE('Sorry, this is not Javascript. Array indexes must be integers.');
                        throw new Error();
                    }
                }
            }
            variables[name + ""] = value;
        }
        if (tokens.indexOf('disp') !== -1) {
            var index2 = tokens.indexOf('disp');
            for (var g = index2 + 1; g < tokens.length; g++) {
                tokens[g] = replaceVars(tokens[g]);
                if (tokens[g] === ',') {} else {
                    print(eval(tokens[g]));
                }
            }
        }
        if(tokens.indexOf('prompt')!==-1){
            var pIndex = tokens.indexOf('prompt');
            var newVar = tokens[pIndex+1];
            document.getElementById('output').value += newVar+'=?';
            awaitingInput=true;
            newInputVarName = newVar;
        }
        if(tokens.indexOf('input')!==-1){
            var pIndex = tokens.indexOf('input');
            var newVar = tokens[pIndex+1];
            document.getElementById('output').value += '?';
            awaitingInput=true;
            newInputVarName = newVar;
        }
        if(tokens.indexOf('pause')!==-1){
            awaitingInput=true;
            newInputVarName = null;
        }
        if(tokens.indexOf('pxl-on')!==-1){
            var first = tokens[2].substring(1,tokens[2].length);
            var second = tokens[4].substring(0,tokens[4].length-1);
            first = replaceVars(first);
            second = replaceVars(second);
            var valueF = eval(first);
            var valueS = eval(second);
            drawPixel(valueF,valueS,1);
            pixels[(valueF,valueS)] = 1;
        }
        if(tokens.indexOf('pxl-off')!==-1){
            var first2 = tokens[2].substring(1,tokens[2].length);
            var second2 = tokens[4].substring(0,tokens[4].length-1);
            first2 = replaceVars(first2);
            second2 = replaceVars(second2);
            var valueF2 = eval(first2);
            var valueS2 = eval(second2);
            pixels[(valueF2,valueS2)] = 0;
            drawPixel(valueF2,valueS2,0);
        }
        if(tokens.indexOf('clrdraw')!==-1){
            clearPixels();
        }
        if (tokens.indexOf('if') !== -1) {
            var index3 = tokens.indexOf('if');
            tokens[index3 + 1] = replaceVars(tokens[index3 + 1]);
            var value = eval(tokens[index3 + 1]);
            ifStack.push(value);
            typeStack.push('if');
        }
        if (tokens.indexOf('while') !== -1) {
            var index4 = tokens.indexOf('while');
            var expression = tokens[index4 + 1];
            expression = replaceVars(expression);
            var value2 = eval(expression);
            if (value2 === true) {
                typeStack.push('while');
                loopStack.push(currentLine);
            } else {
                currentLine = nextEnd(currentLine, lines);
                return currentLine;
            }
        }
        if (tokens.indexOf('for') !== -1) {
            var index5 = tokens.indexOf('for');
            var varName = tokens[index5 + 1];
            varName = varName.trim();
            varName = varName.substring(1, varName.length);
            var initValue = eval(replaceVars(tokens[index5 + 3]));
            variables[varName] = initValue;
            var endingValue = eval(replaceVars(tokens[index5 + 5]));
            var increaseVal = replaceVars(tokens[index5 + 7]);
            increaseVal = eval(increaseVal.substring(0, increaseVal.length - 1));
            var diff = endingValue - initValue;
            if (sign(diff) !== sign(increaseVal) && sign(diff) !== 0) {
                currentLine = nextEnd(currentLine, lines);
                return currentLine;
            } else {
                loopStack.push(currentLine);
                typeStack.push('for');
            }
        }
        if (tokens.indexOf('repeat') !== -1) {
            var repeatVal = eval(replaceVars(tokens[1]));
            if (repeatVal === true || repeatVal === false) {
                //basically the same as a while loop...so just replace it!
                var newLine = 'while ' + '!(' + tokens[1] + ')';
                lines[currentLine] = newLine;
                currentLine--;
                return currentLine;
            } else {
                repeatStack.push(0);
                typeStack.push('repeat');
                loopStack.push(currentLine);
            }
        }
    }
    if (tokens.indexOf('else') !== -1) {
       ifStack[ifStack.length - 1] = !ifStack[ifStack.length - 1];
    }
    if (tokens.indexOf('end') !== -1) {
        if (typeStack[typeStack.length - 1] === 'if') {
            ifStack.pop();
            typeStack.pop();
        } else if (typeStack[typeStack.length - 1] === 'while') {
            var prevLineNum = loopStack[loopStack.length - 1];
            var prevLine = lines[prevLineNum];
            var prevTokens = tokenize(prevLine);
            var whileIndex = prevTokens.indexOf('while');
            var expression2 = replaceVars(prevTokens[whileIndex + 1]);
            if (eval(expression2) === true) {
                currentLine = prevLineNum - 1;
                return currentLine;
            } else {
                loopStack.pop();
                typeStack.pop();
            }
        } else if (typeStack[typeStack.length - 1] === 'repeat') {
            var line = lines[loopStack[loopStack.length - 1]];
            var tokenized = tokenize(line);
            var numTimes = eval(replaceVars(tokenized[1]));
            var currentIteration = repeatStack[repeatStack.length - 1];
            currentIteration++;
            if (currentIteration !== numTimes) {
                repeatStack[repeatStack.length - 1] = currentIteration;
                currentLine = loopStack[loopStack.length - 1]; //once currentLine++, will be on next line after repeat;
                return currentLine;
            } else {
                repeatStack.pop();
                typeStack.pop();
                loopStack.pop();
            }
        } else if (typeStack[typeStack.length - 1] === 'for') {
            var prevLineNum2 = loopStack[loopStack.length - 1];
            var prevLine2 = lines[prevLineNum2];
            var prevTokens2 = tokenize(prevLine2);
            var forIndex = prevTokens2.indexOf('for');
            var varName2 = prevTokens2[forIndex + 1];
            varName2 = varName2.substring(1, varName2.length);
            var initVal = eval(replaceVars(prevTokens2[forIndex + 3]));
            var endVal = eval(replaceVars(prevTokens2[forIndex + 5]));
            var stepVal = replaceVars(prevTokens2[forIndex + 7]);
            stepVal = eval(stepVal.substring(0, stepVal.length - 1));
            variables[varName2] = parseInt(stepVal, 10) + parseInt(variables[varName2], 10);
            var signDiff = sign(endVal - initVal);
            var condTrue = true;
            if (signDiff === 0) {
                condTrue = false;
            }
            if (signDiff === 1) {
                if (variables[varName2] > endVal) {
                    condTrue = false;
                }
            } else {
                if (variables[varName2] < endVal) {
                    condTrue = false;
                }
            }
            if (condTrue === true) {
                currentLine = prevLineNum2;
                return currentLine;
            } else {
                typeStack.pop();
                loopStack.pop();
            }
        }
    }
    return currentLine;
}

function sign(num) {
    if (num === 0) {
        return 0;
    }
    if (num > 0) {
        return 1;
    }
    return -1;
}
function drawPixel(x,y,color){//color = 0 if off, 1 if on
    var canvas = document.getElementById('canvas');
    var width = canvas.width;
    var height = canvas.height;
    var pxWidth = width/96;
    var pxHeight = height/64;
    var ctx = canvas.getContext('2d');
    if(color===1){
        ctx.fillStyle = '#000';
    }else{
        ctx.fillStyle = '#fff';
    }
    ctx.fillRect((x/96)*width, (y/64)*height,pxWidth,pxHeight);
}
function nextEnd(line, lines) {
    for (var i = line + 1; i < lines.length; i++) {
        if (lines[i].indexOf('end') !== -1) {
            return i;
        }
    }
    return line;
}

function tokenize(line) {
    line = line.trim();
    var split = [];
    var currentSplit = '';
    var cursor = 0;
    var unknown = '';
    var allTokens = tokens;
    while (cursor < line.length) {
        var lengthOfCursor = line.length - cursor;
        while (lengthOfCursor > 0) {
            var index = allTokens.indexOf(line.substring(cursor, cursor + lengthOfCursor));
            if (index !== -1) {
                if (unknown !== '') {
                    split.push(unknown.trim());
                }
                unknown = '';
                split.push(allTokens[index]);
                cursor += lengthOfCursor - 1; //for cursor++ later
                break;
            }
            lengthOfCursor--;
            if (lengthOfCursor === 0) {
                unknown = unknown.concat(line.charAt(cursor));
            }
        }
        cursor++;
    }
    if (unknown !== '') {
        split.push(unknown.trim());
    }
    return split;
}

function replaceVars(token) {
    for (var i = 0; i < tokens.length; i++) {
        if (token === tokens[i]) {
            return token;
        }
    }
    //deals with lists
    for (var cursor = 0; cursor < token.length - 1; cursor++) {
        if (/[^a-zA-Z_]L[1-6]|^L[1-6]/.test(token.substring(cursor, cursor + 3)) === true) {
            var parenthIndex;
            for (var newCurs = cursor; newCurs < token.length; newCurs++) {
                if (token.charAt(newCurs) === '(') {
                    parenthIndex = newCurs;
                    break;
                }
            }
            var nextPIndex = matchParenthese(token, parenthIndex);
            var inner = token.substring(parenthIndex + 1, nextPIndex);
            //note recursiveness, supports L1(L1(L1(5))), for example
            var innerValue = eval(replaceVars(inner));
            var num = parseInt(token.substring(parenthIndex - 1, parenthIndex));
            var realValue;
            if (num === 1) {
                realValue = L1[innerValue];
            }
            if (num === 2) {
                realValue = L2[innerValue];
            }
            if (num === 3) {
                realValue = L3[innerValue];
            }
            if (num === 4) {
                realValue = L4[innerValue];
            }
            if (num === 5) {
                realValue = L5[innerValue];
            }
            if (num === 6) {
                realValue = L6[innerValue];
            }
            if (innerValue !== Math.round(innerValue) || innerValue < 1) {
                printE('array indexes must be integers greater or equal to 1. Why? ask Texas Instruments.');
                throw new Error();
            }
            token = token.substring(0, parenthIndex - 2) + realValue + token.substring(nextPIndex + 1);
        }
    }
    //Math stuff
    var a;
    var sinFunc = function (value) {
        return Math.sin(value);
    };
    while ((a = returnValue('sin', token, sinFunc)) !== null) {
        token = a;
    }

    var cosFunc = function (value) {
        return Math.cos(value);
    };
    while ((a = returnValue('cos', token, cosFunc)) !== null) {
        token = a;
    }

    var tanFunc = function (value) {
        return Math.tan(value);
    };
    while ((a = returnValue('tan', token, tanFunc)) !== null) {
        token = a;
    }

    var asinFunc = function (value) {
        return Math.asin(value);
    };
    while ((a = returnValue('asin', token, asinFunc)) !== null) {
        token = a;
    }

    var acosFunc = function (value) {
        return Math.acos(value);
    };
    while ((a = returnValue('acos', token, acosFunc)) !== null) {
        token = a;
    }

    var atanFunc = function (value) {
        return Math.atan(value);
    };
    while ((a = returnValue('atan', token, atanFunc)) !== null) {
        token = a;
    }
    //note my calculator doesn't have atan2...

    var absFunc = function (value) {
        return Math.abs(value);
    };
    while ((a = returnValue('abs', token, absFunc)) !== null) {
        token = a;
    }

    var roundFunc = function (value) {
        return Math.round(value);
    };
    while ((a = returnValue('round', token, roundFunc)) !== null) {
        token = a;
    }

    var intFunc = function (value) {
        return Math.floor(value);
    };
    while ((a = returnValue('int', token, intFunc)) !== null) {
        token = a;
    }

    var coshFunc = function (value) {
        return (Math.pow(Math.E, value) + Math.pow(Math.E, -1 * value)) / 2;
    };
    while ((a = returnValue('cosh', token, coshFunc)) !== null) {
        token = a;
    }

    var sinhFunc = function (value) {
        return (Math.pow(Math.E, value) - Math.pow(Math.E, -1 * value)) / 2;
    };
    while ((a = returnValue('sinh', token, sinhFunc)) !== null) {
        token = a;
    }

    var tanhFunc = function (value) {
        return (Math.pow(Math.E, value) - Math.pow(Math.E, -1 * value)) / (Math.pow(Math.E, value) + Math.pow(Math.E, -1 * value));
    };
    while ((a = returnValue('tanh', token, tanhFunc)) !== null) {
        token = a;
    }

    //if token contains new variables, then initialize them with random values
    var newReg = new RegExp('([^a-zA-Z_])([a-zA-Z_]+)([^a-zA-Z_])', 'g');
    var newReg2 = new RegExp('^([a-zA-Z_]+)([^a-zA-Z_])', 'g');
    var newReg3 = new RegExp('([^a-zA-Z_])([a-zA-Z_]+)$', 'g');
    var newReg4 = new RegExp('^([a-zA-Z_]+)$', 'g');
    var match1 = token.match(newReg);
    if (match1 !== null) {
        for (var q = 0; q < match1.length; q++) {
            initializeVar(match1[q].substring(1, match1[q].length - 1));
        }
    }

    var match2 = token.match(newReg2);
    if (match2 !== null) {
        for (var w = 0; w < match2.length; w++) {
            initializeVar(match2[w].substring(0, match2[w].length - 1));
        }
    }

    var match3 = token.match(newReg3);
    if (match3 !== null) {
        for (var e = 0; e < match3.length; e++) {
            initializeVar(match3[e].substring(1, match3[e].length));
        }
    }

    var match4 = token.match(newReg4);
    if (match4 !== null) {
        for (var r = 0; r < match4.length; r++) {
            initializeVar(match4[r].substring(0, match4[r].length));
        }
    }

    var varNames = [];
    for (var key in variables) {
        if (token.indexOf(key) !== -1) {
            var regex1 = '([^a-zA-Z_])(' + key + ')([^a-zA-Z_])';
            var reg = new RegExp(regex1, 'g');
            token = token.replace(reg, '$1' + variables[key] + '$3');
            var regex2 = '(^' + key + ')([^a-zA-Z_])';
            var reg2 = new RegExp(regex2, 'g');
            token = token.replace(reg2, variables[key] + '$2');
            var regex3 = '([^a-zA-Z_])(' + key + ')$';
            var reg3 = new RegExp(regex3, 'g');
            token = token.replace(reg3, '$1' + variables[key]);
            var reg4 = new RegExp('^' + key + '$', 'g');
            token = token.replace(reg4, variables[key]);
        }
    }
    return token;
}

function matchParenthese(token, index) {
    var pStack = [];
    for (var cursor = index + 1; cursor < token.length; cursor++) {
        if (token.charAt(cursor) === '(') {
            pStack.push(1);
        }
        if (token.charAt(cursor) === ')') {
            if (pStack.length > 0) {
                pStack.pop();
            } else {
                return cursor;
            }
        }
    }
    return index;
}

function returnValue(identifyer, token, toDoFunction) { //note: do NOT include parentheses in identifyer
    for (var cursor = 0; cursor < token.length; cursor++) {
        if (token.length > cursor + identifyer.length) {
            if (token.substring(cursor, cursor + identifyer.length) === identifyer) {
                if (cursor === 0 || /^[^a-zA-Z_]/.test(token.charAt(cursor - 1)) === true) {
                    if (nextNonWhiteChar(token, cursor + identifyer.length - 1) === '(') {
                        print(identifyer);
                        var nextParen = matchParenthese(token, cursor + identifyer.length + 1);
                        var inner = token.substring(cursor + identifyer.length + 1, nextParen);
                        inner = replaceVars(inner);
                        var value = eval(inner);
                        value = toDoFunction(value);
                        return token.substring(0, cursor) + value + token.substring(nextParen + 1, token.length);
                    }
                }
            }
        }

    }
    return null;
}

function nextNonWhiteChar(token, index) { //give non-white character
    for (var i = index + 1; i < token.length; i++) {
        if (token.charAt(i) !== ' ') {
            return token.charAt(i);
        }
    }
}
function clearPixels(){
    var canvas = document.getElementById('canvas');
    canvas.getContext('2d').fillStyle = '#fff';
    canvas.getContext('2d').fillRect(0,0,canvas.width,canvas.height);
    for(var x=0;x<96;x++){
        for(var y=0;y<64;y++){
            pixels[(x,y)] = 0;
        }
    }
}
function stop(){
    running = false;
    clearInterval(lineProcessing);
}
function initializeVar(name) {
    if (!(name in variables) && name !== 'L1' && name !== 'L2' && name !== 'L3' && name !== 'L4' && name !== 'L5' && name !== 'L6') {
        variables[name] = Math.random() * 100;
    }
}

function clear() {
    document.getElementById('output').value = '';
    document.getElementById('error').value = '';
}

function printE(str) {
    document.getElementById('error').value += str + '\n'
}

function print(str) {
    document.getElementById('output').value += str + '\n';
}
<h1>Ti-Basic Interpreter</h1>


<h3>Code</h3>

<textarea id='code-block' cols='50' rows='7' oninput='inputChanged()'>:clrdraw
:for(a,2,96,2)
:for(b,(a/2)%2,64,2)
:pxl-on(a,b)
:end
:end</textarea>
<br>
<button width='20' height='10' onclick='run()'>Run</button>
    <button width='20' height='10' onclick='stop()'>Stop</button>

<h3>Output (also input)</h3>

    <textarea id='output' cols='50' rows='7' onkeypress='onUserInput(event)'></textarea>
<br>
    <canvas id='canvas' width='192' height='128'></canvas>
<br>

<textarea id='error' cols='50' rows='7'></textarea>


per quanto riguarda prima il pensiero javascript e poi la visualizzazione, il browser funziona in un singolo thread. il rendering degli oggetti DOM (la pagina Web effettiva) avviene su questo stesso thread, quindi fino a quando il codice non esegue l'esecuzione, la pagina non verrà aggiornata. il modo per risolverlo è utilizzare la funzione setTimeout ( w3schools.com/jsref/met_win_settimeout.asp ) per produrre in modo che il browser possa eseguire il rendering dell'aggiornamento, quindi continuare il processo
pseudonym117

1
Sto facendo cose con questo codice! Ho trovato un errore: On line ~ 93, hai lineProcessing.clearInterval();; questo invece dovrebbe essere clearInterval(lineProcessing);.
Conor O'Brien,

@ CᴏɴᴏʀO'Bʀɪᴇɴ Sentiti libero di modificarlo e cambiarlo. È da un po 'che non guardo questo codice. Inoltre, sono un po 'sommerso dal lavoro scolastico in questo momento, quindi potrebbe volerci un po' prima che cambi qualcosa.
Stretch Maniac,

3
@StretchManiac Ah, ok. Capisco - procrastinare ATM ^ _ ^
Conor O'Brien,

26

Brainfuck

Ecco un interprete BF di base. Non c'è debugger però, ma ha un paio di opzioni di personalizzazione.

const NUM_CELLS = 30000;
const ITERS_PER_SEC = 100000;
const TIMEOUT_MILLISECS = 5000;
const ERROR_BRACKET = "Mismatched brackets";
const ERROR_TIMEOUT = "Timeout";
const ERROR_INTERRUPT = "Interrupted by user";

var code, input, wrap, timeout, eof, loop_stack, loop_map;
var running, start_time, code_ptr, input_ptr, cell_ptr, cells, iterations;

function clear_output() {
  document.getElementById("output").value = "";
  document.getElementById("stderr").innerHTML = "";
}

function stop() {
  running = false;
  document.getElementById("run").disabled = false;
  document.getElementById("stop").disabled = true;
  document.getElementById("clear").disabled = false;
  document.getElementById("wrap").disabled = false;
  document.getElementById("timeout").disabled = false;
  document.getElementById("eof").disabled = false;
}

function interrupt() {
  error(ERROR_INTERRUPT);
}

function error(msg) {
  document.getElementById("stderr").innerHTML = msg;
  stop();
}

function run() {
  clear_output();
  
  document.getElementById("run").disabled = true;
  document.getElementById("stop").disabled = false;
  document.getElementById("clear").disabled = true;
  document.getElementById("wrap").disabled = true;
  document.getElementById("timeout").disabled = true;
  document.getElementById("eof").disabled = true;

  code = document.getElementById("code").value;
  input = document.getElementById("input").value;
  wrap = document.getElementById("wrap").value;
  timeout = document.getElementById("timeout").checked;
  eof = document.getElementById("eof").value;

  loop_stack = [];
  loop_map = {};

  for (var i = 0; i < code.length; ++i) {
    if (code[i] == "[") {
      loop_stack.push(i);

    } else if (code[i] == "]") {
      if (loop_stack.length == 0) {
        error(ERROR_BRACKET);
        return;

      } else {
        var last_bracket = loop_stack.pop();
        loop_map[last_bracket] = i;
        loop_map[i] = last_bracket;
      }
    }
  }

  if (loop_stack.length > 0) {
    error(ERROR_BRACKET);
    return;
  }

  running = true;
  start_time = Date.now();
  code_ptr = 0;
  input_ptr = 0;
  cell_ptr = Math.floor(NUM_CELLS / 2);
  cells = {};
  iterations = 0;

  bf_iter(1);
}

function bf_iter(niters) {
  if (code_ptr >= code.length || !running) {
    stop();
    return;
  }

  var iter_start_time = Date.now();

  for (var i = 0; i < niters; ++i) {
    if (cells[cell_ptr] == undefined) {
      cells[cell_ptr] = 0;
    }

    switch (code[code_ptr]) {
      case "+":
        if ((wrap == "8" && cells[cell_ptr] == 255) ||
            (wrap == "16" && cells[cell_ptr] == 65535) || 
            (wrap == "32" && cells[cell_ptr] == 2147483647)) {
            cells[cell_ptr] = 0;
        } else {
          cells[cell_ptr]++;
        }
        break;
        
      case "-":
        if (cells[cell_ptr] == 0 && wrap != "-1"){
          if (wrap == "8"){ cells[cell_ptr] = 255 }
          if (wrap == "16"){ cells[cell_ptr] = 65535 }
          if (wrap == "32"){ cells[cell_ptr] = 2147483647 }    
        } else {
          cells[cell_ptr]--;
        }
        break;
      
      case "<": cell_ptr--; break;
      case ">": cell_ptr++; break;

      case ".":
        document.getElementById("output").value += String.fromCharCode(cells[cell_ptr]);
        break;

      case ",":
        if (input_ptr >= input.length) {
          if (eof != "nochange") {
            cells[cell_ptr] = parseInt(eof);
          }
        } else {
          cells[cell_ptr] = input.charCodeAt(input_ptr);
          input_ptr++;
        }
        break;

      case "[":
        if (cells[cell_ptr] == 0) {
          code_ptr = loop_map[code_ptr];
        }
        break;

      case "]":
        if (cells[cell_ptr] != 0) {
          code_ptr = loop_map[code_ptr];
        }
        break;
    }

    code_ptr++;
    iterations++;

    if (timeout && Date.now() - start_time > TIMEOUT_MILLISECS) {
      error(ERROR_TIMEOUT);
      return;
    }
  }

  setTimeout(function() { bf_iter(ITERS_PER_SEC * (Date.now() - iter_start_time)/1000) }, 0);
}
<div style="font-size:12px;font-family:Verdana, Geneva, sans-serif;">
  <div style="float:left; width:50%;">
    Code:
    <br>
    <textarea id="code" rows="4" style="overflow:scroll;overflow-x:hidden;width:90%;">>++++++++[<+++++++++>-]<.>>+>+>++>[-]+<[>[->+<<++++>]<<]>.+++++++..+++.>>+++++++.<<<[[-]<[-]>]<+++++++++++++++.>>.+++.------.--------.>>+.>++++.</textarea>
    <br>Input:
    <br>
    <textarea id="input" rows="2" style="overflow:scroll;overflow-x:hidden;width:90%;"></textarea>
    <p>
      Wrap:
      <select id="wrap">
        <option value="8">8-bit</option>
        <option value="16">16-bit</option>
        <option value="32">32-bit</option>
        <option value="-1">None</option>
      </select>
      &nbsp;
      Timeout:
      <input id="timeout" type="checkbox" checked="true" />&nbsp; EOF:
      <select id="eof">
        <option value="nochange">Same</option>
        <option value="0">0</option>
        <option value="-1">-1</option>
      </select>
    </p>
  </div>
  <div style="float:left; width:50%;">
    Output:
    <br>
    <textarea id="output" rows="6" style="overflow:scroll;width:90%;"></textarea>
    <p>
      <input id="run" type="button" value="Run" onclick="run()" />
      <input id="stop" type="button" value="Stop" onclick="interrupt()" disabled="true" />
      <input id="clear" type="button" value="Clear" onclick="clear_output()" />
      &nbsp;
      <span id="stderr" style="color:red"></span>
    </p>
  </div>
</div>

Nel mio browser tutto è contenuto nello snippet espanso, ma non sono un esperto di compatibilità del browser, quindi non posso garantire che sarà lo stesso per tutti.

Caratteristiche

  • È possibile configurare il wrapping delle celle e il comportamento EOF
  • Il timeout può essere bypassato
  • Il programma può essere interrotto a metà dell'esecuzione
  • Un bel pulsante chiaro
  • Tutto questo all'interno della casella Stack Snippet (o almeno ci ho provato) e con un clock di circa 6k caratteri non convertito

Ecco un programma cat da testare: ,.[>,.]( attenzione : non provare con testi di grandi dimensioni!). Ma questo codice funziona GRANDE !.
Ismael Miguel,

@IsmaelMiguel Che dire di +[,.]:)
vedi

1
@IsmaelMiguel Personalmente preferisco non spostare il puntatore all'interno del loop in modo che le persone non si accorgano che il nastro è delimitato dalla dimensione intera di Javascript: P
Sp3000

1
@ Sp3000 Bene, se riesci a leggere la lunghezza del testo, puoi essere sicuro che il codice funzionerà correttamente. Se riesci a ottenere un testo la cui lunghezza è 0xFFFFFFFFFFFFFFFF e il mio codice "muore", dai una medaglia a Sieg.
Ismael Miguel,

1
Ti suggerisco di usare una scorciatoia per la document.getElementById()funzione.
AL

21

Marbelous *

Questo interprete è probabilmente pieno di bug; se ne trovi qualcuno, fammi sapere.

Questo supporta tutte le funzionalità di Marbelous tranne #include . C'è anche un'opzione per l'uso di una tavola cilindrica (i marmi spinti dai lati della tavola riappaiono sull'altro lato).

L'interprete viene inoltre fornito con molte schede presenti negli esempi nel repository per l'interprete Python per Marbelous . Queste schede sono elencate di seguito:

dec_out.mbl - Dp, Decout
hex_out.mbl - Hp, Hexo
fourwayincrement.mbl - Fwin
threewaysplit.mbl - 3W
bitwise_operations.mbl - Bitx, Bdif, Borr, Band, Bxor, Bnor
logical_operations.mbl - Tf, Nt, Lorr, Land, Lnor, Lxor, Cmpr, Eqal, Gteq, Lteq, Grtr, Less, Sort
replace_input.mbl - Replac
adder.mbl - Plus
arithmetic.mbl - Subt, Subo, Subful, Addo, Addful, Mult
wide_devices.mbl - Wideadditionfunc, Widesubtractfunc, Wbitleft, Wbitrght, Wbitfetchx, Mulx, Doblmult, Widemultiplyfunc

Non includere dovrebbe essere utilizzato. Vedi il repository dell'interprete Python per i dettagli su ciò che ciascuna di queste schede fa.

* Ulteriori informazioni su Marbelous:

Nota: l'uscita grafica (256x256 con doppio buffer con colore RGB a 24 bit) è disponibile su questo interprete. A tale scopo possono essere utilizzate le seguenti schede:

{}{}{}{}{} - Set Pixel for Back Buffer (}0 - x, }1 - y, }2 - red, }3 - green, }4 - blue)
>< - Swap Buffers and Clear Back Buffer (}0 - anything)
@f@f@f - Get Pixel from Front Buffer (}0 - x, }1 - y, {0 - red, {1 - green, {2 - blue)
@b@b@b - Get Pixel from Back Buffer (}0 - x, }1 - y, {0 - red, {1 - green, {2 - blue)

Notare che il segno di Use Draw Buffersspunta (richiesto per l'output grafico) potrebbe rallentare l'interprete e che l'output grafico è lento.

Aggiornamento : modificati i buffer per utilizzare canvas anziché div 1 x 1 pixel; il disegno dovrebbe essere molto più veloce ora.

var stdin = "";
var boards = {};
var bnames = [];
var max_tick = 1000;
var space_as_blank = false;
var cylindrical_board = false;
var print_numbers = false;
var libraries = true;
var stopped = false;
var gfx = false;
var front_buffer = null;
var back_buffer = null;
function base36(a){	return a.toString(36).toUpperCase();}
function base16(a){	return ("0"+a.toString(16).toUpperCase()).substr(-2);}
function wto16(arr, i){ return arr[i] << 8 | arr[i+1]; }
function wto32(arr, i){ return arr[i] << 24 | arr[i+1] << 16 | arr[i+2] << 8 | arr[i+3]; }
function getch(){
var p = stdin.substr(0, 1);
stdin = stdin.substr(1);
if(p === '') return -1;
else return p.charCodeAt(0) & 255;
}
function putch(obj, ch){
if(print_numbers)
	obj.stdout += ch + ' ';
else
	obj.stdout += String.fromCharCode(ch);
}
function longestMatch(search, list){
var best = null, blen = 0;
for(var i = 0, len = list.length; i < len; ++i)
	if(list[i].length > blen && search.indexOf(list[i]) === 0)
		best = list[i], blen = best.length;
return best;
}
function swapBuffers(){
front_buffer.ctx.drawImage(back_buffer.canvas, 0, 0);
back_buffer.clear();
}

function jsBoard(name, inc, outc, code){
var f = eval('(function(inp, self){return ' + code + ';})');
boards[name] = new Board(name, true, f, inc, outc);
bnames.push(name);
}
function loadDefaultBoards(){
// implement \\ // /\ \/ ++ -- >> << ~~ ]] +n -n ?? ?n ^n =n >n <n as js boards
jsBoard('\\\\', 1, 0, '{37: inp[0]}');
jsBoard('//', 1, 0, '{36: inp[0]}');
jsBoard('/\\', 1, 0, '{36: inp[0], 37: inp[0]}');
jsBoard('\\/', 1, 0, '{}');
jsBoard('++', 1, 1, '{0: (inp[0]+1)&255}');
jsBoard('--', 1, 1, '{0: (inp[0]+255)&255}');
jsBoard('>>', 1, 1, '{0: inp[0]>>1}');
jsBoard('<<', 1, 1, '{0: (inp[0]<<1)&255}');
jsBoard('~~', 1, 1, '{0: (~inp[0])&255}');
jsBoard(']]', 1, 1, '(c=getch())>-1?{0:c}:{37:inp[0]}');
jsBoard('??', 1, 1, '{0: Math.floor(Math.random()*(inp[0]+1))}');
for(var i = 0; i < 36; ++i){
	j = base36(i);
	jsBoard('+'+j, 1, 1, '{0: (inp[0]+'+i+')&255}');
	jsBoard('-'+j, 1, 1, '{0: (inp[0]-'+i+')&255}');
	jsBoard('?'+j, 1, 1, '{0: Math.floor(Math.random()*'+(i+1)+')}');
	jsBoard('='+j, 1, 1, 'inp[0]=='+i+'?{0: inp[0]}:{37: inp[0]}');
	jsBoard('>'+j, 1, 1, 'inp[0]>'+i+'?{0: inp[0]}:{37: inp[0]}');
	jsBoard('<'+j, 1, 1, 'inp[0]<'+i+'?{0: inp[0]}:{37: inp[0]}');
	if(i < 8){
		jsBoard('^'+j, 1, 1, '{0: !!(inp[0]&(1<<'+i+'))}');
	}
}
if(gfx){
	jsBoard('{}{}{}{}{}', 5, 0, 'back_buffer.set(inp[0], inp[1], inp[2], inp[3], inp[4]),{}');
	jsBoard('@f@f@f', 2, 3, 'front_buffer.get(inp[0], inp[1])');
	jsBoard('@b@b@b', 2, 3, 'back_buffer.get(inp[0], inp[1])');
	jsBoard('><', 1, 0, 'swapBuffers(), {}');
}
if(libraries){
	// dec_out.mbl - Dp, Decout
	jsBoard('Dp', 1, 0, 'putch(self,Math.floor(inp[0]/100)+0x30),putch(self,Math.floor(inp[0]/10)%10+0x30),putch(self,inp[0]%10+0x30),{}');
	jsBoard('Decout', 1, 3, '{0: inp[0]/100, 1: inp[0]/10%10, 2: inp[0]%10}');
	// hex_out.mbl - Hp, Hexo
	jsBoard('Hp', 1, 0, 's=base16(inp[0]),putch(self,s.charCodeAt(0)),putch(self,s.charCodeAt(1)),{}');
	jsBoard('Hexo', 1, 2, 's=base16(inp[0]),{0: s.charCodeAt(0), 1: s.charCodeAt(1)}');
	// fourwayincrement.mbl - Fwin
	jsBoard('Fwin', 1, 2, '{36: inp[0], 0: (inp[0]+1)&255, 1: (inp[0]+1)&255, 37: (inp[0]+2)&255}');
	// threewaysplit.mbl - 3W
	jsBoard('3W', 1, 1, '{0: inp[0], 36: inp[0], 37: inp[0]}');
	// bitwise_operations.mbl - Bitx, Bdif, Borr, Band, Bxor, Bnor
	jsBoard('Bitx', 2, 1, 'inp[1]<8?{0: !!(inp[0] & (1 << inp[1]))}:{}');
	jsBoard('Bdif', 2, 1, 'b=inp[0]^inp[1],{0: !!(b&1)+!!(b&2)+!!(b&4)+!!(b&8)+!!(b&16)+!!(b&32)+!!(b&64)+!!(b&128)}');
	jsBoard('Borr', 2, 1, '{0: inp[0]|inp[1]}');
	jsBoard('Band', 2, 1, '{0: inp[0]&inp[1]}');
	jsBoard('Bxor', 2, 1, '{0: inp[0]^inp[1]}');
	jsBoard('Bnor', 2, 1, '{0: ~(inp[0]|inp[1])}');
	// logical_operations.mbl - Tf, Nt, Lorr, Land, Lnor, Lxor, Cmpr, Eqal, Gteq, Lteq, Grtr, Less, Sort
	jsBoard('Tf', 1, 1, '{0: (inp[0]>0)|0}');
	jsBoard('Nt', 1, 1, '{0: (!inp[0])|0}');
	jsBoard('Lorr', 2, 1, '{0: (inp[0]||inp[1])|0}');
	jsBoard('Land', 2, 1, '{0: (inp[0]&&inp[1])|0}');
	jsBoard('Lnor', 2, 1, '{0: !(inp[0]||inp[1])|0}');
	jsBoard('Lxor', 2, 1, '{0: (!inp[0]!=!inp[1])|0}');
	jsBoard('Cmpr', 2, 1, '{0: inp[0]>inp[1]?1:inp[0]<inp[1]?-1:0}');
	jsBoard('Eqal', 2, 1, '{0: (inp[0] == inp[1])|0}');
	jsBoard('Gteq', 2, 1, '{0: (inp[0] >= inp[1])|0}');
	jsBoard('Lteq', 2, 1, '{0: (inp[0] <= inp[1])|0}');
	jsBoard('Grtr', 2, 1, '{0: (inp[0] > inp[1])|0}');
	jsBoard('Less', 2, 1, '{0: (inp[0] < inp[1])|0}');
	jsBoard('Sort', 2, 2, '{0: Math.min(inp[0],inp[1]), 1: Math.max(inp[0],inp[1])}');
	// replace_input.mbl - Replac
	jsBoard('Replac', 3, 1, '{0: inp[0]==inp[1]?inp[2]:inp[0]}');
	// adder.mbl - Plus
	jsBoard('Plus', 2, 1, '{0: (inp[0] + inp[1])&255}');
	// arithmetic.mbl - Subt, Subo, Subful, Addo, Addful, Mult
	jsBoard('Subt', 2, 1, '{0: (inp[0] - inp[1])&255}');
	jsBoard('Subo', 2, 1, '{0: (inp[0] - inp[1])&255, 36: (inp[0] < inp[1])|0}');
	jsBoard('Subful', 3, 1, 'a=(inp[0] - inp[1])&255,{0: (a + 256 - inp[2])&255, 36: (inp[0]<inp[1])+(a<inp[2])}');
	jsBoard('Addo', 2, 1, 'a=inp[0]+inp[1],{0: a&255, 36: (a>255)|0}');
	jsBoard('Addful', 3, 1, 'a=inp[0]+inp[1]+inp[2],{0: a&255, 36: (a>255)|0}');
	jsBoard('Mult', 2, 1, '{0: (inp[0]*inp[1])&255}');
	// wide_devices.mbl - Wideadditionfunc, Widesubtractfunc, Wbitleft, Wbitrght, Wbitfetchx, Mulx, Doblmult, Widemultiplyfunc
	jsBoard('Wideadditionfunc', 8, 4, 'c=(wto32(inp,0)+wto32(inp,4))&0xFFFFFFFF,{0:  (c&0xFF000000)>>>24, 1: (c&0x00FF0000)>>>16, 2: (c&0x0000FF00)>>>8, 3: (c&0x000000FF)}');
	jsBoard('Widesubtractfunc', 8, 4, 'c=(wto32(inp,0)-wto32(inp,4))&0xFFFFFFFF,{0: (c&0xFF000000)>>>24, 1: (c&0x00FF0000)>>>16, 2: (c&0x0000FF00)>>>8, 3: (c&0x000000FF)}');
	jsBoard('Wbitleft', 4, 4, 'c=(wto32(inp,0)<<1)&0xFFFFFFFF,{0: (c&0xFF000000)>>>24, 1: (c&0x00FF0000)>>>16, 2: (c&0x0000FF00)>>>8, 3: (c&0x000000FF)}');
	jsBoard('Wbitrght', 4, 4, 'c=wto32(inp,0)>>>1,{0: (c&0xFF000000)>>>24, 1: (c&0x00FF0000)>>>16, 2: (c&0x0000FF00)>>>8, 3: (c&0x000000FF)}');
	jsBoard('Wbitfetchx', 5, 1, 'inp[4]<32?{0:!!(wto32(inp,0)&(1<<inp[4]))}:{}');
	jsBoard('Mulx', 2, 2, 'c=(inp[0]*inp[1])&0xFFFF,{0: (c&0xFF00)>>>8, 1: (c&0x00FF)}');
	jsBoard('Doblmult', 4, 4, 'c=(wto16(inp,0)*wto16(inp,2))&0xFFFFFFFF,{0: (c&0xFF000000)>>>24, 1: (c&0x00FF0000)>>>16, 2: (c&0x0000FF00)>>>8, 3: (c&0x000000FF)}');
	jsBoard('Widemultiplyfunc', 8, 4, 'c=(wto32(inp,0)*wto32(inp,4))&0xFFFFFFFF,{0: (c&0xFF000000)>>>24, 1: (c&0x00FF0000)>>>16, 2: (c&0x0000FF00)>>>8, 3: (c&0x000000FF)}');
}
}
// most devices are implemented as js subboards
var CTypes = {
PORTAL:			1,
SYNCHRONISER:	2,
INPUT:			3,
OUTPUT:			4,
TERMINATE:		5,
SUBROUTINE:		6,
LITERAL:		7,
};
function Cell(type,value){
this.type = type;
this.value = value;
}
Cell.prototype.copy = function(other){
this.type = other.type;
this.value = other.value;
};
function Board(name, js, jsref, jsinc, jsoutc){
this.name = name;
this.stdout = "";
if(!js){
	this.cells = [];
	this.marbles = [];
	this.cols = 0;
	this.rows = 0;
	this.inputs = [];
	this.outputs = [];
	this.syncs = [];
	this.portals = [];
	this.terminators = [];
	for(var i = 0; i < 36; ++i){
		this.inputs[i] = [];
		this.outputs[i] = [];
		this.syncs[i] = [];
		this.portals[i] = [];
	}
	this.outputs[36] = []; // {<
	this.outputs[37] = []; // {>
	this.subroutines = []; // [r0,c0,board name,size,inputs,outputs]
	this.type = 0;
	this.inc = 0; 
	this.outc = 0;
}else{
	this.func = jsref;
	this.inc = jsinc;
	this.outc = jsoutc;
	this.type = 1;
}
}
Board.prototype.set = function(row,col,cell){
if(row >= this.rows){
	for(var r = this.rows; r <= row; ++r){
		this.cells[r] = [];
		this.marbles[r] = [];
	}
}
this.rows = Math.max(this.rows, row + 1);
this.cols = Math.max(this.cols, col + 1);
if(!cell){
	this.cells[row][col] = null;
	return;
}
if(!this.cells[row][col])
	this.cells[row][col] = new Cell;
this.cells[row][col].copy(cell);
if(cell.type == CTypes.LITERAL){
	this.marbles[row][col] = cell.value;
}else{
	this.marbles[row][col] = null;
}
};
Board.prototype.get = function(r,c){
return this.cells[r][c];
};
Board.prototype.init = function(){
if(this.type == 0){
	var maxin = 0, maxout = 0;
	for(var r = 0; r < this.rows; ++r){
		for(var c = 0; c < this.cols; ++c){
			if(this.cells[r][c] == null) continue;
			switch(this.cells[r][c].type){
				case CTypes.PORTAL:
					this.portals[this.cells[r][c].value].push([r,c]);
				break;
				case CTypes.SYNCHRONISER:
					this.syncs[this.cells[r][c].value].push([r,c]);
				break;
				case CTypes.INPUT:
					this.inputs[this.cells[r][c].value].push([r,c]);
					maxin = Math.max(this.cells[r][c].value + 1, maxin);
				break;
				case CTypes.OUTPUT:
					if(this.cells[r][c].value != '<' && this.cells[r][c].value != '>'){
						this.outputs[this.cells[r][c].value].push([r,c]);
						maxout = Math.max(this.cells[r][c].value + 1, maxout);
					}else{
						this.outputs[this.cells[r][c].value == '<' ? 36 : 37].push([r,c]);
					}
				break;
				case CTypes.TERMINATE:
					this.terminators.push([r,c]);
				break;
			}
		}
	}
	this.inc = maxin;
	this.outc = maxout;
}
var namelen = Math.max(1, this.inc, this.outc) * 2;
this.name = new Array(namelen + 1).join(this.name).substr(0, namelen);
};
Board.prototype.validateSubr = function(names){
if(this.type == 1) return;
for(var r = 0, len = this.cells.length; r < len; ++r){
	var str = "", start = -1;
	for(var c = 0, rlen = this.cells[r].length; c < rlen; ++c){
		if(this.cells[r][c] && this.cells[r][c].type == CTypes.SUBROUTINE){
			if(start == -1) start = c;
			str += this.cells[r][c].value;
		}else if(start != -1){
			var match;
			while(str.length && (match = longestMatch(str, names))){
				var slen = match.length / 2;
				this.subroutines.push([r,start,match,slen,boards[match].inc,boards[match].outc]);
				start += slen;
				str = str.substr(slen * 2); 
			}
			if(str.length){
				throw "No subboard could be found near `" + str + "`";
			}
			start = -1;
			str = "";
		}
	}
	var match;
	while(str.length && (match = longestMatch(str, names))){
		var slen = match.length / 2;
		this.subroutines.push([r,start,match,slen,boards[match].inc,boards[match].outc]);
		start += slen;
		str = str.substr(slen * 2);
	}
	if(str.length){
		throw "No subboard could be found near `" + str + "`";
	}
}
};
Board.prototype.runCopy = function(inp){
var b = new Board('');
b.type = 2;
b.ref = this;
b.tickNum = 0;
if(this.type == 0){
	for(var r = 0, rlen = this.marbles.length; r < rlen; ++r){
		b.marbles[r] = [];
		for(var c = 0, clen = this.marbles[r].length; c < clen; ++c){
			b.marbles[r][c] = this.marbles[r][c]; 
		}
	}
	for(var i = 0; i < this.inc; ++i){
		if(inp[i] != null){
			var k = this.inputs[i];
			for(var j = 0, l = k.length; j < l; ++j){
				b.marbles[k[j][0]][k[j][1]] = ((parseInt(inp[i])&255)+256)&255;
			}
		}
	}
	b.cols = this.cols;
	b.rows = this.rows;
	b.inc = this.inc;
	b.outc = this.outc;
	b.stdout = "";
}else{
	b.inp = inp;
}
return b;
};
Board.prototype.tick = function(){
if(this.type != 2) throw "Calling Board.tick without Board.runCopy";
if(this.tickNum == -1) throw "Copied board has already run to completion";

if(this.ref.type == 1){
	this.tickNum = -1;
	this.outp = this.ref.func(this.inp, this);
	return moved;
}

var moved = false;

var new_marbles = [];
for(var r = 0; r <= this.rows; ++r) 
	new_marbles[r] = [];

// subroutines
for(var i = 0, len = this.ref.subroutines.length; i < len; ++i){
	var r = this.ref.subroutines[i][0], c = this.ref.subroutines[i][1], 
		name = this.ref.subroutines[i][2], sz = this.ref.subroutines[i][3],
		inc = this.ref.subroutines[i][4], outc = this.ref.subroutines[i][5];
	var all = true, inp = [];
	for(var j = 0; j < inc; ++j){
		if(this.marbles[r][c+j] == null && (boards[name].type == 1 || boards[name].inputs[j].length > 0)){
			all = false; break;
		}else{
			inp[j] = this.marbles[r][c+j];
		}
	}
	if(all){
		var cb = boards[name].runCopy(inp);
		while(cb.tickNum != -1 && cb.tickNum < max_tick) cb.tick();
		if(cb.tickNum != -1) throw "Max tick count exceeded running board `" + name + "`";
		var outp = cb.out();
		if(cb.stdout != "") moved = true;
		for(var j = 0; j < outc; ++j){
			if(outp[j] != null){
				new_marbles[r+1][c+j] = ((new_marbles[r+1][c+j]||0)+(outp[j]))&255;
				moved = true;
			}
		}
		if(outp[36] != null){ // left
			var left = c-1;
			if(left < 0 && cylindrical_board){
				left = this.cols - 1;
			}
			if(left >= 0){
				new_marbles[r][left] = ((new_marbles[r][left]||0)+(outp[36]))&255;
				moved = true;
			}
		}
		if(outp[37] != null){ // right
			var right = c+sz;
			if(right >= this.cols && cylindrical_board){
				right = 0;
			}
			if(right < this.cols){
				new_marbles[r][right] = ((new_marbles[r][right]||0)+(outp[37]))&255;
				moved = true;
			}
		}
		this.stdout += cb.stdout;
	}else{
		for(var j = 0; j < inc; ++j){
			if(this.marbles[r][c+j] != null){
				new_marbles[r][c+j] = ((new_marbles[r][c+j]||0)+(this.marbles[r][c+j]))&255;
			}					
		}
	}
}

// synchronisers
for(var i = 0; i < 36; ++i){
	if(this.ref.syncs[i].length){
		var all = true;
		for(var j = 0, len = this.ref.syncs[i].length; j < len; ++j){
			if(this.marbles[this.ref.syncs[i][j][0]][this.ref.syncs[i][j][1]] == null){
				all = false; break;
			}
		}
		if(all){
			for(var j = 0, len = this.ref.syncs[i].length; j < len; ++j){
				var r = this.ref.syncs[i][j][0];
				var c = this.ref.syncs[i][j][1];
				new_marbles[r+1][c] = this.marbles[r][c];
				moved = true;
			}
		}else{
			for(var j = 0, len = this.ref.syncs[i].length; j < len; ++j){
				var r = this.ref.syncs[i][j][0], c = this.ref.syncs[i][j][1];
				if(this.marbles[r][c] != null){
					new_marbles[r][c] = ((new_marbles[r][c]||0)+( this.marbles[r][c]))&255;
				}
			}
		}
	}
}

// input literal null move, output does not
for(var r = 0; r < this.rows; ++r){
	for(var c = 0; c < this.cols; ++c){
		if(this.marbles[r][c] != null){
			var type = this.ref.cells[r][c] && this.ref.cells[r][c].type;
			if(!type || type == CTypes.INPUT || type == CTypes.LITERAL){
				new_marbles[r+1][c] = ((new_marbles[r+1][c]||0)+(this.marbles[r][c]))&255;
				moved = true;
			}else if(type == CTypes.OUTPUT){
				new_marbles[r][c] = ((new_marbles[r][c]||0)+(this.marbles[r][c]))&255;
			}
		}
	}
}	

// shift portal
for(var i = 0; i < 36; ++i){
	if(this.ref.portals[i].length){
		var p = this.ref.portals[i];
		if(p.length == 1){
			var r = p[0][0], c = p[0][1];
			if(this.marbles[r][c] != null){
				new_marbles[r+1][c] = ((new_marbles[r+1][c]||0)+( this.marbles[r][c]))&255;
				moved = true;
			}
		}else{
			var q = [];
			for(var j = 0, l = p.length; j < l; ++j){
				if(this.marbles[p[j][0]][p[j][1]] != null){
					// generate output portal - any other portal except the input
					var toWhere = Math.floor(Math.random() * (l-1));
					if(toWhere >= j) ++toWhere;
					var r = p[j][0], c = p[j][1];
					q[toWhere] = ((q[toWhere]||0)+(this.marbles[r][c]))&255;
					moved = true;
				}
			}
			for(var j = 0, l = p.length; j < l; ++j){
				if(q[j] != null){
					var r = p[j][0] + 1, c = p[j][1];
					new_marbles[r][c] = q[j];
				}
			}
		}
	}
}

// check stdout
if(new_marbles[new_marbles.length-1].length){
	var r = this.rows;
	for(var i = 0, l = new_marbles[r].length; i < l; ++i){
		if(new_marbles[r][i] != null){
			putch(this, new_marbles[r][i]);
			moved = true;
		}
	}
}
new_marbles.splice(this.rows);

if(!moved){
	this.tickNum = -1;
	return moved;
}
this.marbles = new_marbles;
// check terminator
for(var i = 0, len = this.ref.terminators.length; i < len; ++i){
	var r = this.ref.terminators[i][0], c = this.ref.terminators[i][1];
	if(new_marbles[r][c] != null){
		this.tickNum = -1;
		return moved;
	}
}
// check output
if(this.outc){
	var allOuts = true;
	for(var i = 0; i < 38; ++i){
		var o = this.ref.outputs[i];
		if(o.length){
			var occupied = false;
			for(var j = 0, len = o.length; j < len; ++j){
				if(new_marbles[o[j][0]][o[j][1]] != null){
					occupied = true;
					break;
				}
			}
			if(!occupied){
				allOuts = false; break;
			}
		}
	}
	if(allOuts){
		this.tickNum = -1;
		return moved;
	}
}
++this.tickNum;
return moved;
};
Board.prototype.out = function(){
if(this.type != 2) throw "Calling Board.out without Board.runCopy";
if(this.tickNum != -1) throw "Copied board hasn't run to completion yet";
if(this.ref.type == 1) return this.outp;
var outp = {};
for(var i = 0; i < 38; ++i){
	if(this.ref.outputs[i].length){
		outp[i] = 0;
		var o = this.ref.outputs[i], isFilled = false;
		for(var j = 0, len = o.length; j < len; ++j){
			var r = o[j][0], c = o[j][1];
			isFilled = isFilled || this.marbles[r][c] != null;
			outp[i] = ((outp[i])+( this.marbles[r][c] || 0))&255;
		}
		if(!isFilled)
			outp[i] = null;
	}
}
return outp;
};

function DrawBuffer(canvas){
this.canvas = canvas;
this.ctx = this.canvas.getContext('2d');
this.ctx.fillStyle = 'rgb(0,0,0)';
this.ctx.fillRect(0, 0, 256, 256);
}

DrawBuffer.prototype.clear = function(){
this.ctx.fillStyle = 'rgb(0,0,0)';
this.ctx.fillRect(0, 0, 256, 256);
};
DrawBuffer.prototype.set = function(x, y, r, g, b){
this.ctx.fillStyle = 'rgb(' + r + ',' + g + ',' + b + ')';
this.ctx.fillRect(x, y, 1, 1);
};
DrawBuffer.prototype.get = function(x, y){
return this.ctx.getImageData(x, y, 1, 1).data.splice(0, 3);
};
// spaces: is an empty cell denoted with whitespace?
function parseMblSrc(src,spaces){
var lines = (':MB\n'+src).split('\n');
var sb = []; // start lines of new mb subboards
for(var i = lines.length; i-- > 0;){
	// strip mid-line spaces if possible
	if(!spaces){
		lines[i] = lines[i].trim();
		lines[i] = lines[i].replace(/\s/g,'');
	}
	// index of comment
	var o = lines[i].indexOf('#');
	// remove comments
	if(o > 0){
		lines[i] = lines[i].substr(0, o).trim();
	}else if(lines[i].length == 0 || o == 0){
		if(lines[i].indexOf('include') == 1){
			throw "#include not supported";
		}
		lines.splice(i, 1);
	}
}
for(var i = lines.length; i-- > 0;){
	// identify subboards
	if(lines[i].charAt(0) == ':'){
		sb.push(i);
	}
}
sb.sort(function(a,b){return a-b;});
var mbname = '';
for(var i = 0, len = sb.length; i < len; ++i){
	var name = lines[sb[i]].substr(1).trim();
	var board;
	board = new Board(name, false);
	var endl;
	if(i == len - 1) endl = lines.length;
	else endl = sb[i+1];
	for(var j = sb[i]+1; j < endl; ++j){
		var r = j - sb[i] - 1;
		if(lines[j].length % 2 != 0){
			throw "Error near `" + lines[j] + "`";
		}
		var cells = lines[j].match(/../g);
		for(var k = 0, clen = cells.length; k < clen; ++k){
			var val;
			if(val = cells[k].match(/^@([0-9A-Z])$/)){
				board.set(r, k, new Cell(CTypes.PORTAL, parseInt(val[1], 36)));
			}else if(val = cells[k].match(/^&([0-9A-Z])$/)){
				board.set(r, k, new Cell(CTypes.SYNCHRONISER, parseInt(val[1], 36)));
			}else if(val = cells[k].match(/^}([0-9A-Z])$/)){
				board.set(r, k, new Cell(CTypes.INPUT, parseInt(val[1], 36)));
			}else if(val = cells[k].match(/^{([0-9A-Z<>])$/)){
				var value;
				if(val[1] == '<' || val[1] == '>') value = val[1];
				else value = parseInt(val[1], 36);
				board.set(r, k, new Cell(CTypes.OUTPUT, value));
			}else if(cells[k] == '!!'){
				board.set(r, k, new Cell(CTypes.TERMINATE, 0));
			}else if(val = cells[k].match(/^[0-9A-F]{2}$/)){
				board.set(r, k, new Cell(CTypes.LITERAL, parseInt(cells[k], 16)));
			}else if(cells[k].match(/^[ \.]{2}$/)){
				board.set(r, k, null);
			}else{
				board.set(r, k, new Cell(CTypes.SUBROUTINE, cells[k]));
			}
		}
	}
	board.init();
	if(name == 'MB')
		mbname = board.name;
	name = board.name;
	bnames.push(name);
	boards[name] = board;
}
// validate and connect subr
for(var p in boards){
	boards[p].validateSubr(bnames);
}
return mbname;
}
function run(){
// normal init
stopped = false;
max_tick = document.getElementById('mb-ticks').value;
space_as_blank = document.getElementById('mb-spaces').checked;
cylindrical_board = document.getElementById('mb-cylinder').checked;
print_numbers = document.getElementById('mb-numprint').checked;
libraries = document.getElementById('mb-lib').checked;
gfx = document.getElementById('mb-gfx').checked;

src = document.getElementById('mb-src').value;
stdin = document.getElementById('mb-in').value;
boards = {};
bnames = [];
loadDefaultBoards();

if(gfx){
	// prepare draw buffers
	front_buffer = new DrawBuffer(document.getElementById('mb-fb'));
	back_buffer = new DrawBuffer(document.getElementById('mb-bb'));
}else{
	if(front_buffer){
		front_buffer.clear();
		back_buffer.clear();
		front_buffer = null;
		back_buffer = null;
	}
}
try{
	var mb = parseMblSrc(src, space_as_blank);
	var rc = boards[mb].runCopy(document.getElementById('mb-args').value.split(' '));
	var tmp = function(){
		try{
			if(stopped) throw "Board execution stopped.";
			else if(rc.tickNum != -1 && rc.tickNum < max_tick){
				rc.tick();
				document.getElementById('mb-out').value = rc.stdout;
				document.getElementById('mb-out').scrollTop = document.getElementById('mb-out').scrollHeight;
				setTimeout(tmp, 0);
			}else if(rc.tickNum == -1){
				document.getElementById('mb-out').value = rc.stdout;
				document.getElementById('mb-out').scrollTop = document.getElementById('mb-out').scrollHeight;
				document.getElementById('mb-return').value = rc.out()[0] || 0;
			}else throw "Max tick count exceeded running main board.";
		}catch(e){
			document.getElementById('mb-out').value = rc.stdout + '\n' + e;
			document.getElementById('mb-out').scrollTop = document.getElementById('mb-out').scrollHeight;
		}
	};
	setTimeout(tmp, 0);
}catch(e){
	document.getElementById('mb-out').value = (rc ? rc.stdout: '') + '\n' + e;
	document.getElementById('mb-out').scrollTop = document.getElementById('mb-out').scrollHeight;
}
}
function stop(){
stopped = true;
}
<div style="font-size: 12px;font-family: Helvetica, Arial, sans-serif;">
<div style="float: left;">
	Marbelous Source:<br />
	<textarea id="mb-src" rows="4" cols="35">48 65 6C 6C 6F 20 57 6F 72 6C 64 21</textarea><br />
	Arguments: <br />
	<input id="mb-args" size="33" /> <br />
	STDIN: <br />
	<textarea id="mb-in" rows="2" cols="35"></textarea><br />
	<span style="float: left">
		Max Ticks: <input id="mb-ticks" type="number" min="1" style="width: 60px" value="1000" />
	</span>
	<span style="float: right">
		<input type="button" onclick="run()" value="Run Code" style="" />
		<input type="button" onclick="stop()" value="Stop" style="" />
	</span>
</div>
<div style="float: left; margin-left: 15px;">
	<div style="margin-bottom: 10px">
		<input type="checkbox" id="mb-spaces" />Using spaces for blank cells<br />
		<input type="checkbox" id="mb-cylinder" />Cylindrical Board<br />
		<input type="checkbox" id="mb-numprint" />Display output as decimal numbers<br />
		<input type="checkbox" id="mb-lib" checked="true" />Include Libraries<br />
		<input type="checkbox" id="mb-gfx" />Use Draw Buffers<br />
	</div>
	<div>
		STDOUT:<br />
		<textarea id="mb-out" rows="3" cols="35"></textarea><br />
		Return Code: <input id="mb-return" />
	</div>
</div>
<div style="clear: both; text-align: center; width: 550px; padding-top: 10px;" id="mb-draw-buffers">
	<div style="float: left; width: 256px;">
		Front Buffer:
		<canvas style="height: 256px; width: 256px; background: black;" width="256" height="256" id="mb-fb"></canvas>
	</div>
	<div style="float: right; width: 256px;">
		Back Buffer:
		<canvas style="height: 256px; width: 256px; background: black;" width="256" height="256" id="mb-bb"></canvas>
	</div>
</div>
</div>

Alcuni semplici programmi da provare:

gatto (stampa stdin su stdout)

.. @0 ..
00 ]] \/
@0 /\ ..

rot13 (legge da stdin)

.. @0 ..
00 ]] \/
@0 /\ Rt
:Rt
}0 .. @0 .. }0 }0 }0 }0 }0
-W .. -W .. .. +D -D +D -D
-X .. >C &3 &0 &1 &2 &3 &4
>C &1 >P &4 {0 {0 {0 {0 {0
>P &2 &0 \/ .. .. .. .. ..
@0 \/ \/ .. .. .. .. .. ..

Demo di output grafico (imposta un pixel casuale su un colore casuale e quindi lancia il buffer)

FF FF FF FF FF 00
?? ?? ?? ?? ?? ..
{} {} {} {} {} ><

Questo è fantastico, sembra che le bacheche con nomi di una sola lettera non funzionino però.
overactor

@overactor che dovrebbe essere risolto ora
es1024

L'ultima demo dà un erroreError near FF FF FF FF FF 00
Khaled.K l'

17

JavaScript (risposta di esempio)

L'interpretazione di JavaScript tramite JavaScript è alquanto inutile, ma questo mostra come dovrebbero comportarsi i frammenti dell'interprete.

Ecco la versione bare bones, pensata per un rapido utilizzo in altri post:

BEGIN_CODE
// Put JavaScript code here
// it may be on multiple lines
END_CODE_BEGIN_INPUT
Put input here
it may be on multiple lines
END_INPUT
<!--Interpreter code:--><script>i=document.body.innerHTML;document.body.innerHTML=''</script><script>c=i.match(/BEGIN_CODE\n([\s\S]*)\nEND_CODE_BEGIN_INPUT/);c=c&&c.length>1?c[1]:'// Error reading code. Make sure it is on the lines between BEGIN_CODE and END_CODE_BEGIN_INPUT.';i=i.match(/END_CODE_BEGIN_INPUT\n([\s\S]*)\nEND_INPUT/);i=i&&i.length>1?i[1]:'Error reading input. Make sure it is on the lines between END_CODE_BEGIN_INPUT and END_INPUT.'</script>JavaScript:<br><tt>function(x) {</tt><br><textarea id='c'rows='4'cols='60'></textarea><br><tt>}</tt><br><br>Input string (variable x):<br><textarea id='i'rows='4'cols='60'></textarea><p><input type='button'value='Run'onclick='r()'></p>Output (return value):<br><textarea id='o'rows='4'cols='60'style='background-color:#f0f0f0;'></textarea><script>document.getElementById('c').value=c;document.getElementById('i').value=i;function r(){var r,c,i;r=c=i=null;eval('var f=function(x) {'+document.getElementById('c').value+'}');document.getElementById('o').value=String(f(document.getElementById('i').value))}</script>

Il Markdown grezzo per l'inclusione di questo frammento di stack in un'altra domanda o risposta è:

<!-- begin snippet: js hide: false -->
<!-- language: lang-html -->
BEGIN_CODE
// Put JavaScript code here
// it may be on multiple lines
END_CODE_BEGIN_INPUT
Put input here
it may be on multiple lines
END_INPUT
<!--Interpreter code:--><script>i=document.body.innerHTML;document.body.innerHTML=''</script><script>c=i.match(/BEGIN_CODE\n([\s\S]*)\nEND_CODE_BEGIN_INPUT/);c=c&&c.length>1?c[1]:'// Error reading code. Make sure it is on the lines between BEGIN_CODE and END_CODE_BEGIN_INPUT.';i=i.match(/END_CODE_BEGIN_INPUT\n([\s\S]*)\nEND_INPUT/);i=i&&i.length>1?i[1]:'Error reading input. Make sure it is on the lines between END_CODE_BEGIN_INPUT and END_INPUT.'</script>JavaScript:<br><tt>function(x) {</tt><br><textarea id='c'rows='4'cols='60'></textarea><br><tt>}</tt><br><br>Input string (variable x):<br><textarea id='i'rows='4'cols='60'></textarea><p><input type='button'value='Run'onclick='r()'></p>Output (return value):<br><textarea id='o'rows='4'cols='60'style='background-color:#f0f0f0;'></textarea><script>document.getElementById('c').value=c;document.getElementById('i').value=i;function r(){var r,c,i;r=c=i=null;eval('var f=function(x) {'+document.getElementById('c').value+'}');document.getElementById('o').value=String(f(document.getElementById('i').value))}</script>
<!-- end snippet -->

Per usarlo basta copiarlo in un nuovo post e inserire il codice sulle righe tra BEGIN_CODEe END_CODE_BEGIN_INPUTe il tuo input sulle righe tra END_CODE_BEGIN_INPUTe END_INPUT. L'interprete farà il resto. Si noti che nulla deve essere rientrato.

Direi che questa BEGIN...ENDtecnica è attualmente il modo migliore in cui dobbiamo scrivere questi interpreti in termini di facilità d'uso futuro perché ...

  • Quando viene eseguito il rendering, esiste un solo blocco di codice (quello HTML) e solo una riga è "extra".
  • L'utente che scrive lo snippet può vedere esattamente dove posizionare il proprio codice e input. Non devono cercare il tag textarea appropriato.
  • Gli utenti che leggono il post possono facilmente distinguere il codice senza nemmeno eseguire lo snippet. Naturalmente quando viene eseguito lo snippet il codice è ovvio.
  • Si interrompe solo quando gli identificatori di inizio / fine compaiono sulle proprie righe all'interno del codice o dell'input. Ma questo è improbabile e possono essere cambiati se assolutamente necessario.
  • È autonomo. Tutto il codice è proprio lì. (So ​​che questo potrebbe essere impossibile per un interprete più grande, ma uno dei punti di Stack Snippet era combattere i collegamenti morti con JSFiddle e simili, quindi l'autosufficienza è buona.)
  • Potrebbe essere espanso per adattarsi a qualsiasi numero di input (basato su testo).

Lo snippet di seguito è la versione generale non minimizzata, completa di esempio e un po 'più di stile.


15

Brainfuck (con debugger di base)

Ho visto la risposta di Brainfuck e ho pensato: sai cosa sarebbe fantastico? Se potessi fingere di capire cosa sta facendo il codice Brainfuck. E quindi ho creato un interprete e un debugger brainfuck di base. Il debugger è LENTO, ma funziona abbastanza bene, anche se per ora non ho implementato punti di interruzione (nella lista delle cose da fare).

Nota: la "macchina virtuale" Brainfuck non si ripristina automaticamente dopo aver eseguito il codice. Premere reset manualmente o il nastro avrà gli stessi valori esistenti al termine dell'ultima esecuzione del programma.

Il debugger funziona meglio a schermo intero.

var mycode = "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.";

function Brainfuck()    {
    this.cell_max = 255;
    this.read = function()    {return 0;}
    this.reset();
}

Brainfuck.prototype.reset = function()    {
    this.stack = [0];
    this.stackptr = 0;
    
    this.printbuffer = "";
}

Brainfuck.prototype.setCode = function(code)    {
    this.code = code;
    this.codeptr = 0;
    
    this.loop_map = {};
    var loops = [];
    for(var i = 0; i < this.code.length; i++)    {
        if(this.code[i] == '[')    {
            loops.push(i);
        }    else if(this.code[i] == ']')    {
            var last = loops.pop();
            this.loop_map[last] = i;
            this.loop_map[i] = last;
        }
    }
}

Brainfuck.prototype.done = function()    {
    return !(this.codeptr < this.code.length);
}

Brainfuck.prototype.step = function()    {
    switch(this.code.charAt(this.codeptr))    {
        case '>':
            if(++this.stackptr >= this.stack.length)    {
                this.stack.push(0);
            }
            break;
        case '<':
            if(--this.stackptr < 0)    {
                this.stackptr = this.stack.length - 1;
            }
            break;
        case '+':
            if(++this.stack[this.stackptr] > this.cell_max)    {
                this.stack[this.stackptr] = 0;
            }
            break;
        case '-':
            if(--this.stack[this.stackptr] < 0)    {
                this.stack[this.stackptr] = this.cell_max;
            }
            break;
        case '.':
            this.print();
            break;
        case ',':
            this.stack[this.stackptr] = this.read();
            break;
        case '[':
            if(this.stack[this.stackptr] == 0)    {
                this.codeptr = this.loop_map[this.codeptr];
            }
            break;
        case ']':
            if(this.stack[this.stackptr] != 0)    {
                this.codeptr = this.loop_map[this.codeptr];
            }
            break;
        default:
            
    }
    while(!this.done() && '><+-.,[]'.indexOf(this.code[++this.codeptr]) == -1);
}

Brainfuck.prototype.print = function()    {
    this.printbuffer += String.fromCharCode(this.stack[this.stackptr]);
}

// UI File

var $ = document.getElementById.bind(document);
var $_ = document.createElement.bind(document);

String.prototype.decodeHTML = function() {
    var map = {"gt":">", "lt":"<", "nbsp":""};
    return this.replace(/&(#(?:x[0-9a-f]+|\d+)|[a-z]+);?/gi, function($0, $1) {
        if ($1[0] === "#") {
            return String.fromCharCode($1[1].toLowerCase() === "x" ? parseInt($1.substr(2), 16)  : parseInt($1.substr(1), 10));
        } else {
            return map.hasOwnProperty($1) ? map[$1] : $0;
        }
    });
}

var bf = new Brainfuck();

var setup = function()    {
    bf.setCode($('code').value.decodeHTML());
    bf.read = function()    {
        var stdin = $('stdin').value;
        if(bf.read.index < stdin.length)    {
            return stdin[bf.read.index++].charCodeAt(0);
        }
        return 0;
    }
    bf.read.index = 0;
}

var run = function()    {
    setup();
    
    var stdout = $('stdout');
    var func = function()    {
        for(var i = 0; i < 500000 && !bf.done(); i++)    {
            bf.step();
        }
        stdout.innerHTML = bf.printbuffer;
        setTimeout(func, 0);
    };
    func();
}

var debug = function()    {
    $('debug-area').style.display = 'block';

    setup();
    
    var running = $('running-code');
        for(var i = 0; i < bf.code.length; i++)    {
            var s = $_('span');
            s.innerHTML = bf.code[i];
            s.style.fontFamily = "Courier";
            running.appendChild(s);
        }
        running.children[bf.codeptr].setAttribute('class', 'selected');
    
    genStackTable();
}

var genStackTable = function()    {
    var stable = $('stack-table');
    var head = stable.createTHead();
        var row = head.insertRow(0);
            row.insertCell(0).innerHTML = 'ptr';
            row.insertCell(1).innerHTML = 'addr';
            row.insertCell(2).innerHTML = 'value';
            row.insertCell(3).innerHTML = 'ASCII';
    var setStackVal = function(i, num, ascii, changed)    {
        return changed === num ? function() {
            ascii.value = String.fromCharCode(num.value);
            bf.stack[i] = num.value;
        } : function()    {
            num.value = ascii.value.charCodeAt(0);
            bf.stack[i] = num.value;
        }
    }
    for(var i in bf.stack)    {
        row = stable.insertRow();
        row.insertCell(0).innerHTML = i == bf.stackptr ? '>' : '';
        row.insertCell(1).innerHTML = i;
        var cell = row.insertCell(2);
            var numinput = $_('input');
                numinput.type = 'number';
                numinput.value = bf.stack[i];
            cell.appendChild(numinput);
        cell = row.insertCell(3);
            var asciiinput = $_('input');
                asciiinput.type = 'text';
                asciiinput.value = String.fromCharCode(bf.stack[i]);
                asciiinput.setAttribute('maxlength', 1);
            cell.appendChild(asciiinput);
        
        numinput.oninput = setStackVal(i, numinput, asciiinput, numinput);
        asciiinput.oninput = setStackVal(i, numinput, asciiinput, asciiinput);
    }
}

var debugRun = function()    {
    debugRun.pause = false;
    var func = function()    {
        step();
        if(!bf.done() && !debugRun.pause)    {
            setTimeout(func, $('step-duration').value);
        }
    }
    func();
}

var debugPause = function()    {
    debugRun.pause = true;
}

var step = function()    {
    var running = $('running-code');
    running.children[bf.codeptr].setAttribute('class', '');
    bf.step();
    $('stack-table').innerHTML = '';
    genStackTable();
    if(!bf.done())    {
        running.children[bf.codeptr].setAttribute('class', 'selected');
    }
    $('stdout').innerHTML = bf.printbuffer;
}

var reset = function()    {
    bf.reset();
    bf.read.index = 0;
    $('stdout').innerHTML = '';
    $('running-code').innerHTML = '';
    $('stack-table').innerHTML = '';
    $('debug-area').style.display = 'none';
}

var setStackSize = function()    {
    var sel = $('stackSize');
    bf.cell_max = parseInt(sel.options[sel.selectedIndex].value);
}

$('code').value = mycode;
input    {
    box-sizing:border-box;
    -moz-box-sizing:border-box;
}
div.textarea {
    -moz-appearance: textfield-multiline;
    -webkit-appearance: textarea;
    border: 1px solid gray;
    font: -webkit-small-control;
    font-family:Courier;
    height: 28px;
    overflow: auto;
    padding: 2px;
    resize: both;
    width: 200px;
    white-space:pre;
}
#debug-area    {
    display:none;
}
span.selected    {
    background-color:red;
}
<div>
    <h1>Brainfuck</h1>

    <div>
        <div>Code</div>
        <textarea id="code"></textarea>
    </div>
    <div>
        <div>Stdin</div>
        <textarea id="stdin"></textarea>
    </div>
    <div>
        <div>Stdout</div>
        <div id="stdout" class="textarea"></div>
    </div>
    <div>
        <span>Cell Size</span>
        <select id="stackSize" onchange="setStackSize()">
            <option value="255">8-bit</option>
            <option value="65535">16-bit</option>
            <option value="4294967296">32-bit</option>
        </select>
    </div>
    <div>
        <button id="run" onclick="run()">Run</button>
        <button id="debug" onclick="debug()">Debug</button>
        <button id="reset" onclick="reset()">Reset</button>
    </div>
    <div id="debug-area">
        <h2>Debug</h2>
        <div>
            <button onclick="debugRun()">Run</button>
            <button onclick="debugPause()">Pause</button>
            <span>Time between instructions</span>
            <input id="step-duration" type="number" value=5 />
			<br/>
            <button onclick="step()">Step</button>
        </div>
        <div>
            <h3>Executing Code</h3>
            <div id="running-code"></div>
        </div>
        <div id="stack">
            <h3>Stack</h3>
            <table id="stack-table"></table>
        </div>
    </div>
</div>

FARE:

  • aggiungere punti di interruzione
  • aggiungi il controllo della portata per cambiare lo stack
  • indicatore di progresso
  • farlo sembrare migliore
  • aggiungi rewind per il debug
  • cambiare stdin in una specie di stream?
  • codice di golf un po '
  • ?

Uso:

Per utilizzarlo in uno snippet da qualche parte sul sito, modifica la prima riga dello snippet per includere il codice come "mycode".

Per eseguire il codice senza debugger, è sufficiente premere Esegui. Buffer l'output per mezzo milione di istruzioni prima di aggiornare stdout.

Per eseguire il debug, iniziare premendo il pulsante debug. Il pulsante di passaggio passerà all'istruzione successiva. Il pulsante Esegui eseguirà l'intero programma, ma un passo alla volta, aggiornando la tabella dello stack ad ogni passo (motivo per cui è così lento). Il tempo tra le istruzioni è determinato dalla casella di input con quel nome. Il pulsante di pausa mette in pausa l'esecuzione del codice. Può essere ripreso premendo di nuovo Esegui.

Tutti i valori nello stack possono essere cambiati dal vivo a quello che vuoi. Fai attenzione, tuttavia, non controlla se cambi il valore intero nella cella, quindi se lo metti in 300 con una dimensione dello stack di 8 bit, non ti interessa davvero e non lo correggerà fino alla prossima volta che aumenta.


Questo è abbastanza pulito. Adoro il debugger!
Ingo Bürk,

14

Japt

Japt ( Ja vascri pt abbreviato) è una lingua che ho progettato a settembre 2015. A causa dell'essere pigro impegnato, non ho creato un interprete fino all'inizio di novembre. Puoi trovare l'interprete ufficiale e i documenti qui .

Nota: in caso di domande, suggerimenti o segnalazioni di bug, pubblicarli nella chat room di Japt .

Curiosità: questo era in origine l'interprete principale (e in effetti l' unico interprete). Puoi vederlo se dai un'occhiata alla cronologia delle revisioni .


Japt ha un Github?
Downgoat,

@ Vɪʜᴀɴ Non ancora, ma ne installerò uno nelle prossime 24 ore.
ETHproductions

2
@ Vɪʜᴀɴ Avrei dovuto dire 24 minuti. ;) Ecco qua. Il file Leggimi è in arrivo.
ETHproductions

1
Dovresti usare rawgit.com invece di raw.githubusercontent.com: a Chrome non piacciono le cose di tipo MIME.
Mama Fun Roll,

1
@nicael Puoi usare Us q1, credo.
ETHproductions

13

FRACTRAN

Un interprete semi-ottimizzato per la mia lingua esoterica preferita! Purtroppo non ho molto tempo questa settimana, quindi le funzionalità aggiuntive dovranno venire più tardi.

var ITERS_PER_SEC = 100000
var TIMEOUT_MILLISECS = 5000

var ERROR_INPUT = "Invalid input"
var ERROR_PARSE = "Parse error: "
var ERROR_TIMEOUT = "Timeout"
var ERROR_INTERRUPT = "Interrupted by user"

var running, instructions, registers, timeout, start_time, iterations;

function clear_output() {
  document.getElementById("output").value = ""
  document.getElementById("stderr").innerHTML = ""
}

function stop() {
  running = false
  document.getElementById("run").disabled = false
  document.getElementById("stop").disabled = true
  document.getElementById("clear").disabled = false
}

function interrupt() {
  error(ERROR_INTERRUPT)
}

function error(msg) {
  document.getElementById("stderr").innerHTML = msg
  stop()
}

function factorise(n) {
  var factorisation = {}
  var divisor = 2
  
  while (n > 1) {
    if (n % divisor == 0) {
      var power = 0
      
      while (n % divisor == 0) {
        n /= divisor
        power += 1
      }
      
      if (power != 0) {
        factorisation[divisor] = power
      }
    }
    
    divisor += 1
  }
  
  return factorisation
}

function fact_accumulate(fact1, fact2) {
  for (var reg in fact2) {
    if (reg in fact1) {
      fact1[reg] += fact2[reg]
    } else {
      fact1[reg] = fact2[reg]
    }
  } 
  
  return fact1
}

function exp_to_fact(expression) {
  expression = expression.trim().split(/\s*\*\s*/)
  var factorisation = {}
  
  for (var i = 0; i < expression.length; ++i) {
    var term = expression[i].trim().split(/\s*\^\s*/)
    
    if (term.length > 2) {
      throw "error"
    }
    
    term[0] = parseInt(term[0])
    
    if (isNaN(term[0])) {
      throw "error"
    }
    
    if (term.length == 2) {
      term[1] = parseInt(term[1])
      
      if (isNaN(term[1])) {
        throw "error"
      }
    }    
    
    if (term[0] <= 1) {
      continue 
    }
    
    var fact_term = factorise(term[0])
    
    if (term.length == 2) {
      for (var reg in fact_term) {
        fact_term[reg] *= term[1] 
      }
    }
    
    factorisation = fact_accumulate(factorisation, fact_term)
  }
  
  return factorisation
}

function to_instruction(n, d) {
  instruction = []
  divisor = 2
  
  while (n > 1 || d > 1) {
    if (n % divisor == 0 || d % divisor == 0) {
       reg_offset = 0
       
       while (n % divisor == 0) {
         reg_offset += 1
         n /= divisor
       }
      
       while (d % divisor == 0) {
         reg_offset -= 1
         d /= divisor
       }
      
      if (reg_offset != 0) {
        instruction.push(Array(divisor, reg_offset))
      }
    }
    
    divisor += 1
  }
  
  return instruction
}

function run() {
  clear_output()
  
  document.getElementById("run").disabled = true
  document.getElementById("stop").disabled = false
  document.getElementById("clear").disabled = true
  
  timeout = document.getElementById("timeout").checked

  var code = document.getElementById("code").value
  var input = document.getElementById("input").value
  
  instructions = []
  
  code = code.trim().split(/[\s,]+/)
  
  for (i = 0; i < code.length; ++i){
    fraction = code[i]
    
    split_fraction = fraction.split("/")
    
    if (split_fraction.length != 2){
      error(ERROR_PARSE + fraction)
      return
    }
    
    numerator = parseInt(split_fraction[0])
    denominator = parseInt(split_fraction[1])
    
    if (isNaN(numerator) || isNaN(denominator)){
      error(ERROR_PARSE + fraction)
      return
    }
    
    instructions.push(to_instruction(numerator, denominator))
  }
  
  try {
    registers = exp_to_fact(input)
  } catch (err) {
    error(ERROR_INPUT)
    return
  }
  
  running = true
  iterations = 0
  start_time = Date.now()
  
  fractran_iter(1)
}

function regs_to_string(regs) {
  reg_list = Object.keys(regs)
  reg_list.sort(function(a,b){ return a - b })
  
  out_str = []
  
  for (var i = 0; i < reg_list.length; ++i) {
    if (regs[reg_list[i]] != 0) {
      out_str.push(reg_list[i] + "^" + regs[reg_list[i]])
    }
  }
  
  out_str = out_str.join(" * ")  
  
  if (out_str == "") {
    out_str = "1"
  }
  
  return out_str
}

function fractran_iter(niters) {
  if (!running) {
    stop()
    return
  }
  
  var iter_start_time = Date.now()
  
  for (var i = 0; i < niters; ++i)
  {
    program_complete = true
    
    for (var instr_ptr = 0; instr_ptr < instructions.length; ++instr_ptr){
      instruction = instructions[instr_ptr]
      perform_instr = true
    
      for (var j = 0; j < instruction.length; ++j)
      {
        var reg = instruction[j][0]
        var offset = instruction[j][1]
        
        if (registers[reg] == undefined) {
          registers[reg] = 0
        }
        
        if (offset < 0 && registers[reg] < -offset) {
          perform_instr = false
          break
        }         
      }
      
      if (perform_instr) {
        for (var j = 0; j < instruction.length; ++j)
        {
           var reg = instruction[j][0]
           var offset = instruction[j][1]
           
           registers[reg] += offset
        }
        
        program_complete = false
        break
      }
    }
    
    if (program_complete) {
      document.getElementById("output").value += regs_to_string(registers)
      stop()
      return
    }
    
    iterations++
    
    if (timeout && Date.now() - start_time > TIMEOUT_MILLISECS) {
      error(ERROR_TIMEOUT)
      return
    }
  }
  
  setTimeout(function() { fractran_iter(ITERS_PER_SEC * (Date.now() - iter_start_time)/1000) }, 0)
}
<div style="font-size:12px;font-family:Verdana, Geneva, sans-serif;">
  <div style="float:left; width:50%;">
    Code:
    <br>
    <textarea id="code" rows="4" style="overflow:scroll;overflow-x:hidden;width:90%;">37789/221 905293/11063 1961/533 2279/481 57293/16211 2279/611 53/559 1961/403 53/299 13/53 1/13 6557/262727 6059/284321 67/4307 67/4661 6059/3599 59/83 1/59 14279/871933 131/9701 102037079/8633 14017/673819 7729/10057 128886839/8989 13493/757301 7729/11303 89/131 1/89 31133/2603 542249/19043 2483/22879 561731/20413 2483/23701 581213/20687 2483/24523 587707/21509 2483/24797 137/191 1/137 6215941/579 6730777/965 7232447/1351 7947497/2123 193/227 31373/193 23533/37327 5401639/458 229/233 21449/229 55973/24823 55973/25787 6705901/52961 7145447/55973 251/269 24119/251 72217/27913 283/73903 281/283 293/281 293/28997 293/271 9320827/58307 9831643/75301 293/313 28213/293 103459/32651 347/104807 347/88631 337/347 349/337 349/33919 349/317 12566447/68753 13307053/107143 349/367 33197/349 135199/38419 389/137497 389/119113 389/100729 383/389 397/383 397/39911 397/373 1203/140141 2005/142523 2807/123467 4411/104411 802/94883 397/401 193/397 1227/47477 2045/47959 2863/50851 4499/53743 241/409 1/241 1/239
</textarea>
    <br>Input:
    <br>
    <textarea id="input" rows="2" style="overflow:scroll;overflow-x:hidden;width:90%;">2^47 * 193</textarea>
    <p>
      Timeout:
      <input id="timeout" type="checkbox" checked="true"></input>
    </p>
  </div>
  <div style="float:left; width:50%;">
    Output:
    <br>
    <textarea id="output" rows="6" style="overflow:scroll;width:90%;"></textarea>
    <p>
      <input id="run" type="button" value="Run" onclick="run()"></input>
      <input id="stop" type="button" value="Stop" onclick="interrupt()" disabled="true"></input>
      <input id="clear" type="button" value="Clear" onclick="clear_output()"></input>
      &nbsp;
      <span id="stderr" style="color:red"></span>
    </p>
  </div>
</div>

Il programma di esempio sopra è il mio programma di quattro quadrati insieme - prende l'ingresso 2 n * 193 e produce 3 a * 5 b * 7 c * 11 d , in modo tale che a 2 + b 2 + c 2 + d 2 = n.

Fare

  • Generatore di frammenti
  • Consenti la notazione di fattorizzazione anche per le frazioni
  • Convalida dell'input meno terribile
  • Pulisci il codice per essere migliore
  • Consentire la stampa di registri in condizioni speciali (ad es. Solo registro 2 È impostato , nel caso del generatore principale di Conway). Attualmente solo i programmi che terminano producono qualsiasi output.
  • Ottimizzazioni delle prestazioni?

uso

  • Le frazioni nel codice sono divise per [\s,]+ , permettendoti di separare le frazioni da newline, spazi o virgole (o schede, o anche qualsiasi combinazione di quanto sopra, se sei pazzo)
  • L'input può essere in notazione di fattorizzazione, ad es 2^5 * 3^7 * 11
  • Generatore di frammenti in arrivo qualche tempo dopo

1
Ha bisogno di più punti e virgola. L'ASI è opera del diavolo.
nyuszika7h

10

Preludio

Forse potrei aumentare un po 'l'adozione di Prelude se le persone possono semplicemente giocarci nei loro browser, quindi ecco un interprete JavaScript. È basato sull'interprete Brainfuck di Sp3000 , la cui caratteristica killer è l'esecuzione interrompibile e un timeout opzionale.

var ITERS_PER_SEC = 100000;
var TIMEOUT_MILLISECS = 5000;
var ERROR_LOOP_MISMATCH = "Mismatched parentheses";
var ERROR_LOOP_MULTI = "Multiple parentheses in the same column";
var ERROR_TIMEOUT = "Timeout";
var ERROR_INTERRUPT = "Interrupted by user";

var code, input, timeout, num_input, num_output, loop_stack, loop_map;
var running, start_time, code_ptr, width, input_ptr, voices, iterations;

function clear_output() {
    document.getElementById("output").value = "";
    document.getElementById("stderr").innerHTML = "";
}

function stop() {
    running = false;
    document.getElementById("run").disabled = false;
    document.getElementById("stop").disabled = true;
    document.getElementById("clear").disabled = false;
    document.getElementById("num_input").disabled = false;
    document.getElementById("num_output").disabled = false;
    document.getElementById("timeout").disabled = false;
}

function interrupt() {
    error(ERROR_INTERRUPT);
}

function error(msg) {
    document.getElementById("stderr").innerHTML = msg;
    stop();
}

function run() {
    clear_output();

    document.getElementById("run").disabled = true;
    document.getElementById("stop").disabled = false;
    document.getElementById("clear").disabled = true;
    document.getElementById("num_input").disabled = false;
    document.getElementById("num_output").disabled = false;
    document.getElementById("timeout").disabled = false;

    code = document.getElementById("code").value;
    input = document.getElementById("input").value;
    num_input = document.getElementById("num_input").checked;
    num_output = document.getElementById("num_output").checked;
    timeout = document.getElementById("timeout").checked;

    loop_stack = [];
    loop_map = {};

    if (num_input) {
        input = input.match(/-?\d+/g).map(function (n) {
            return +n;
        });
    } else {
        input = input.split("").map(function (s) {
            return s.charCodeAt(0);
        });
    }

    code = code.split("\n");
    width = 0;
    for (var i = 0; i < code.length; ++i)
        if (code[i].length > width) 
            width = code[i].length;
    console.log(code);
    console.log(width);
    for (var i = 0; i < width; ++i) {
        var hasParens = false;
        for (var j = 0; j < code.length; ++j) {
            var char = code[j][i];
            if (char == "(" || char == ")") {
                if (hasParens) {
                    error(ERROR_LOOP_MULTI);
                    return;
                }

                hasParens = true;
                if (char == "(") loop_stack.push({
                    x: i,
                    y: j
                });
                else {
                    if (loop_stack.length == 0) {
                        error(ERROR_LOOP_MISMATCH);
                        return;
                    } else {
                        var last_parens = loop_stack.pop();
                        loop_map[last_parens.x] = {
                            x: i,
                            y: last_parens.y
                        };
                        loop_map[i] = last_parens;
                    }
                }
            }
        }
        console.log(i);
        console.log(loop_stack);
    }

    if (loop_stack.length > 0) {
        error(ERROR_LOOP_MISMATCH);
        return;
    }

    console.log(loop_map);

    running = true;
    start_time = Date.now();
    code_ptr = 0;
    input_ptr = 0;
    voices = code.map(function () {
        return [];
    });
    iterations = 0;

    prelude_iter(1);
}

function prelude_iter(niters) {
    if (code_ptr >= width || !running) {
        stop();
        return;
    }

    console.log(voices);
    var iter_start_time = Date.now();

    for (var i = 0; i < niters; ++i) {
        var previousTops = voices.map(function(v) { return v[v.length-1] || 0; });
        
        for (var j = 0; j < code.length; ++j) {
            switch (code[j][code_ptr]) {
                case "0":
                case "1":
                case "2":
                case "3":
                case "4":
                case "5":
                case "6":
                case "7":
                case "8":
                case "9":
                    voices[j].push(+code[j][code_ptr]);
                    break;
                    
                case "+":
                    var x = voices[j].pop() || 0;
                    var y = voices[j].pop() || 0;
                    voices[j].push(x + y);
                    break;

                case "-":
                    var x = voices[j].pop() || 0;
                    var y = voices[j].pop() || 0;
                    voices[j].push(y - x);
                    break;

                case "v":
                    voices[j].push(previousTops[j == code.length-1 ? 0 : j + 1]);
                    break;
                    
                case "^":
                    voices[j].push(previousTops[j == 0 ? code.length-1 : j - 1]);
                    break;
                    
                case "#":
                    voices[j].pop();
                    break;

                case "!":
                    var value = voices[j].pop() || 0; 
                    document.getElementById("output").value += num_output ? value+"\n" : String.fromCharCode(value);
                    break;

                case "?":
                    if (input_ptr >= input.length) {
                        voices[j].push(0);
                    } else {
                        voices[j].push(input[input_ptr]);
                        ++input_ptr;
                    }
                    break;
            }
        }

        if (loop_map[code_ptr])
        {
            var other = loop_map[code_ptr];
            code_ptr = previousTops[other.y] ? Math.min(code_ptr, other.x) : Math.max(code_ptr, other.x);
        }

        ++code_ptr;
        ++iterations;

        if (timeout && Date.now() - start_time > TIMEOUT_MILLISECS) {
            error(ERROR_TIMEOUT);
            return;
        }
    }

    setTimeout(function () {
        prelude_iter(ITERS_PER_SEC * (Date.now() - iter_start_time) / 1000)
    }, 0);
}
<div style="font-size:12px;font-family:Verdana, Geneva, sans-serif;">Code:
    <br>
    <textarea id="code" rows="4" style="overflow:scroll;overflow-x:hidden;width:90%;">1(  #^    #^^   (#^+!
6 9+ 05+5+^#^+! #^ ^+!
   (((1- )#^##)^^+   )7-!)1433545514232323344949145353495314235494040404232323013334492349532333344953493435343584233475234501333449530423232349495323232323495323230494)</textarea>
    <br>Input:
    <br>
    <textarea id="input" rows="2" style="overflow:scroll;overflow-x:hidden;width:90%;">5a-13 11 2e3</textarea>
    <p>Numeric Input:
        <input id="num_input" type="checkbox">&nbsp; Numeric Output:
        <input id="num_output" type="checkbox">&nbsp; Timeout:
        <input id="timeout" type="checkbox" checked="checked">&nbsp;
        <br>
        <br>
        <input id="run" type="button" value="Run" onclick="run()">
        <input id="stop" type="button" value="Stop" onclick="interrupt()" disabled="disabled">
        <input id="clear" type="button" value="Clear" onclick="clear_output()">&nbsp; <span id="stderr" style="color:red"></span>

    </p>Output:
    <br>
    <textarea id="output" rows="6" style="overflow:scroll;width:90%;"></textarea>
</div>

In alternativa, ecco un JSFiddle .

L'interprete è prepopolato con il mio quine , ma puoi facilmente trovare altri programmi di esempio con cui giocare cercando le mie risposte Prelude .

Tutte le funzionalità di Prelude sono implementate. L'unico difetto è la mancanza di aritmetica di precisione arbitraria, dovuta al tipo di numero JavaScript. Potrei risolverlo a un certo punto, poiché ho solo bisogno di supportare l'addizione e la sottrazione per numeri interi arbitrari.

L'input e l'output sono in genere i valori byte dei singoli caratteri, ma l'interprete viene fornito con due flag per leggere e / o scrivere numeri (con segno).

Fare

  • Aggiungi versione ridotta per la copia.
  • Supporta l'aritmetica di precisione arbitraria.
  • Aggiungi generatore di frammenti.

9

Pesce morto

function run() {
  var code = document.getElementById("code").value
  var unicode = document.getElementById("unicode").checked
  var n = 0
  var output = ""

  for (var i = 0; i < code.length; ++i) {
    switch (code[i]) {
      case "i":
        n++
        break
      case "d":
        n--
        break
      case "s":
        n *= n
        break
      case "o":
        if (unicode) {
          output += String.fromCharCode(n)
        } else {
          output += n
          output += "\n"
        }
        break
      default:
        output += "\n"
    }
    
    if (n == -1 || n == 256) {
      n = 0
    }
  }

  document.getElementById('output').value = output
}
<div style="font-size:12px;font-family:Verdana, Geneva, sans-serif;">
  <div style="float:left; width:50%;">
    Code:<br>
    <textarea id="code" rows="8" style="overflow:scroll;overflow-x:hidden;width:90%;" wrap="hard">iiisdsiiiiiiiioiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiiiiiiiiiooiiiiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddoddddddddddddddddddddddddsiioiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiiioiioddddddddddddoddddodddoiiiiiiiiiiiiiiiiiiiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddodddddddddddddddddddddsdddddodddddodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddodddddddddddddddddddddddsiiiiiiiioiiiiiiiiiiiiiiiiiiiiiioiiiiiiofdddddddddddddddddddddddddddddddddddddddddddddoiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiiiiiiiiiooiiiiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddoddddddddddddddddddddddddsiioiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiiioiioddddddddddddoddddodddoiiiiiiiiiiiiiiiiiiiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddodddddddddddddddddddddsdddddodddddodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddodddddddddddddddddddddddsiiiiiiiioiiiiiiiiiiiiiiiiiiiiiioiiiiiiofdddddddddddddddddddddddddddddddddddddddddddddoiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiiiiiiiiiooiiiiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddoddddddddddddddddddddddddsiioiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiiioiioddddddddddddoddddodddoiiiiiiiiiiiiiiiiiiiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddoddddddddddddddddddddddddsiiiioiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioddddoiiiiiiiiiiiiiiiiioddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddoddddddddddddddddddddddddsiiiioiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioddddoiiioiioiiioiiiiiiiiiiodddddddddddofddddddddddddddddddddddddddddddddoiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiiiiiiiiiooiiiiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddoddddddddddddddddddddddddsiioiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiiioiioddddddddddddoddddodddoiiiiiiiiiiiiiiiiiiiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddodddddddddddddddddddddsdddddodddddodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddodddddddddddddddddddddddsiiiiiiiioiiiiiiiiiiiiiiiiiiiiiioiiiiiio</textarea>
    <p>
      <input id="unicode" type="checkbox" checked="true" />Use ASCII/Unicode mode
    </p>
  </div>
  <div style="float:left; width:50%;">
    Output:<br>
    <textarea id="output" rows="6" style="overflow:scroll;width:90%;"></textarea>
  <p>
    <input id='run' type='button' value='Run' onclick='run()' />
  </p>
  </div>
</div>

Per pre-inizializzare la casella del codice, basta inserire qualcosa tra i tag textarea. Allo stesso modo, aggiungendo checked="true"il tag checkbox, è possibile attivare la modalità ASCII / Unicode per impostazione predefinita (come visto sopra).

Nota che Deadfish stesso non ha effettivamente l'output ASCII nelle sue specifiche originali, l'ho solo messo per domande che potrebbero consentire "la prossima cosa più vicina". Se temi che le regole di una domanda non consentano Deadfish a causa di ciò, puoi sempre guardare qualcosa come Deadfish ~ che ha un output ASCII.

L'esempio mostrato è tratto dall'argomento Buon compleanno .


inputgli elementi non hanno contenuto (né tag di chiusura). Dovresti usare <label><input />Foo</label>invece di<input>Foo</input>
Oriol

Ha bisogno di più punti e virgola. L'ASI è opera del diavolo.
nyuszika7h,

@ nyuszika7h Mi spiace, aggiornerò quando avrò tempo (troppo usato per Python e non ho molto JS)
Sp3000

8

Pesce morto

Questo non è strettamente conforme ai requisiti, è la mia visione su come potremmo utilizzare Stack Snippet.

Non mi piace la quantità di boilerplate, in particolare la necessità di includere HTML personalizzato per un altro pulsante Esegui.

Nella mia visione:

  • posizionare un singolo <script> tag per includere un framework semplice e l'interprete effettivo
  • mettere lo script nell'area CSS (l'evidenziazione della sintassi potrebbe andare in modo orribile)
  • utilizza il pulsante Esegui snippet di codice esistente per eseguire il codice
  • ottenere l'output nel frame dello snippet

Per ora non ho deciso come sarebbe meglio specificare l'input.

iiisdsiiiiiiiioiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiiiiiiiiiooiiiiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddoddddddddddddddddddddddddsiioiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiiioiioddddddddddddoddddodddoiiiiiiiiiiiiiiiiiiiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddodddddddddddddddddddddsdddddodddddodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddodddddddddddddddddddddddsiiiiiiiioiiiiiiiiiiiiiiiiiiiiiioiiiiiio
dddddddddddddddddddddddddddddddddddddddddddddoiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiiiiiiiiiooiiiiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddoddddddddddddddddddddddddsiioiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiiioiioddddddddddddoddddodddoiiiiiiiiiiiiiiiiiiiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddodddddddddddddddddddddsdddddodddddodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddodddddddddddddddddddddddsiiiiiiiioiiiiiiiiiiiiiiiiiiiiiioiiiiiio
dddddddddddddddddddddddddddddddddddddddddddddoiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiiiiiiiiiooiiiiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddoddddddddddddddddddddddddsiioiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiiioiioddddddddddddoddddodddoiiiiiiiiiiiiiiiiiiiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddoddddddddddddddddddddddddsiiiioiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioddddoiiiiiiiiiiiiiiiiioddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddoddddddddddddddddddddddddsiiiioiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioddddoiiioiioiiioiiiiiiiiiiodddddddddddo
ddddddddddddddddddddddddddddddddoiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiiiiiiiiiooiiiiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddoddddddddddddddddddddddddsiioiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioiiiiiiiiioiioddddddddddddoddddodddoiiiiiiiiiiiiiiiiiiiiiiiiodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddodddddddddddddddddddddsdddddodddddodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddodddddddddddddddddddddddsiiiiiiiioiiiiiiiiiiiiiiiiiiiiiioiiiiiio
<script src="https://bitbucket.org/manatwork/stackcode/raw/681610d0a6face9df62e82c50ec887d66d692e0f/interpret.js#Deadfish"></script>


dovrebbe esserci un modo per includere facilmente anche l'input, immagino
SztupY,

Certamente, @SztupY. Per ora sono indeciso se includere anche l'input nel pezzo CSS o in quello HTML. Non userei il pezzo JavaScript per questo, poiché i browser lo eseguiranno prima e un po 'di codice potrebbe risultare in un ciclo infinito in JavaScript. Sfortunatamente, non c'è altro modo in quanto altri pezzi non vengono copiati sul server dello snippet dello stack. :(
arte

Penso che il codice vada bene nel CSS e che l'input possa seguire i <script>tag (forse in un piccolo contenitore, come <pre>, quindi lo script potrebbe accedervi. Speriamo che un pre non distorca troppo l'input).
SztupY,

Viene visualizzato un <pre>(o generalmente qualsiasi tag) e la sintassi evidenziata in verde. Dato che JavaScript è in grado di estrarre comunque la parte di input, non includerei markup extra. La differenza principale tra l'utilizzo del pezzo CSS rispetto al pezzo HTML è che CSS non appare nel documento, mentre HTML lo fa. Ancora indeciso.
arte

3
Inoltre, mi sto perdendo qualcosa o il tuo frammento non funziona in questo momento?
Calvin's Hobbies,

8

JavaScript ES7

Ciò consente di eseguire il codice ES6 / 7 in qualsiasi browser.

I browser su cui sono sicuro che funziona al 100% sono: IE 11, Chrome 46 e Safari 7.

Questo supporta la comprensione dell'array ( [for(a in b) c])

function color(n,e){return~[null,void 0].indexOf(n)?'<div class="out '+e+'"><span style="color: #808080">'+String(n)+"</span></div>":"string"==typeof n?'<div class="out '+e+'"><span class="string">"'+n+'"</span></div>':"number"==typeof n?'<div class="out '+e+'"><span class="number">'+n+"</span></div>":"function"==typeof n?'<div class="out '+e+'"><span style="color: #808080">function</span></div>':"undefined"!=typeof n.length?'<div class="out '+e+'">'+JSON.stringify(n).replace(/(["'])((?:(?=\\*)\\.|.)*?)\1/g,'<span class="string">$1$2$1</span>').replace(/(\d+)/g,'<span class="number">$1</span>')+"</div>":'<div class="out '+e+'">'+JSON.stringify(n,null,2).replace(/(["'])((?:(?=\\*)\\.|.)*?)\1/g,'<span class="string">$1$2$1</span>').replace(/(\d+)/g,'<span class="number">$1</span>').replace(/\n/g,"<br>")+"</div>"}document.getElementById("run").onclick=function(){document.getElementById("Console").innerHTML="";var res="",err=!1;try{res=eval(babel.transform(document.getElementById("code").value).code.split("\n").slice(1).join("\n"))}catch(er){res=er.toString(),err=!0}err?document.getElementById("Console").innerHTML+='<div class="out error"><span>'+res+"</span></div>":document.getElementById("Console").innerHTML+=color(res,"implicit")},function(n,e){window.console={log:function(){n.log.apply(n,arguments),document.getElementById("Console").innerHTML+=color(arguments.length-1?Array.prototype.slice.call(arguments):arguments[0],"")},warn:function(){n.warn.apply(n,arguments),document.getElementById("Console").innerHTML+=color(arguments.length-1?Array.prototype.slice.call(arguments):arguments[0],"warn")},error:function(){n.error.apply(n,arguments),document.getElementById("Console").innerHTML+=color(arguments.length-1?Array.prototype.slice.call(arguments):arguments[0],"error")}},window.alert=console.log}(window.console,window.alert);
@import url(http://fonts.googleapis.com/css?family=Open+Sans:400,300,700);@import url(https://fonts.googleapis.com/css?family=Inconsolata);*{font-family:'Open Sans',Arial,sans-serif;font-size:.9rem}.pre,code,pre,pre *{font-family:Inconsolata,monospace}:not(b,bold,strong){font-weight:300}h1,h2,h3,h4,h5,h6{font-weight:600}h1{font-size:1.4rem}h2{font-size:1.38rem}h3{font-size:1.2rem}h4{font-size:1.15rem}h5{font-size:1.11rem}h6{font-size:1.05rem}b,i,p,span{color:#404040}p{line-height:1.3rem}a{color:#605346;text-decoration:none}a:active{color:#523415}a:visited{color:#74513E}hr{border:none;border-top:1px solid #e0d7c1}blockquote{background:#EDE3D3;border-radius:0 .5rem .5rem 0;padding:.5rem .5rem .5rem 4em;margin:.5rem .2rem}code{background:#EBE7DD;border:1px solid #e0d7c1;padding:.3rem .4rem;border-radius:.2rem}.pre,pre{background:rgba(221,221,221,.3);border-radius:.3rem;padding:.5rem;font-size:1.2rem}ol{counter-reset:ol;list-style:none}li{line-height:1.5rem}ol li:before{content:counter(ol) ". ";counter-increment:ol;font-weight:700}table{background:#f2e8d9;border-radius:.75rem;border-collapse:collapse;table-layout:fixed}table.full>tbody{width:100%}thead>tr:first-child>td{border:none;border-bottom:2px solid #e0cbab!important;font-weight:700;z-index:1;text-align:center}td:not(:first-child){border-left:1px solid #eadbc3;z-index:-1}td:only-child{background:#e6dac7;text-align:center;font-weight:600;padding:.25rem;column-span:all}td{padding:.75rem}tr.sub{background:#EDE3D3}input,textarea{border-radius:.5rem;padding:.25rem;border:none;outline:0;transition:box-shadow .3s ease;background-color:#fff!important;margin:.5rem 0}input:focus,textarea:focus{box-shadow:0 0 5px rgba(81,203,238,1)}textarea{resize:vertical}button,input[type=button]{padding:.3rem .5rem;border-radius:.5rem;background-color:#faebd7;cursor:pointer;border:none;border-bottom:1.5px solid #deb887;outline:0}button:active,input[type=button]:active{border:none;border-top:1.5px solid #deb887;color:#000}
#Console{background-color:#fff;border-radius:.5rem;padding:0;height:auto!important;overflow:scroll;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;min-height:1rem}.out,.out *{font-size:1.1rem;font-family:Inconsoleta,monospace}.out *{padding-left:.3rem}.out{border-top:1px solid #F0F0F0;border-bottom:1px solid #F0F0F0;padding:.7rem 1rem}.string,.string *{color:#C41927!important}.number{color:#1D00CF}.out.implicit:before{content:"<\00B7 ";color:#888;letter-spacing:-2px}.out.error:before,.out.warn:before{display:inline-block;background-size:1.1rem;content:"";width:1.1rem;height:1.1rem}.out.warn:before{background-image:url(http://vihan.org/p/esfiddle/icons/Warn.png)}.out.error:before{background-image:url(http://vihan.org/p/esfiddle/icons/Error.png)}.out.warn,.out.warn *{color:#AA5909;background-color:}.out.implicit,.out.log{border-color:#F0F0F0;background-color:#FFF}.out.error{border-color:#FFD7D8;background-color:#FFEBEB}
body,html{width:100%;height:100%;margin:0}body{background:#F4F3F1;display:-ms-flex;display:-webkit-flex;display:flex;align-items:center;justify-content:center}body>div{background:#EAE8E4;border-radius:.4rem;margin:2rem;padding:1rem;overflow:auto;width:50%;max-height:80%;overflow-x:hidden}label{display:block}.full{width:calc(100% - 1rem);display:inline-block;height:7rem}#input{width:100%}.out.warn  { border-color: #FFEFCC; background-color: #FFFAE1; }
<div id="demo"><h1>Code</h1><textarea id="code" class="full pre" placeholder="Code here">f=n=>n+1;
console.log( f(3) );
console.warn( `Foo` )
console.error( `Bar` );
alert( `Output` );
[ f(1), f(2) ]</textarea><button id="run">Run</button><button onclick="prompt('Link:','http://vihan.org/p/esfiddle?code='+encodeURIComponent(document.getElementById('code').value))">Permalink</button></div><div><h1>Console Output</h1><pre id="Console" class="full"></pre></div><script src="http://babeljs.io/scripts/babel.js"></script>

Per i permalink, utilizzare ESFiddle


Sto scaricando questa risposta perché quando provo a eseguirla, Chrome avvisa ERR_NAME_NOT_RESOLVED e quindi arresta in modo
cat

1
Chrome versione 57 outputReferenceError: babel is not defined
Khaled.K

6

Insonnia

Le specifiche sono ambigue sulla semantica delle istruzioni 8 e 9, quindi non sono implementate.

Sentiti libero di migliorarlo per supportare le istruzioni da 0 a 7. C'è anche un codice incompleto per eseguire il programma al rallentatore, ma era difettoso, quindi lo rimuovo dall'interfaccia.

function toAsciiValue(t) {
    var i = 0;
    var a = "";
    for (i = 0; i < t.length; i++) {
        a += t.charCodeAt(i);
    }
    return a;
}

// http://stackoverflow.com/questions/1219860/html-encoding-in-javascript-jquery
function escapeHTML(str)
{
    var div = document.createElement('div');
    var text = document.createTextNode(str);
    div.appendChild(text);
    return div.innerHTML;
}

var interpreter = (function () {
    var group;
    var ip;
    var gp;
    var bp;
    var code;
    var halted;
    var tid;
    var output = "";
    
    function flipbit() {
        group[gp] = group[gp] ^ (1 << bp);
    };
    
    var commands = {
        0: function () { 
            flipbit();
            bp = (bp - 1) & 0x7;
        },
        1: function () {
            flipbit();
            bp = (bp + 1) & 0x7;
        },
        2: flipbit,
        3: function () { gp++; bp = 7; },
        4: function () { gp--; bp = 7; },
        5: function () { output += ~~group[gp]; },
        6: function () { output += String.fromCharCode(~~group[gp]); },
        7: function () {}
    };
    
    var nonprint = {
        "\0": "NUL",
        "\x01": "SOH",
        "\x02": "STX",
        "\x03": "ETX",
        "\x04": "EOT",
        "\x05": "ENQ",
        "\x06": "ACK",
        "\x07": "BEL",
        "\x08": "BS",
        "\x09": "TAB",
        "\x0a": "LF",
        "\x0b": "VT",
        "\x0c": "FF",
        "\x0d": "CR",
        "\x0e": "SO",
        "\x0f": "SI",
        "\x10": "DLE",
        "\x11": "DC1",
        "\x12": "DC2",
        "\x13": "DC3",
        "\x14": "DC4",
        "\x15": "NAK",
        "\x16": "SYN",
        "\x17": "ETB",
        "\x18": "CAN",
        "\x19": "EM",
        "\x1a": "SUB",
        "\x1b": "ESC",
        "\x1c": "FS",
        "\x1d": "GS",
        "\x1e": "RS",
        "\x1f": "US",
        "\x7f": "DEL",
        "\x80": "PAD",
        "\x81": "HOP",
        "\x82": "BPH",
        "\x83": "NBH",
        "\x84": "IND",
        "\x85": "NEL",
        "\x86": "SSA",
        "\x87": "ESA",
        "\x88": "HTS",
        "\x89": "HTJ",
        "\x8a": "LTS",
        "\x8b": "PLD",
        "\x8c": "PLU",
        "\x8d": "RI",
        "\x8e": "SS2",
        "\x8f": "SS3",
        "\x90": "DCS",
        "\x91": "PU1",
        "\x92": "PU2",
        "\x93": "STS",
        "\x94": "CCH",
        "\x95": "MW",
        "\x96": "SPA",
        "\x97": "EPA",
        "\x98": "SOS",
        "\x99": "SGCI",
        "\x9a": "SCI",
        "\x9b": "CSI",
        "\x9c": "ST",
        "\x9d": "OSC",
        "\x9e": "PM",
        "\x9f": "APC"
    }
    
    function exec(opcode) {
        var instruction = commands[opcode];
        if (typeof instruction === "function") {
            instruction();
        } else {
            halted = true;
            alert("Unsupported operation: " + opcode + ". Execution halted.");
        }
    }
    
    return {
        init: function (src) {
            group = [];
            ip = 0;
            gp = 0;
            bp = 7;
            halted = false;
            code = toAsciiValue(src);
            output = "";
            tid = void 0;
            
            this.update();
        },
        output: function () {
            return output;
        },
        update: function () {
            var dispCode = code + " ";
            document.getElementById('execcode').innerHTML = 
                dispCode.substring(0, ip) + "<span class='highlight'>" + dispCode[ip] + "</span>" + dispCode.substring(ip + 1);
            
            document.getElementById('output').innerHTML = 
                escapeHTML(output).replace(/[\x00-\x1f\x7f-\x9f]/g, function ($0) { 
                    return "<span class='non-printable'>" + nonprint[$0] + "</span>"; 
                });
                
            document.getElementById('gp').textContent = gp;
            document.getElementById('bp').textContent = bp;
            
            var dispByte = ("0000000" + (~~group[gp]).toString(2)).substr(-8);
            document.getElementById('currgr').innerHTML =
                dispByte.substring(0, 7 - bp) + "<span class='highlight'>" + dispByte[7 - bp] + "</span>" + dispByte.substring(8 - bp);
        },
        step: function () {
            if (ip >= code.length) {
                alert("The program has terminated. Reload the program to run from the beginning.");
                return;
            }
            
            if (halted) {
                alert("Execution has been halted and cannot be recovered");
                return;
            }
            
            exec(code[ip]);
            if (!halted) {
                ip++;
                this.update();
            }
        },
        slow: function () {
            // TODO: Complete this feature. May need to modify run and step.
            if (typeof tid == "number") {
                clearTimeout(tid);
                tid = void 0;
            } else {
                (function auto() {
                    if (!halted && ip < code.length) {
                        interpreter.step();
                        
                        if (!halted) {
                            tid = setTimeout(auto, 200);
                        }
                    }
                })();
            }
        },
        run: function () {
            if (ip >= code.length) {
                alert("The program has terminated. Reload the program to run from the beginning.");
                return;
            }
            
            if (halted) {
                alert("Execution has been halted and cannot be recovered");
                return;
            }
            
            while (ip < code.length) {
                exec(code[ip]);
                
                if (!halted) {
                    ip++;
                } else {
                    // Break out of the loop and update the UI
                    break;
                }
            }
            
            this.update();
        }
    }
})();

document.addEventListener('DOMContentLoaded', function () {

    var $ascii = document.getElementById("ascii");
    var $workspace = document.getElementById("workspace");
    
    $ascii.textContent = toAsciiValue($workspace.value);
    
    $workspace.onkeypress = $workspace.onkeyup = function () {
        $ascii.textContent = toAsciiValue(this.value);
    }
    
    interpreter.init('');
    
    document.getElementById("load").onclick = function () {
        interpreter.init($workspace.value);
    }
    
    document.getElementById("run").onclick = function () {
        interpreter.run();
    }
    
    document.getElementById("step").onclick = function () {
        interpreter.step();
    }
    
});
body {
    font-family: 'Franklin Gothic Book', 'Trebuchet MS', 'Arial', sans-serif;
}

.code {
    font-family: monospace;
    word-wrap: break-word;
    white-space: pre-wrap;
}

pre.code, textarea.code {
    width: 100%;
}

table th {
    padding: 0 10px;
}

table .code {
    width: 100px;
    text-align: center;
}

td {
    border: 1px solid;
}

.highlight {
    background: pink;
}

.non-printable {
    background: black;
    color: white;
    border-radius: 4px;
    margin: 0 1px;
    padding: 0 1px;
}

.box {
    border: 2px groove;
    height: 6em;
}
<h1>Insomnia<sup><a href="http://esolangs.org/wiki/Insomnia">[?]</a></sup></h1>

Currently only supports commands 0-7. Semantics of command 8 and 9 (WHILE loop) is not clearly understood, so it is not implemented.<br>
This interpreter is greatly inspired by <a href="http://www.quirkster.com/iano/js/">Ian's Befunge-93 interpreter</a>.

<h3>Source code</h3>
<textarea cols="80" rows="5" id="workspace" class="code"></textarea>

<h3>ASCII sequence</h3>
<pre id="ascii" class="code"></pre>
<input type="button" id="load" value="Load program" />

<hr>

<h3>Execution</h3>
<pre id="execcode" class="code"></pre>

<input type="button" id="run" value="Run" />
<input type="button" id="step" value="Step" />
<br>

<h3>Debug</h3>
<table>
  <tr>
    <th>Group Pointer</th>
    <td class="code" id="gp"></td>
  </tr>
  <tr>
    <th>Bit Pointer</th>
    <td class="code" id="bp"></td>
  </tr>
  <tr>
    <th>Current group</th>
    <td class="code" id="currgr"></td>
  </tr>
</table>

<h3>Output</h3>
<pre id="output" class="code box"></pre>


5

HQ9 +

Dato che Calvin's Hobbies ha persino usato HQ9 + come esempio, ho deciso di scriverne una rapida implementazione. Bene, implementazione parziale, dato che ho deciso di tralasciare l'accumulatore (potresti odiarmi per quello).

L'interprete, diciamo, è parzialmente golfato. Non so perché l'ho giocato a golf, ma non proprio.

(function () {
    var bottles = (function beerMe(amount) {
        return "012, 01.\n3, 412.5".replace(/\d/g, function (c) {
            return [amount || "No more", " bottles of beer", " on the wall", amount ? "Take one down, pass it around" : "Go to the store and buy some more", ((amount || 100) - 1) || "no more", amount ? "\n\n" : ""][c];
        }) + (amount ? beerMe(amount - 1) : "");
    })(99);

    document.getElementById('run').onclick = function () {
        var source = document.getElementById('source').value,
            output = '';
        source.split('').forEach(function (command) {
            var index = ['H', 'Q', '9'].indexOf(command);
            (index + 1 && (output += ['Hello, world!', source, bottles][index], !0)) || alert('illegal command: ' + command);
        });

        document.getElementById('stdout').value = output;
    };
})();
#source, #stdout {
    display: block;
    width: 100%;
}

#stdout {
    white-space: pre;
    height: 50px;
}

#stdout, #run {
    margin-top: 3px;
}
<div>
    <input type="text" id="source" placeholder="Enter your HQ9+ program here" />
    <textarea id="stdout" wrap="off" readonly></textarea>
    <input type="button" id="run" value="Execute HQ9+" />
</div>


1
il tuo if sul comando 9 è al contrario ... dice vai al negozio e compra un po 'di più ogni volta, ma l'ultima volta
pseudonimo117

1
@ pseudonym117 Oops. Fisso. Una lingua con tre (utili) comandi e riesco ancora a stampare l'output sbagliato. :)
Ingo Bürk,

5
Bug: "1 bottiglia di birra sul muro".
kennytm,

5
Il tuo interprete non supporta l'aumento dell'accumulatore!
jimmy23013,

7
Volevo dire che dovresti almeno ignorare il +comando invece di lanciare un errore.
jimmy23013,

5

Fascio

Penso davvero che questo linguaggio meritasse di avere un interprete e sembrava abbastanza semplice da provare per un non programmatore come me. Spero di aver capito bene. Sembra funzionare per gli esempi che ho provato. Gran parte del codice è plagiato da altre risposte in questa domanda. Mi scuso con i veri programmatori là fuori se ho commesso peccati cardinali nel mio codice :)

Ho inserito l'esempio "Reverse STDIN" dalla pagina di Esolangs.

var ITERS_PER_SEC = 100000;
var TIMEOUT_SECS = 50;
var ERROR_INTERRUPT = "Interrupted by user";
var ERROR_TIMEOUT = "Maximum iterations exceeded";
var ERROR_LOSTINSPACE = "Beam is lost in space";

var code, store, beam, ip_x, ip_y, dir, input_ptr, mem;
var input, timeout, width, iterations, running;

function clear_output() {
document.getElementById("output").value = "";
document.getElementById("stderr").innerHTML = "";
}

function stop() {
running = false;
document.getElementById("run").disabled = false;
document.getElementById("stop").disabled = true;
document.getElementById("clear").disabled = false;
document.getElementById("timeout").disabled = false;
}

function interrupt() {
error(ERROR_INTERRUPT);
}

function error(msg) {
document.getElementById("stderr").innerHTML = msg;
stop();
}

function run() {
clear_output();
document.getElementById("run").disabled = true;
document.getElementById("stop").disabled = false;
document.getElementById("clear").disabled = true;
document.getElementById("input").disabled = false;
document.getElementById("timeout").disabled = false;

code = document.getElementById("code").value;
input = document.getElementById("input").value;
timeout = document.getElementById("timeout").checked;
	
code = code.split("\n");
width = 0;
for (var i = 0; i < code.length; ++i){
	if (code[i].length > width){ 
		width = code[i].length;
	}
}
console.log(code);
console.log(width);
	
running = true;
dir = 0;
ip_x = 0;
ip_y = 0;
input_ptr = 0;
beam = 0;
store = 0;
mem = [];
	
input = input.split("").map(function (s) {
		return s.charCodeAt(0);
	});
	
iterations = 0;

beam_iter();
}

function beam_iter() {
while (running) {
	var inst; 
	try {
		inst = code[ip_y][ip_x];
	}
	catch(err) {
		inst = "";
	}
	switch (inst) {
		case ">":
			dir = 0;
			break;
		case "<":
			dir = 1;
			break;
		case "^":
			dir = 2;
			break;
		case "v":
			dir = 3;
			break;
		case "+":
			if(++beam > 255)
				beam = 0;
			break;
		case "-":
			if(--beam < 0)
				beam = 255;
			break;
		case "@":
			document.getElementById("output").value += String.fromCharCode(beam);
			break;
		case ":":
			document.getElementById("output").value += beam;
			break;
		case "/":
			dir ^= 2;
			break;
		case "\\":
			dir ^= 3;
			break;
		case "!":
			if (beam != 0) {
				dir ^= 1;
			}
			break;
		case "?":
			if (beam == 0) {
				dir ^= 1;
			}
			break;
		case "_":
			switch (dir) {
			case 2:
				dir = 3;
				break;
			case 3:
				dir = 2;
				break;
			}
			break;
		case "|":
			switch (dir) {
			case 0:
				dir = 1;
				break;
			case 1:
				dir = 0;
				break;
			}
			break;
		case "H":
			stop();
			break;
		case "S":
			store = beam;
			break;
		case "L":
			beam = store;
			break;
		case "s":
			mem[beam] = store;
			break;
		case "g":
			store = mem[beam];
			break;
		case "P":
			mem[store] = beam;
			break;
		case "p":
			beam = mem[store];
			break;
		case "u":
			if (beam != store) {
				dir = 2;
			}
			break;
		case "n":
			if (beam != store) {
				dir = 3;
			}
			break;
		case "`":
			--store;
			break;
		case "'":
			++store;
			break;
		case ")":
			if (store != 0) {
				dir = 1;
			}
			break;
		case "(":
			if (store != 0) {
				dir = 0;
			}
			break;
		case "r":
			if (input_ptr >= input.length) {
				beam = 0;
			} else {
				beam = input[input_ptr];
				++input_ptr;
			}
			break;
		}
	// Move instruction pointer
	switch (dir) {
		case 0:
			ip_x++;
			break;
		case 1:
			ip_x--;
			break;
		case 2:
			ip_y--;
			break;
		case 3:
			ip_y++;
			break;
	}
	if (running && (ip_x < 0 || ip_y < 0 || ip_x >= width || ip_y >= code.length)) {
		error(ERROR_LOSTINSPACE);
	}
	++iterations;
	if (iterations > ITERS_PER_SEC * TIMEOUT_SECS) {
		error(ERROR_TIMEOUT);
	}
}
}
<div style="font-size:12px;font-family:Verdana, Geneva, sans-serif;">Code:
    <br>
    <textarea id="code" rows="8" style="overflow:scroll;overflow-x:hidden;width:90%;">v
(>``v
!  H(p`@`p)H
P   H
' 
r 
' 
P 
! 
>^
	</textarea>
    <br>Input:
    <br>
    <textarea id="input" rows="2" style="overflow:scroll;overflow-x:hidden;width:90%;">Reverse this string</textarea>
    <p>Timeout:
        <input id="timeout" type="checkbox" checked="checked">&nbsp;
        <br>
        <br>
        <input id="run" type="button" value="Run" onclick="run()">
        <input id="stop" type="button" value="Stop" onclick="interrupt()" disabled="disabled">
        <input id="clear" type="button" value="Clear" onclick="clear_output()">&nbsp; <span id="stderr" style="color:red"></span>
    </p>Output:
    <br>
    <textarea id="output" rows="6" style="overflow:scroll;width:90%;"></textarea>
</div>


Come non l'ho notato prima? Questo è fantastico! Adoro vedere le lingue salvate dalla Fossa dell'Implementazione. ;)
ETHproductions,

1
Spero non ti dispiaccia, ma ho pulito un po 'la sezione JS.
ETHproductions,

@ETHproductions Non ho alcun problema con questo. Non sono un vero programmatore come ho detto sopra, ma volevo davvero qualcosa per testare alcune idee che hai scatenato con la tua risposta alla sfida Hello World.
MickyT

La funzionalità di timeout al momento non sembra funzionare. Se inserisco un ciclo infinito, si blocca il mio browser, e mi ricordo che una volta si tenta di stampare tutti i caratteri ASCII da !a ~, e averlo sempre tempo dopo i primi tre, anche con timeout disattivato. Daremo un'occhiata tra poco.
ETHproductions

@ETHproductions che sono venuti con lo snippet che ho copiato in gran parte per iniziare questo. Devo ammettere che ho avuto alcuni problemi con i timeout.
MickyT

5

K5

Questo è un wrapper semplice e sottile attorno all'implementazione K basata su JavaScript, oK , e fa riferimento al repository github. Ho già creato un frontend basato su browser molto più bello . oK implementa una porzione molto consistente di K5, oltre a IO, ed è stato usato in passato per risolvere una serie di problemi qui in overflow dello stack. Il codice non è golfato di per sé, ma è ben al di sotto di 1000 righe tra cui commenti, parser, tutte le operazioni primitive, l'interprete e la prettyprinter.

* {
  font-size:12px;
  font-family:Verdana, Geneva, sans-serif;
}
textarea {
  overflow:scroll;
  overflow-x:hidden;
  width:90%;
  font-family:Consolas, Courier New, monospace;
  font-size:10p
}
<script src="http://johnearnest.github.io/ok/oK.js"></script>
<script>
    function runk() {
    	var code = document.getElementById("code").value;
    	var env  = baseEnv();
    	var ret  = run(parse(code), baseEnv());
    	document.getElementById("output").value = format(ret);
    }
</script>

Code:
<br>
<textarea id="code" rows="8">2*!10</textarea>
<p><input id="run" type="button" value="Run" onclick="runk()"></p>
Output:
<br>
<textarea id="output" rows="6" style="overflow:scroll;width:90%;"></textarea>


5

Lo spazio bianco

function interpret() {
    function num(sign, bits) { return sign * parseInt(bits.replace("S", "0").replace("T", "1"), 2); }
    var prog = document.getElementById("prog").value, esc = document.getElementById("esc").checked;
    if (!esc)
        prog = prog.replace(" ", "S").replace("\t", "T").replace("\n", "L");
    prog = prog.replace(/[^STL]/g, "");
    var stack = [], labels = {}, heap = [], input = document.getElementById("in").value, output = document.getElementById("out"), inPos = 0, callStack = [];
    for (var i = 0; i < prog.length; i++) {
        switch (prog[i]) {
            case "S":
                switch (prog[++i]) {
                    case "S":
                        stack.push(num(prog[++i] == "S" ? 1 : -1, prog.slice(++i, prog.indexOf("L", i) - 1)));
                        i = prog.indexOf("L", i);
                        break;
                    case "T":
                        switch (prog[++i]) {
                            case "S":
                                stack.push(stack[stack.length - num(prog[++i] == "S" ? 1 : -1, prog.slice(++i, prog.indexOf("L", i) - 1))]);
                                i = prog.indexOf("L", i);
                                break;
                            case "L":
                                var num = num(prog[++i] == "S" ? 1 : -1, prog.slice(++i, prog.indexOf("L", i) - 1));
                                i = prog.indexOf("L", i);
                                stack.splice(stack.length - num - 1, num);
                                break;
                        }
                        break;
                    case "L":
                        switch (prog[++i]) {
                            case "S":
                                stack.push(stack[stack.length - 1]);
                                break;
                            case "T":
                                stack.push.apply(stack, stack.slice(-2).reverse());
                                break;
                            case "L":
                                stack.pop();
                                break;
                        }
                        break;
                }
                break;
            case "T":
                switch (prog[++i]) {
                    case "S":
                        switch (prog[++i]) {
                            case "S":
                                switch (prog[++i]) {
                                    case "S":
                                        stack.push(stack.pop() + stack.pop());
                                        break;
                                    case "T":
                                        stack.push(stack.pop() - stack.pop());
                                        break;
                                    case "L":
                                        stack.push(stack.pop() * stack.pop());
                                        break;
                                }
                                break;
                            case "T":
                                switch (prog[++i]) {
                                    case "S":
                                        stack.push(Math.floor(stack.pop() / stack.pop()));
                                        break;
                                    case "T":
                                        stack.push(stack.pop() % stack.pop());
                                        break;
                                }
                                break;
                        }
                        break;
                }
                break;
            case "T":
                switch (prog[++i]) {
                    case "S":
                        heap[stack[stack.length - 2]] = stack.pop();
                        stack.pop();
                        break;
                    case "T":
                        stack.push(heap[stack.pop()]);
                        break;
                }
                break;
            case "L":
                switch (prog[++i]) {
                    case "S":
                        switch (prog[++i]) {
                            case "S":
                                output.value += String.fromCharCode(stack.pop());
                                break;
                            case "T":
                                output.value += stack.pop();
                                break;
                        }
                        break;
                    case "T":
                        switch (prog[++i]) {
                            case "S":
                                heap[stack.pop()] = input.charCodeAt(inPos++);
                                break;
                            case "T":
                                heap[stack.pop()] = parseInt(input.slice(inPos, input.indexOf("\n", inPos) - 1));
                                break;
                        }
                }
                break;
            case "L":
                switch (prog[++i]) {
                    case "S":
                        switch (prog[++i]) {
                            case "S":
                                labels[num(1, prog.slice(++i, prog.indexOf("L", i) - 1))] = i = prog.indexOf("L", i);
                                break;
                            case "T":
                                callStack.push(prog.indexOf("L", ++i));
                                i = labels[num(1, prog.slice(i, prog.indexOf("L", i) - 1))];
                                break;
                            case "L":
                                i = labels[num(1, prog.slice(++i, prog.indexOf("L", i) - 1))];
                                break;
                        }
                        break;
                    case "T":
                        switch (prog[++i]) {
                            case "S":
                                if (stack.pop() == 0)
                                    i = labels[num(1, prog.slice(++i, prog.indexOf("L", i) - 1))];
                                else
                                    i = prog.indexOf("L", ++i);
                                break;
                            case "T":
                                if (stack.pop() < 0)
                                    i = labels[num(1, prog.slice(++i, prog.indexOf("L", i) - 1))];
                                else
                                    i = prog.indexOf("L", ++i);
                                break;
                        }
                        break;
                    case "L":
                        i = callStack.pop();
                        break;
                }
                break;
            case "L":
                if (prog[++i] == "L")
                    return JSON.stringify(stack);
                break;
        }
    }
    return JSON.stringify(stack);
}
Program:<br/>
<textarea id="prog" rows="4" cols="60"></textarea><br/>
Input:<br/>
<textarea id="in" rows="4" cols="60"></textarea><br/>
<form>
    Is escaped as <code>STL</code>: <input id="esc" type="checkbox"/><br/>
</form>
<button onclick="document.getElementById('stack').innerText = interpret()">Interpret</button><br/>
Output:<br/>
<textarea id="out" rows="4" cols="60"></textarea><br/>
Resulting stack: <span id="stack"/>


5

Ouroboros

Un linguaggio esoterico creato da me, DLosc, nell'ottobre 2015. Il modello di esecuzione si basa sul fatto che ogni riga di codice è un serpente ouroboros . Il controllo procede dalla testa alla coda e ritorna alla testa; le istruzioni consentono al serpente di ingoiare parte della sua coda o rigurgitare ciò che ha ingoiato, cambiando così il flusso di esecuzione. Tutti i serpenti vengono eseguiti in parallelo. I dati vengono archiviati su uno stack condiviso e su uno stack individuale per ciascun serpente. Per ulteriori informazioni, programmi di esempio e l'interprete più aggiornato, consultare il repository Github .

// Define Stack class
function Stack() {
  this.stack = [];
  this.length = 0;
}
Stack.prototype.push = function(item) {
  this.stack.push(item);
  this.length++;
}
Stack.prototype.pop = function() {
  var result = 0;
  if (this.length > 0) {
    result = this.stack.pop();
    this.length--;
  }
  return result;
}
Stack.prototype.top = function() {
  var result = 0;
  if (this.length > 0) {
    result = this.stack[this.length - 1];
  }
  return result;
}
Stack.prototype.toString = function() {
  return "" + this.stack;
}

// Define Snake class
function Snake(code) {
  this.code = code;
  this.length = this.code.length;
  this.ip = 0;
  this.ownStack = new Stack();
  this.currStack = this.ownStack;
  this.alive = true;
  this.wait = 0;
  this.partialString = this.partialNumber = null;
}
Snake.prototype.step = function() {
  if (!this.alive) {
    return null;
  }
  if (this.wait > 0) {
    this.wait--;
    return null;
  }
  var instruction = this.code.charAt(this.ip);
  var output = null;
  console.log("Executing instruction " + instruction);
  if (this.partialString !== null) {
    // We're in the middle of a double-quoted string
    if (instruction == '"') {
      // Close the string and push its character codes in reverse order
      for (var i = this.partialString.length - 1; i >= 0; i--) {
        this.currStack.push(this.partialString.charCodeAt(i));
      }
      this.partialString = null;
    } else {
      this.partialString += instruction;
    }
  } else if (instruction == '"') {
    this.partialString = "";
  } else if ("0" <= instruction && instruction <= "9") {
    if (this.partialNumber !== null) {
      this.partialNumber = this.partialNumber + instruction;  // NB: concatenation!
    } else {
      this.partialNumber = instruction;
    }
    next = this.code.charAt((this.ip + 1) % this.length);
    if (next < "0" || "9" < next) {
      // Next instruction is non-numeric, so end number and push it
      this.currStack.push(+this.partialNumber);
      this.partialNumber = null;
    }
  } else if ("a" <= instruction && instruction <= "f") {
    // a-f push numbers 10 through 15
    var value = instruction.charCodeAt(0) - 87;
    this.currStack.push(value);
  } else if (instruction == "$") {
    // Toggle the current stack
    if (this.currStack === this.ownStack) {
      this.currStack = this.program.sharedStack;
    } else {
      this.currStack = this.ownStack;
    }
  } else if (instruction == "s") {
    this.currStack = this.ownStack;
  } else if (instruction == "S") {
    this.currStack = this.program.sharedStack;
  } else if (instruction == "l") {
    this.currStack.push(this.ownStack.length);
  } else if (instruction == "L") {
    this.currStack.push(this.program.sharedStack.length);
  } else if (instruction == ".") {
    var item = this.currStack.pop();
    this.currStack.push(item);
    this.currStack.push(item);
  } else if (instruction == "m") {
    var item = this.ownStack.pop();
    this.program.sharedStack.push(item);
  } else if (instruction == "M") {
    var item = this.program.sharedStack.pop();
    this.ownStack.push(item);
  } else if (instruction == "y") {
    var item = this.ownStack.top();
    this.program.sharedStack.push(item);
  } else if (instruction == "Y") {
    var item = this.program.sharedStack.top();
    this.ownStack.push(item);
  } else if (instruction == "\\") {
    var top = this.currStack.pop();
    var next = this.currStack.pop()
    this.currStack.push(top);
    this.currStack.push(next);
  } else if (instruction == "@") {
    var c = this.currStack.pop();
    var b = this.currStack.pop();
    var a = this.currStack.pop();
    this.currStack.push(b);
    this.currStack.push(c);
    this.currStack.push(a);
  } else if (instruction == ";") {
    this.currStack.pop();
  } else if (instruction == "+") {
    var b = this.currStack.pop();
    var a = this.currStack.pop();
    this.currStack.push(a + b);
  } else if (instruction == "-") {
    var b = this.currStack.pop();
    var a = this.currStack.pop();
    this.currStack.push(a - b);
  } else if (instruction == "*") {
    var b = this.currStack.pop();
    var a = this.currStack.pop();
    this.currStack.push(a * b);
  } else if (instruction == "/") {
    var b = this.currStack.pop();
    var a = this.currStack.pop();
    this.currStack.push(a / b);
  } else if (instruction == "%") {
    var b = this.currStack.pop();
    var a = this.currStack.pop();
    this.currStack.push(a % b);
  } else if (instruction == "_") {
    this.currStack.push(-this.currStack.pop());
  } else if (instruction == "I") {
    var value = this.currStack.pop();
    if (value < 0) {
      this.currStack.push(Math.ceil(value));
    } else {
      this.currStack.push(Math.floor(value));
    }
  } else if (instruction == ">") {
    var b = this.currStack.pop();
    var a = this.currStack.pop();
    this.currStack.push(+(a > b));
  } else if (instruction == "<") {
    var b = this.currStack.pop();
    var a = this.currStack.pop();
    this.currStack.push(+(a < b));
  } else if (instruction == "=") {
    var b = this.currStack.pop();
    var a = this.currStack.pop();
    this.currStack.push(+(a == b));
  } else if (instruction == "!") {
    this.currStack.push(+ !this.currStack.pop());
  } else if (instruction == "?") {
    this.currStack.push(Math.random());
  } else if (instruction == "n") {
    output = "" + this.currStack.pop();
  } else if (instruction == "o") {
    output = String.fromCharCode(this.currStack.pop());
  } else if (instruction == "r") {
    var input = this.program.io.getNumber();
    this.currStack.push(input);
  } else if (instruction == "i") {
    var input = this.program.io.getChar();
    this.currStack.push(input);
  } else if (instruction == "(") {
    this.length -= Math.floor(this.currStack.pop());
    this.length = Math.max(this.length, 0);
  } else if (instruction == ")") {
    this.length += Math.floor(this.currStack.pop());
    this.length = Math.min(this.length, this.code.length);
  } else if (instruction == "w") {
    this.wait = this.currStack.pop();
  }
  // Any unrecognized character is a no-op
  if (this.ip >= this.length) {
    // We've swallowed the IP, so this snake dies
    this.alive = false;
    this.program.snakesLiving--;
  } else {
    // Increment IP and loop if appropriate
    this.ip = (this.ip + 1) % this.length;
  }
  return output;
}
Snake.prototype.getHighlightedCode = function() {
  var result = "";
  for (var i = 0; i < this.code.length; i++) {
    if (i == this.length) {
      result += '<span class="swallowedCode">';
    }
    if (i == this.ip) {
      if (this.wait > 0) {
        result += '<span class="nextActiveToken">';
      } else {
        result += '<span class="activeToken">';
      }
      result += escapeEntities(this.code.charAt(i)) + '</span>';
    } else {
      result += escapeEntities(this.code.charAt(i));
    }
  }
  if (this.length < this.code.length) {
    result += '</span>';
  }
  return result;
}

// Define Program class
function Program(source, speed, io) {
  this.sharedStack = new Stack();
  this.snakes = source.split(/\r?\n/).map(function(snakeCode) {
    var snake = new Snake(snakeCode);
    snake.program = this;
    snake.sharedStack = this.sharedStack;
    return snake;
  }.bind(this));
  this.snakesLiving = this.snakes.length;
  this.io = io;
  this.speed = speed || 10;
  this.halting = false;
}
Program.prototype.run = function() {
  this.step();
  if (this.snakesLiving) {
    this.timeout = window.setTimeout(this.run.bind(this), 1000 / this.speed);
  }
}
Program.prototype.step = function() {
   for (var s = 0; s < this.snakes.length; s++) {
    var output = this.snakes[s].step();
    if (output) {
      this.io.print(output);
    }
  }
  this.io.displaySource(this.snakes.map(function (snake) {
      return snake.getHighlightedCode();
    }).join("<br>"));
 }
Program.prototype.halt = function() {
  window.clearTimeout(this.timeout);
}

var ioFunctions = {
  print: function (item) {
    var stdout = document.getElementById('stdout');
    stdout.value += "" + item;
  },
  getChar: function () {
    if (inputData) {
      var inputChar = inputData[0];
      inputData = inputData.slice(1);
      result = inputChar.charCodeAt(0);
    } else {
      result = -1;
    }
    var stdinDisplay = document.getElementById('stdin-display');
    stdinDisplay.innerHTML = escapeEntities(inputData);
    return result;
  },
  getNumber: function () {
    while (inputData && (inputData[0] < "0" || "9" < inputData[0])) {
      inputData = inputData.slice(1);
    }
    if (inputData) {
      var inputNumber = inputData.match(/\d+/)[0];
      inputData = inputData.slice(inputNumber.length);
      result = +inputNumber;
    } else {
      result = -1;
    }
    var stdinDisplay = document.getElementById('stdin-display');
    stdinDisplay.innerHTML = escapeEntities(inputData);
    return result;
  },
  displaySource: function (formattedCode) {
    var sourceDisplay = document.getElementById('source-display');
    sourceDisplay.innerHTML = formattedCode;
  }
};
var program = null;
var inputData = null;
function showEditor() {
  var source = document.getElementById('source'),
    sourceDisplayWrapper = document.getElementById('source-display-wrapper'),
    stdin = document.getElementById('stdin'),
    stdinDisplayWrapper = document.getElementById('stdin-display-wrapper');
  
  source.style.display = "block";
  stdin.style.display = "block";
  sourceDisplayWrapper.style.display = "none";
  stdinDisplayWrapper.style.display = "none";
  
  source.focus();
}
function hideEditor() {
  var source = document.getElementById('source'),
    sourceDisplay = document.getElementById('source-display'),
    sourceDisplayWrapper = document.getElementById('source-display-wrapper'),
    stdin = document.getElementById('stdin'),
    stdinDisplay = document.getElementById('stdin-display'),
    stdinDisplayWrapper = document.getElementById('stdin-display-wrapper');
  
  source.style.display = "none";
  stdin.style.display = "none";
  sourceDisplayWrapper.style.display = "block";
  stdinDisplayWrapper.style.display = "block";
  
  var sourceHeight = getComputedStyle(source).height,
    stdinHeight = getComputedStyle(stdin).height;
  sourceDisplayWrapper.style.minHeight = sourceHeight;
  sourceDisplayWrapper.style.maxHeight = sourceHeight;
  stdinDisplayWrapper.style.minHeight = stdinHeight;
  stdinDisplayWrapper.style.maxHeight = stdinHeight;
  sourceDisplay.textContent = source.value;
  stdinDisplay.textContent = stdin.value;
}
function escapeEntities(input) {
  return input.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
function resetProgram() {
  var stdout = document.getElementById('stdout');
  stdout.value = null;
  if (program !== null) {
    program.halt();
  }
  program = null;
  inputData = null;
  showEditor();
}
function initProgram() {
  var source = document.getElementById('source'),
    stepsPerSecond = document.getElementById('steps-per-second'),
    stdin = document.getElementById('stdin');
  program = new Program(source.value, +stepsPerSecond.innerHTML, ioFunctions);
  hideEditor();
  inputData = stdin.value;
}
function runBtnClick() {
  if (program === null || program.snakesLiving == 0) {
    resetProgram();
    initProgram();
  } else {
    program.halt();
    var stepsPerSecond = document.getElementById('steps-per-second');
    program.speed = +stepsPerSecond.innerHTML;
  }
  program.run();
}
function stepBtnClick() {
  if (program === null) {
    initProgram();
  } else {
    program.halt();
  }
  program.step();
}
function sourceDisplayClick() {
  resetProgram();
}
.container {
    width: 100%;
}
.so-box {
    font-family:'Helvetica Neue', Arial, sans-serif;
    font-weight: bold;
    color: #fff;
    text-align: center;
    padding: .3em .7em;
    font-size: 1em;
    line-height: 1.1;
    border: 1px solid #c47b07;
    -webkit-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3), 0 2px 0 rgba(255, 255, 255, 0.15) inset;
    text-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
    background: #f88912;
    box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3), 0 2px 0 rgba(255, 255, 255, 0.15) inset;
}
.control {
    display: inline-block;
    border-radius: 6px;
    float: left;
    margin-right: 25px;
    cursor: pointer;
}
.option {
    padding: 10px 20px;
    margin-right: 25px;
    float: left;
}
h1 {
    text-align: center;
    font-family: Georgia, 'Times New Roman', serif;
}
a {
    text-decoration: none;
}
input, textarea {
    box-sizing: border-box;
}
textarea {
    display: block;
    white-space: pre;
    overflow: auto;
    height: 100px;
    width: 100%;
    max-width: 100%;
    min-height: 25px;
}
span[contenteditable] {
    padding: 2px 6px;
    background: #cc7801;
    color: #fff;
}
#stdout-container, #stdin-container {
    height: auto;
    padding: 6px 0;
}
#reset {
    float: right;
}
#source-display-wrapper , #stdin-display-wrapper{
    display: none;
    width: 100%;
    height: 100%;
    overflow: auto;
    border: 1px solid black;
    box-sizing: border-box;
}
#source-display , #stdin-display{
    font-family: monospace;
    white-space: pre;
    padding: 2px;
}
.activeToken {
    background: #f93;
}
.nextActiveToken {
    background: #bbb;
}
.swallowedCode{
    color: #999;
}
.clearfix:after {
    content:".";
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
}
.clearfix {
    display: inline-block;
}
* html .clearfix {
    height: 1%;
}
.clearfix {
    display: block;
}
<!--
Designed and written 2015 by D. Loscutoff
Much of the HTML and CSS was taken from this Befunge interpreter by Ingo Bürk: http://codegolf.stackexchange.com/a/40331/16766
-->
<h1><a href="https://github.com/dloscutoff/Esolangs/tree/master/Ouroboros">Ouroboros</a></h1>
<div class="container">
    <textarea id="source" placeholder="Enter your program here" wrap="off"></textarea>
    <div id="source-display-wrapper" onclick="sourceDisplayClick()">
        <div id="source-display"></div>
    </div>
</div>
<div id="stdin-container" class="container">
    <textarea id="stdin" placeholder="Input" wrap="off"></textarea>
    <div id="stdin-display-wrapper" onclick="stdinDisplayClick()">
        <div id="stdin-display"></div>
    </div>
</div>
<div id="controls-container" class="container clearfix">
    <input type="button" id="run" class="control so-box" value="Run" onclick="runBtnClick()" />
    <input type="button" id="pause" class="control so-box" value="Pause" onclick="program.halt()" />
    <input type="button" id="step" class="control so-box" value="Step" onclick="stepBtnClick()" />
    <input type="button" id="reset" class="control so-box" value="Reset" onclick="resetProgram()" />
</div>
<div id="stdout-container" class="container">
    <textarea id="stdout" placeholder="Output" wrap="off" readonly></textarea>
</div>
<div id="options-container" class="container">
    <div class="option so-box">Steps per Second: <span id="steps-per-second" contenteditable>10</span>
    </div>
</div>

Fare

  • Output di debug: contenuto di stack; la quantità di input è rimasto a farsi
  • Durante l'esecuzione, codice con istruzioni attuali visualizzazione evidenziata e porzioni ingestione di code in grigio fatto

4

oOo CODICE

Un interprete molto semplice per oOo CODE (la prima volta che utilizzo javascript). oOo CODICE è un linguaggio esoterico basato su Brainfuck che utilizza lettere maiuscole e minuscole per memorizzare le informazioni, il testo effettivo non ha importanza. Poiché oOo CODE si basa su Brainfuck, ho riutilizzato una delle risposte di Brainfuck e ho aggiunto una funzione per tradurre oOo CODE in Brainfuck.

var NUM_CELLS = 30000;
var ITERS_PER_SEC = 100000;
var TIMEOUT_MILLISECS = 5000;
var ERROR_BRACKET = "Mismatched brackets";
var ERROR_TIMEOUT = "Timeout";
var ERROR_INTERRUPT = "Interrupted by user";

var code, input, wrap, timeout, eof, loop_stack, loop_map;
var running, start_time, code_ptr, input_ptr, cell_ptr, cells, iterations;

function clear_output() {
  document.getElementById("output").value = "";
  document.getElementById("stderr").innerHTML = "";
}

function stop() {
  running = false;
  document.getElementById("run").disabled = false;
  document.getElementById("stop").disabled = true;
  document.getElementById("clear").disabled = false;
  document.getElementById("wrap").disabled = false;
  document.getElementById("timeout").disabled = false;
  document.getElementById("eof").disabled = false;
}

function interrupt() {
  error(ERROR_INTERRUPT);
}

function error(msg) {
  document.getElementById("stderr").innerHTML = msg;
  stop();
}

function oOoCODE(code){
    code = code.match(/[a-z]/gi).join('');
    code = code.match(/.../g);
    for (var i = 0; i<code.length; i++) {
        code[i] = [/[A-Z]/.test(code[i][0]),/[A-Z]/.test(code[i][1]),/[A-Z]/.test(code[i][2])];
        if (code[i][0]) {
            if (code[i][1]) {
                if (code[i][2]) {
                    code[i] = ",";
                } else {
                    code[i] = ".";
                }
            } else {
                if (code[i][2]) {
                    code[i] = "+";
                } else {
                    code[i] = "-";
                }
            }
        } else {
            if (code[i][1]) {
                if (code[i][2]) {
                    code[i] = "]";
                } else {
                    code[i] = "[";
                }
            } else {
                if (code[i][2]) {
                    code[i] = ">";
                } else {
                    code[i] = "<";
                }
            }
        }
    }
    return code.join('');
}

function run() {
  clear_output();
  
  document.getElementById("run").disabled = true;
  document.getElementById("stop").disabled = false;
  document.getElementById("clear").disabled = true;
  document.getElementById("wrap").disabled = true;
  document.getElementById("timeout").disabled = true;
  document.getElementById("eof").disabled = true;

  code = document.getElementById("code").value;
  input = document.getElementById("input").value;
  wrap = document.getElementById("wrap").value;
  timeout = document.getElementById("timeout").checked;
  eof = document.getElementById("eof").value;
  
  code = oOoCODE(code);
  
  loop_stack = [];
  loop_map = {};

  for (var i = 0; i < code.length; ++i) {
    if (code[i] == "[") {
      loop_stack.push(i);

    } else if (code[i] == "]") {
      if (loop_stack.length == 0) {
        error(ERROR_BRACKET);
        return;

      } else {
        var last_bracket = loop_stack.pop();
        loop_map[last_bracket] = i;
        loop_map[i] = last_bracket;
      }
    }
  }

  if (loop_stack.length > 0) {
    error(ERROR_BRACKET);
    return;
  }

  running = true;
  start_time = Date.now();
  code_ptr = 0;
  input_ptr = 0;
  cell_ptr = Math.floor(NUM_CELLS / 2);
  cells = {};
  iterations = 0;

  bf_iter(1);
}

function bf_iter(niters) {
  if (code_ptr >= code.length || !running) {
    stop();
    return;
  }

  var iter_start_time = Date.now();

  for (var i = 0; i < niters; ++i) {
    if (cells[cell_ptr] == undefined) {
      cells[cell_ptr] = 0;
    }

    switch (code[code_ptr]) {
      case "+":
        if ((wrap == "8" && cells[cell_ptr] == 255) ||
            (wrap == "16" && cells[cell_ptr] == 65535) || 
            (wrap == "32" && cells[cell_ptr] == 2147483647)) {
            cells[cell_ptr] = 0;
        } else {
          cells[cell_ptr]++;
        }
        break;
        
      case "-":
        if (cells[cell_ptr] == 0){
          if (wrap == "8"){ cells[cell_ptr] = 255; }
          if (wrap == "16"){ cells[cell_ptr] = 65535; }
          if (wrap == "32"){ cells[cell_ptr] = 2147483647; }    
        } else {
          cells[cell_ptr]--;
        }
        break;
      
      case "<": cell_ptr--; break;
      case ">": cell_ptr++; break;

      case ".":
        document.getElementById("output").value += String.fromCharCode(cells[cell_ptr]);
        break;

      case ",":
        if (input_ptr >= input.length) {
          if (eof != "nochange") {
            cells[cell_ptr] = parseInt(eof);
          }
        } else {
          cells[cell_ptr] = input.charCodeAt(input_ptr);
          input_ptr++;
        }
        break;

      case "[":
        if (cells[cell_ptr] == 0) {
          code_ptr = loop_map[code_ptr];
        }
        break;

      case "]":
        if (cells[cell_ptr] != 0) {
          code_ptr = loop_map[code_ptr];
        }
        break;
    }

    code_ptr++;
    iterations++;

    if (timeout && Date.now() - start_time > TIMEOUT_MILLISECS) {
      error(ERROR_TIMEOUT);
      return;
    }
  }

  setTimeout(function() { bf_iter(ITERS_PER_SEC * (Date.now() - iter_start_time)/1000) }, 0);
}
<div style="font-size:12px;font-family:Verdana, Geneva, sans-serif;">
  <div style="float:left; width:50%;">
    Code:
    <br>
    <textarea id="code" rows="4" style="overflow:scroll;overflow-x:hidden;width:90%;">JuLIeT
   O rOMeO, RoMEo! WHeREfOrE art tHoU RoMEo?
   DEnY ThY FaTHeR AnD ReFuse ThY NaME;
   oR, If ThoU wiLT not, BE but SWoRn mY loVe,
   aND i'Ll NO lONgER bE A cAPuLEt.
ROMeO
   [AsIdE] ShALl I HEar moRE, or sHAlL I sPEaK At THiS?
JuLIeT
   'TiS BUt Thy NamE thAt iS my EneMy;
   tHou ARt ThYSeLF, tHOUgH noT a mOntAguE.
   whAt's MOnTagUe? iT is Nor HanD, noR foOt,
   nOR arm (...)  </textarea>
    <br>Input:
    <br>
    <textarea id="input" rows="2" style="overflow:scroll;overflow-x:hidden;width:90%;"></textarea>
    <p>
      Wrap:
      <select id="wrap">
        <option value="8">8-bit</option>
        <option value="16">16-bit</option>
        <option value="32">32-bit</option>
      </select>
      &nbsp;
      Timeout:
      <input id="timeout" type="checkbox" checked="true" />&nbsp; EOF:
      <select id="eof">
        <option value="nochange">Same</option>
        <option value="0">0</option>
        <option value="-1">-1</option>
      </select>
    </p>
  </div>
  <div style="float:left; width:50%;">
    Output:
    <br>
    <textarea id="output" rows="6" style="overflow:scroll;width:90%;"></textarea>
    <p>
      <input id="run" type="button" value="Run" onclick="run()" />
      <input id="stop" type="button" value="Stop" onclick="interrupt()" disabled="true" />
      <input id="clear" type="button" value="Clear" onclick="clear_output()" />
      &nbsp;
      <span id="stderr" style="color:red"></span>
    </p>
  </div>
</div>


1
Ha bisogno di più punti e virgola. L'ASI è opera del diavolo.
nyuszika7h,

@ nyuszika7h Interessante, non sapevo che funzionasse in questo modo ... (programmatore python) Il codice senza punti e virgola proveniva dalla risposta originale di Brainfuck da Sp3000, quindi non ho notato la mancanza di punti e virgola.
Def

@ Sp3000 Nessun problema, ho scritto la mia risposta per divertimento e per imparare un po 'di javascript, non per la generosità
Def

4

STATA

Modifica: aggiunta sostituzione e verifica la generazione.

Supporta alcune parti di visualizzazione, valori, elenco, generazione e impostazione obs. Inoltre, ha alcuni supporti per la creazione e l'utilizzo di macro (variabili STATA). Supporta operazioni sufficienti per alcune delle risposte più semplici che sono state pubblicate su questo sito, come Evolution di "Hello World!" , Genera la sequenza Stöhr , Fammi un albero dell'alfabeto (sostituisci le virgolette singole con le virgolette doppie e rendila 3 righe anziché 1). Questo è un lavoro in corso e spero di continuare presto, ma ho pensato che avrei almeno messo qualcosa qui per ora.

<html>
<body>
Input
<textarea id="input"></textarea>
<br/>
Code
<textarea id="code"></textarea>
<br/>
<button>Run</button>
<br/>Output:
<textarea id="output"></textarea>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript">

$(function(){
    _N=0
    dataset=[];
    locals=[];
    globals=[];
    $output=$('#output');
    $input=$('#input');
    inputs=[];
    commands=[];
    comTable = [];
    comTable['di'] = 'display';
    comTable['dis'] = 'display';
    comTable['disp'] = 'display';
    comTable['displ'] = 'display';
    comTable['displa'] = 'display';
    comTable['display'] = 'display';
    comTable['loc'] = 'local';
    comTable['loca'] = 'local';
    comTable['local'] = 'local';
    comTable['gl'] = 'global';
    comTable['glo'] = 'global';
    comTable['glob'] = 'global';
    comTable['globa'] = 'global';
    comTable['global'] = 'global';
    comTable['set']='set';
    comTable['g'] = 'generate';
    comTable['ge'] = 'generate';
    comTable['gen'] = 'generate';
    comTable['gene'] = 'generate';
    comTable['gener'] = 'generate';
    comTable['genera'] = 'generate';
    comTable['generat'] = 'generate';
    comTable['generate'] = 'generate';
    comTable['replace'] = 'replace';
    comTable['l']='list';
    comTable['li']='list';
    comTable['lis']='list';
    comTable['list']='list';
    comTable['forv']='forvalues';
    comTable['forva']='forvalues';
    comTable['forval']='forvalues';
    comTable['forvalu']='forvalues';
    comTable['forvalue']='forvalues';
    comTable['forvalues']='forvalues';
    comTable['}']='No Operation';
    opTable=[];
    opTable['display']=[];
    opTable['display']['_r']='_request';
    opTable['display']['_re']='_request';
    opTable['display']['_req']='_request';
    opTable['display']['_requ']='_request';
    opTable['display']['_reque']='_request';
    opTable['display']['_reques']='_request';
    opTable['display']['_request']='_request';
    opTable['set']=[];
    opTable['set']['ob']='obs';
    opTable['set']['obs']='obs';
});
$('button').click(function () {
    _N=0
    dataset=[];
    inputNum=0;
    inputs=$input.val().split('\n');
    $output.val('');
    locals=[];
    globals=[];
    var code = $('#code').val();
    commands = code.split('\n');
    var tokens = [];
    commands.forEach(function (entry) {
        tokens.push(entry.match(/(?:[^\s"]+|"[^"]*")+/g) );
    });
    var error = '';
    var nextIndex=0;
    $.each(tokens,function (index,entry) {
        if(nextIndex!==index){
            return true;
        }
        var tok = entry[0];
        entry[0] = comTable[tok];
        if (entry[0] === undefined) {
            error = tok + ' is not a recognized command';
            outputError(error);
            return false;
        }
        nextIndex+=execute(entry,index);
        if(!nextIndex){
            return false;
        }
    });
});

function execute(command,ind){
    switch(command[0]){
        case 'display':
            return executeDisplay(command);
        case 'local':
            return executeLocal(command);
        case 'global':
            return executeGlobal(command);
        case 'set':
            return executeSet(command);
        case 'generate':
            return executeGenerate(command);
        case 'replace':
            return executeReplace(command);
        case 'list':
            return executeList(command);
        case 'forvalues':
            return executeForvalues(command,ind);
    }
}

function executeForvalues(command,ind){
    var re=/(\w+)=(.+)\((.+)\)(.+){/;
    var arr=re.exec(command[1]);
    if(arr==null){
        outputError('invalid format to command forvalues: '+command[1]);
        return false;
    }
    var locName=evaluate(arr[1],0);
    var i=Number(evaluate(arr[2],0));
    var increment=Number(evaluate(arr[3],0));
    var maximum=evaluate(arr[4],0);
    console.log(locName+' '+i+' '+increment+' '+maximum);
    maximum=Number(maximum);
    var curInd=ind+1;
    for(;i<=maximum;i+=increment){
        locals[locName]=i;
        globals['_'+locName]=i;
        for(curInd=ind+1;commands[curInd]!=='}';curInd++){
            var entry=commands[curInd].match(/(?:[^\s"]+|"[^"]*")+/g);
            var tok = entry[0];
            entry[0] = comTable[tok];
            if (entry[0] === undefined) {
                error = tok + ' is not a recognized command';
                outputError(error);
                return false;
            }
            console.log(entry);
            if(!execute(entry)){
                return false;
            }
            console.log($output.val());
        }
    }
    return curInd-ind;
}

function executeList(command){
    var out='\t'+Object.keys(dataset).join('\t')+'\n';
    for(var i=0;i<_N;i++){
        out+=(i+1)+'\t';
        Object.keys(dataset).forEach(function(element){
            out+=dataset[element][i]===undefined?'.':dataset[element][i]+'\t';
        })
        out+='\n';
    }
    $output.val(function(i,val){
        return val+out;
    });
    return 1;
}

function executeGenerate(command){
    var parts=command[1].split('=');
    if(dataset[parts[0]]){
        outputError('variable '+parts[0]+' already exists.');
        return false;
    }
    dataset[parts[0]]=[];
    for(var i=0;i<_N;i++){
        dataset[parts[0]][i]=evaluateVariables(parts[1],i);
    }
    return 1;
}

function executeReplace(command){
    var parts=command[1].split('=');
    if(!dataset[parts[0]]){
        outputError('variable '+parts[0]+' does not exist.');
        return false;
    }
    for(var i=0;i<_N;i++){
        dataset[parts[0]][i]=evaluateVariables(parts[1],i);
    }
    return 1;
}

function evaluateVariables(str,i){
    return eval(str.replace('_n',i+1));
}

function executeSet(command){
    if(opTable['set'][command[1]]=='obs'){
        _N=parseInt(command[2],10);
        return 1;
    }
    outputError('invalid option for command set: '+command[1]);
    return false;
}

function executeLocal(command){
    var parts=command[1].split('=');
    var name,value;
    if(parts.length==1){
        var re0=/^\+\+(\w+)$/;
        var re1=/^--(\w+)$/;
        var re2=/^(\w+)\+\+$/;
        var re3=/^(\w+)--$/;
        var arr=re0.exec(parts[0])||re1.exec(parts[0])||re2.exec(parts[0])||re3.exec(parts[0]);
        if(arr!=null){
            name=arr[1];
            if(parts[0].indexOf('-')>-1){
                value=globals[name]-1;
            }
            else{
                value=globals[name]+1;
            }
        }
        else{
            parts[1]=command[2];
        }
    }
    if(!value){
        value=evaluate(parts[1],0);
    }
    if(typeof value==='undefined'){
        return false;
    }
    if(!name){
        name=evaluate(parts[0]);
    }
    locals[name]=value;
    globals['_'+name]=value;
    return 1;
}

function executeGlobal(command){
    var parts=command[1].split('=');
    var name,value;
    if(parts.length==1){
        var re0=/^\+\+(\w+)$/;
        var re1=/^--(\w+)$/;
        var re2=/^(\w+)\+\+$/;
        var re3=/^(\w+)--$/;
        var arr=re0.exec(parts[0])||re1.exec(parts[0])||re2.exec(parts[0])||re3.exec(parts[0]);
        if(arr!=null){
            name=arr[1];
            if(parts[0].indexOf('-')>-1){
                value=globals[name]-1;
            }
            else{
                value=Number(globals[name])+1;
            }
        }
        else{
            parts[1]=command[2];
        }
    }
    if(!value){
        value=evaluate(parts[1],0);
    }
    if(typeof value==='undefined'){
        return false;
    }
    if(!name){
        name=evaluate(parts[0]);
    }
    if(name.charAt(0)=='_'){
        locals[name.substring(1)]=value;
    }
    globals[name]=value;
    return 1;
}

function executeDisplay(command){
    for(var i=1;i<command.length;i++){
        var comVal=command[i];
        $output.val(function(ind,val){
            var re=/^(\w+)/;
            var arr=re.exec(command[i]);
            if(arr!==null&&opTable['display'][arr[0]]=='_request'){
                re=/^\w+\((\w+)\)/;
                arr=re.exec(command[i]);
                var input=getInput();
                globals[arr[1]]=input;
                if(arr[1].charAt(0)=='_'){
                    locals[arr[1].substring(1)]=input;
                }
                return val;
            }
            return val+evaluate(command[i],0)+'\n';
        });
    }
    return 1;
}

function getInput(){
    var x=inputs[inputNum];
    inputNum++;
    return x;
}

function evaluate(str,captured){
    str=String(str);
    var index=str.indexOf('"');
    if(index==-1){
        return evaluate2(str);
    }
    var secondIndex=str.indexOf('"',index+1);
    while(secondIndex>0&&str.charAt(secondIndex-1)=='\\'){
        secondIndex=str.indexOf('"',secondIndex+1);
    }
    if(secondIndex<0){
        if(!captured){
            var error ='unmatched quotes';
            outputError(error);
            return undefined;
        }
        return '';
    }
    return (index>0?evaluate2(str.substring(0,index)):'')+evaluate2(str.substring(index,secondIndex+1))+(secondIndex<str.length-1?evaluate(str.substring(secondIndex)):'');
}

function evaluate2(str){
    var index=str.indexOf('`');
    if(index==-1){
        return evaluate3(str);
    }
    var secondIndex=str.indexOf('\'',index+1);
    while(secondIndex>0&&str.charAt(secondIndex-1)=='\\'){
        secondIndex=str.indexOf('\'',secondIndex+1);
    }
    if(secondIndex<0){
        return evaluate3(str);
    }
    var value=locals[str.substring(index+1,secondIndex)];
    if(typeof value==='undefined'){
        value='';
    }
    return evaluate((index>0?str.substring(0,index):'')+value+(secondIndex<str.length-1?str.substring(secondIndex+1):''));
}

function evaluate3(str){
    var re=/\$(\w+)/;
    var arr=re.exec(str);
    if(arr!==null){
        var index=arr.index;
        var length=arr[0].length;
        var value=globals[arr[1]];
        str=str.substring(0,index)+value+str.substring(index+length);
        return evaluate(str);
    }
    try {
        var value=eval(str.replace('_N',_N));
        return value;
    }catch(err){
        console.log(str);
        return str;
    }
}

function evaluate4(str){
    try {
        var value=eval(str);
        return value;
    }catch(err){
        console.log(str);
        return undefined;
    }
}

function outputError(error) {
    $output.val(function(ind,val){
        return val+error+'\n';
    });
}
</script>
</body>
</html>

Bug: in generateun'espressione, _nviene sostituito solo il primo .
LegionMammal978,

Immagino che il metodo di sostituzione JS sostituisca solo la prima istanza. C'è un modo di cambiarlo?
segna il

str.replace(/_n/g,i+1)
LegionMammal978,

ಠ_ಠ hai usato jQuery.
Conor O'Brien,

4

Labirinto

Un interprete per Labyrinth, un linguaggio assolutamente fantastico! (Il mio interprete non ha numeri interi grandi ...)

/*jshint esnext: true */
//Note labyrinth X Y are swapped!
//Syntax highlighting?
//Bigint library?
//Use: https://developers.google.com/web/updates/2014/05/Web-Animations-element.animate-is-now-in-Chrome-36
//Save option 
//a => ASCII code (Explanation of the commands)

var p; //pointer
var labyrinth; //code
var main, auxiliary; //stacks, main.length-1=top
var direction; //N=0,E=1,S=2,W=3;
var inpLoc;
var sucide;
var step;
var debug;

var spiders = false;

var pointerIcons = ["▲", "►", "▼", "◄", "X"];

function mod(x, y) {
  return ((x % y) + y) % y;
}

Array.prototype.top = function() {
  if (this.length === 0) {
    return 0;
  }
  return this[this.length - 1];
};

Array.prototype._pop = Array.prototype.pop;
Array.prototype.pop = function(x) {
  var temp = this._pop();
  return temp !== undefined ? temp : 0;
};

function reset() {
  p = [0, 0];
  labyrinth = lab.innerHTML.replace(/\[/g, " ").replace(/\]/g, " ").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/\n*$|(<br>)*$/, "").split(/<br>|\n/g);
  var maxLength = 0;
  for (var i = 0; i < labyrinth.length; i++) {
    if (maxLength < labyrinth[i].length)
      maxLength = labyrinth[i].length;
  }

  for (i = 0; i < labyrinth.length; i++) {
    labyrinth[i] = (labyrinth[i] + " ".repeat(maxLength - labyrinth[i].length)).split("");
  }

  //Pointer pos
  loop:
    for (i = 0; i < labyrinth.length; i++) {
      for (j = 0; j < labyrinth[i].length; j++) {
        if (labyrinth[i][j] !== " ") {
          p = [j, i];
          break loop;
        }
      }
    }

  main = [];
  auxiliary = [];
  direction = 1;
  sucide = false;
  inpLoc = 0;
  step = 1;
  O.value = "";
}

function run() {
  reset();
  if (debug) {
    spiderContainer.innerHTML = "";
    debugButton.disabled = false;
    lab.contentEditable = false;
    stepButton.disabled = false;
  }
  //Start if
  if (lab.innerHTML.replace(/\[/g, "").replace(/\]/g, "").replace(/<br>|\n/g, "") !== "") {
    if (!debug) {
      while (!sucide) {
        updatePointer();
      }
    } else {
      updatePointer();
    }
  } else {
    stepButton.disabled = "disabled";
    lab.contentEditable = "true";
  }
}

function updatePointer() {
  if (sucide) {
    stepButton.disabled = "disabled";
    lab.contentEditable = "true";
    pointerOverlay.innerHTML = "";
    return -1; //End
  }
  stepDiv.innerHTML = step;
  step++;
  execChar(labyrinth[p[1]][p[0]]);


  var ret = updateDirection();
  //If there are walls
  if (ret != -1) {
    direction = mod(direction, 4);

    if (direction === 0) {
      p[1] --;
    } else if (direction == 1) {
      p[0] ++;
    } else if (direction == 2) {
      p[1] ++;
    } else if (direction == 3) {
      p[0] --;
    }
  }
  deb.value =
    "Pointer: " + p +
    "\nCommand: " + labyrinth[p[1]][p[0]] +
    "\nMain [" + main + " | " + auxiliary.slice().reverse() + "] Auxiliary";
  if (debug) {
    pointerOverlay.innerHTML = "\n".repeat(p[1]) + " ".repeat(p[0]) + (pointerIcons[ret == -1 ? 4 : direction]);
  }

}

function updateGrid() {
  lab.innerHTML = "";
  labyrinth.forEach(s => lab.innerHTML += s.join("") + "\n");
}

function rotVert(rotWhich) {
  var temp;
  for (var i = 0; i < labyrinth.length; i++) {
    if (i === 0) {
      temp = labyrinth[0][rotWhich];
    }
    if (i == labyrinth.length - 1) {
      labyrinth[i][rotWhich] = temp;
    } else {
      labyrinth[i][rotWhich] = labyrinth[i + 1][rotWhich];
    }
    if (labyrinth[i][rotWhich] === undefined) {
      labyrinth[i].splice(rotWhich, 1);
    }
  }
}

function rotVert2(rotWhich) {
  var temp;
  for (var i = labyrinth.length - 1; i >= 0; i--) {
    if (i == labyrinth.length - 1) {
      temp = labyrinth[i][rotWhich];
    }
    if (i === 0) {
      labyrinth[i][rotWhich] = temp;
    } else {
      labyrinth[i][rotWhich] = labyrinth[i - 1][rotWhich];
    }
    if (labyrinth[i][rotWhich] === undefined) {
      labyrinth[i].splice(rotWhich, 1);
    }
  }
}

function lookAt(d) {
  if (mod(d, 4) === 0) {
    try {
      return labyrinth[p[1] - 1][p[0]];
    } catch (e) {
      return " ";
    }
  } else if (mod(d, 4) == 1) {
    try {
      return labyrinth[p[1]][p[0] + 1];
    } catch (e) {
      return " ";
    }
  } else if (mod(d, 4) == 2) {
    try {
      return labyrinth[p[1] + 1][p[0]];
    } catch (e) {
      return " ";
    }
  } else if (mod(d, 4) == 3) {
    try {
      return labyrinth[p[1]][p[0] - 1];
    } catch (e) {
      return " ";
    }
  }
}

function isWall(d) {
  if (lookAt(d) == " " || lookAt(d) === undefined) {
    return true;
  } else {
    return false;
  }
}

function updateDirection() {
  var numOfWalls = 0;
  if (!isWall(0)) {
    numOfWalls++;
  }
  if (!isWall(1)) {
    numOfWalls++;
  }
  if (!isWall(2)) {
    numOfWalls++;
  }
  if (!isWall(3)) {
    numOfWalls++;
  }

  if (numOfWalls == 4) {
    if (main.top() < 0) {
      direction -= 1;
    } else if (main.top() > 0) {
      direction += 1;
    }
  } else if (numOfWalls == 3) {
    if (main.top() < 0) {
      direction -= 1;
    } else if (main.top() > 0) {
      direction += 1;
    }
    if (isWall(direction)) {
      direction += 2;
    }
  } else if (numOfWalls == 2) {
    if (isWall(direction + 2)) {
      if (isWall(direction)) {
        //Special case
        if (main.top() < 0) {
          direction -= 1;
        } else if (main.top() > 0) {
          direction += 1;
        } else {
          direction += Math.random() < 0.5 ? -1 : 1;
        }
      } else {
        //Keep moving..
      }
    } else {
      for (var i = 0; i <= 3; i++) {
        if (!isWall(i) && i != mod((direction + 2), 4)) {
          direction = i;
          break;
        }
      }
    }
  } else if (numOfWalls == 1) {
    if (!isWall(0)) {
      direction = 0;
    } else
    if (!isWall(1)) {
      direction = 1;
    } else
    if (!isWall(2)) {
      direction = 2;
    } else
    if (!isWall(3)) {
      direction = 3;
    }
  } else {
    return -1;
  }
}

function execChar(char) {
  var a;
  var b;
  if (/\d/.exec(char)) {
    main.push(main.pop() * 10 + (+char));
  } else switch (char) {
    case '!':
      O.value += main.pop();
      break;
    case '"': //Nothing...
      break;
    case '#':
      main.push(main.length);
      break;
    case '$':
      main.push(main.pop() ^ main.pop());
      break;
    case '%':
      a = main.pop();
      b = main.pop();
      main.push(mod(b, a));
      break;
    case '&':
      main.push(main.pop() & main.pop());
      break;
    case "'":
      //Debug-Unimplemented
      break;
    case '(':
      main.push(main.pop() - 1);
      break;
    case ')':
      main.push(main.pop() + 1);
      break;
    case '*':
      main.push(main.pop() * main.pop());
      break;
    case '+':
      main.push(main.pop() + main.pop());
      break;
    case ',':
      a = I.value.charCodeAt(inpLoc);
      if (Number.isNaN(a)) {
        main.push(-1);
      } else {
        main.push(a);
        inpLoc++;
      }
      break;
    case '-':
      a = main.pop();
      b = main.pop();
      main.push(b - a);
      break;
    case '.':
      O.value += String.fromCharCode(mod(main.pop(), 256));
      break;
    case '/':
      a = main.pop();
      b = main.pop();
      if (a === 0) {
        sucide = true;
        throw "Stop that";
      }
      main.push(Math.floor(b / a));
      break;
    case ':':
      main.push(main.top());
      break;
    case ';':
      main.pop();
      break;
    case '<':
      //MOVE IP
      b = main.pop();
      a = mod(p[1] + b, labyrinth.length);
      labyrinth[a].push(labyrinth[a].shift());
      updateGrid();
      if (b === 0) {
        p[0] = mod(p[0] - 1, labyrinth[a].length);
      }
      break;
    case '=':
      a = main.pop();
      b = auxiliary.pop();
      main.push(b);
      auxiliary.push(a);
      break;
    case '>':
      //MOVE IP
      b = main.pop();
      a = mod(p[1] + b, labyrinth.length);
      labyrinth[a].unshift(labyrinth[a].pop());
      updateGrid();
      if (b === 0) {
        p[0] = mod(p[0] + 1, labyrinth[a].length);
      }
      break;
    case '?':
      try {
        a = I.value.substr(inpLoc);
        b = (+(/[\+-]?\d+/.exec(a)[0]));
        main.push(b);
        inpLoc += a.search(/[\+-]?\d+/) + (b + "").length;
      } catch (e) {
        main.push(0);
        inpLoc = I.value.length;
      }
      break;
    case '@':
      sucide = true;
      break;
    case '\\':
      O.value += "\n";
      break;
    case '^': //Fix!
      b = main.pop();
      labyrinth = transpose(labyrinth);
      a = mod(p[0] + b, labyrinth[p[1]].length);
      labyrinth[a].unshift(labyrinth[a].pop());
      if (b === 0) {
        p[1] = mod(p[1] - 1, labyrinth.length);
      }
      labyrinth = transpose(labyrinth);
      updateGrid();
      break;
    case '_':
      main.push(0);
      break;
    case '`':
      main.push(-main.pop());
      break;
    case 'v': //Fix!
      b = main.pop();
      a = mod(p[0] + b, labyrinth[p[1]].length);
      rotVert2(a);
      updateGrid();
      if (b === 0) {
        p[1] = mod(p[1] + 1, labyrinth.length);
      }
      break;
    case '{':
      main.push(auxiliary.pop());
      break;
    case '|':
      main.push(main.pop() | main.pop());
      break;
    case '}':
      auxiliary.push(main.pop());
      break;
    case '~':
      main.push(~main.pop());
      break;
  }
}

function transpose(array) {
  var newArray = array[0].map(function(col, i) {
    return array.map(function(row) {
      return row[i];
    });
  });
  return newArray;
}

//Spiders
function startDebug() {
  if (spiders && document.cookie.split("youWereHere=")[1] === undefined) {
    document.cookie = "youWereHere=yep";
    debugButton.disabled = 'disabled';
    var spiderImg = document.createElement('img');
    spiderImg.src = "http://i.imgur.com/fsYfS9H.png"; //http://i.imgur.com/PRPmqMJ.gif
    spiderImg.className = "spider";

    var svg = document.createElementNS('http://www.w3.org/2000/svg', 'line');
    svg.setAttribute("stroke-width", 2);
    var rn = Math.random() * 10 + 5;
    for (var i = 0; i < rn; i++) {
      var tempSpider = spiderImg.cloneNode(true);

      var left = Math.min(Math.random() * innerWidth, innerWidth - 50);
      var top = -Math.random() * 300;
      tempSpider.style.left = left - 26 + "px";
      tempSpider.style.top = top - 5 + "px";

      var tempSvg = svg.cloneNode(true);
      tempSvg.setAttribute("y1", top - innerHeight - 100);
      tempSvg.setAttribute("y2", top);
      tempSvg.setAttribute("x1", left);
      tempSvg.setAttribute("x2", left);

      spiderContainer.appendChild(tempSpider);
      svgId.appendChild(tempSvg);
      // Make sure the initial state is applied.
      window.getComputedStyle(tempSpider).transform; // jshint ignore:line
      window.getComputedStyle(tempSvg).transform; // jshint ignore:line

      tempSpider.style.transform = "translateY(" + (innerHeight + 48 + top) + "px)";
      tempSvg.style.transform = "translateY(" + (innerHeight + 48 + top) + "px)";
    }
    setTimeout(fallDown, 2500);
    debug = true;
    setTimeout(run, 4000);
  } else {
    debug = true;
    run();
  }
}

function fallDown() {
  svgId.innerHTML = "";
  var spiders = document.getElementsByClassName("spider");
  for (var i = 0; i < spiders.length; i++) {
    spiders[i].style.top = innerHeight + "px";
  }
}


//Maze proper copy
lab.addEventListener("paste", function(e) {
  // cancel paste
  e.preventDefault();

  // get text representation of clipboard
  var text = e.clipboardData.getData("text/plain");

  // insert text manually
  //document.execCommand("insertHTML", false, text);
  lab.innerHTML = text;
});
body {
  background: #484848;
}
h3{
  font-family: sans-serif;
  color: white;
  font-weight: bolder;
  margin: 6px;
  margin-bottom: 0px;
}
#inputHeader, #outputHeader, #debugHeader{
  flex: 1;
}
#debugHeader{
  display: none;
}
#deb {
  display: none;
}
.container {
  width: 100%;
  position: relative;
  display: flex;
  flex-flow: row wrap;
}
.container pre,textarea {
  flex: 1;
  min-height: 175px;
  background: #202020;
  color: white;
  border: #202020;
  margin: 6px;
  font: monospace;
  resize: vertical;
}
.container pre[contentEditable=false] {
  cursor: not-allowed;
}

#lab {
  width: 100%;
  min-height: 150px;
}

#pointerOverlay{
  width: 100%;
  position: absolute;
  background: rgba(0,0,0,0);
  /*width: 100%;*/
  resize: vertical;
  height: 200px;
  pointer-events: none;
  color: rgba(255,0,0,0.7);
  left: 0px;
}
button:not(.run) {
  vertical-align: top;
  border: #303030;
  color: white;
  font-weight: bold;
  font-size: 1em;
  letter-spacing: 1px;
  background: #303030;
  cursor: pointer;
  min-width: 100px;
  min-height: 45px;
  margin: 5px;
  line-height: 50px;
}
button:not(.run):hover {
  background: #202020;
}

button:not(.run)[disabled] {
  background: #404040;
  cursor: not-allowed;
}
.buttonImg{
  width: 40px;
  vertical-align: middle;
  transform: translateX(-10px);
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>Labyrinth</title>
</head>

<body>
  <button onclick="debug=false; run(); deb.style.display = 'none'; debugHeader.style.display = 'none';"><img src="http://i.imgur.com/XvHQHX9.png" class="buttonImg">Run</button>
  <button id="debugButton" onclick="startDebug(); deb.style.display='flex'; debugHeader.style.display = 'flex';"><img src="http://i.imgur.com/Th4Kyvd.png" class="buttonImg">Debug</button>
  <button id="stepButton" onclick="updatePointer();" disabled>Step: <span id="stepDiv">1</span>
  </button>
  <button onclick="sucide = true; updatePointer();">Stop</button>

  <div class="container">
    <h3>Maze:</h3>
    <div style="width:100%;  margin: -6px;"></div>
    <pre id="pointerOverlay"></pre>
    <pre id="lab" contentEditable="true">,)@
.(</pre>
    <div style="width:100%;"></div>
    
    <h3 id="inputHeader">Input:</h3>
    <h3 id="outputHeader">Output:</h3>
    <h3 id="debugHeader">Debugging:</h3>
    <div style="width:100%"></div>
    <textarea id="I">Labyrinth rocks!</textarea>
    <textarea id="O"></textarea>
    <textarea id="deb"></textarea>
  </div>
  <svg width="100%" id="svgId">
  </svg>
  <div id="spiderContainer">
  </div>
</body>

</html>

Ecco la versione più aggiornata: http://output.jsbin.com/cuzoxu


Bel design dell'interprete! E il debugger. Mi hai fatto venire voglia di imparare questa lingua!
RedClover,

@Soaku Grazie! Se avete suggerimenti / reclami / ecc., Non esitate a dirmelo. Sono felice di implementare praticamente qualsiasi cosa!
Stefnotch,

4

Fourier

Questa è ora una versione completa di Fourier, tradotta direttamente dal Python. Questo dovrebbe rimanere aggiornato.

<!DOCTYPE html> <html> <head> <title>FourIDE - Editor</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css"> <style> body { padding-left: 2em; background-color: gainsboro } textarea, input { font-family: Courier New; border: none } </style> </head> <body> <h1><a href="https://github.com/beta-decay/Fourier">Fourier</a> Interpreter</h1> <h3>Code:</h3> <textarea id="code" rows="4" oninput="javascript:chars()" cols="40"></textarea> <br/> Function: <select id="funcSelect"> <option value="exec">Execute code</option> <option value="expl">Explode code</option> <option value="debg">Debug code</option> </select> <br/> <h3>Input:</h3> <textarea id="input" rows="4" cols="40"></textarea> <br/><br/> <button id="run" onclick="javascript:main()">Engage</button> <button id="clear" onclick="javascript:clearText()">Clear</button> <br/> Character count: <span id="ccount">0</span> characters <h3>Output:</h3> <textarea id="output" readonly="readonly" rows="4" cols="40" style="cursor: default;"></textarea> <br/> <a href="javascript:getperma()">Get permalink</a> <br/> <h3>Character reference</h3> <h4>ASCII code reference</h4> <input id="charRef" cols="40" oninput="javascript:getCharCode()"> <br/> <input id="asciiRef" readonly="readonly" cols="40" style="background-color: #c2c2c2; cursor: default;"> <script src="https://rawgit.com/beta-decay/Fourier/master/javascript/editor.js"></script> <script src="https://rawgit.com/beta-decay/Fourier/master/javascript/debug.js"></script> <script src="https://rawgit.com/beta-decay/Fourier/master/javascript/interpreter.js"></script> <script> function main() { document.getElementById("output").style.color = "black"; choice = document.getElementById("funcSelect").value; if (choice == "exec") { interpreter(); } else if (choice == "debg") { debug(); } else { document.getElementById("output").value = "Sorry, those features are not ready yet"; } } </script> </body> </html>

Vedi altro:


2
ᴜɢʜ ɴᴏ ᴊQᴜᴇʀʏʏʏ
Conor O'Brien,

2
@ CᴏɴᴏʀO'Bʀɪᴇɴ Gah, fermati con i maiuscoletti: D
Decadimento beta

Padrone della razza JS pura! Sovvertire il paradigma jQuery dominante!
Mama Fun Roll

3

Unario (a Brainfuck)

Converte semplicemente Unary in Brainfuck. Questo potrebbe essere facilmente accoppiato con uno degli interpreti Brainfuck per eseguire direttamente il codice Unary - non è necessario reinventare la ruota!

function interpret() {
  var result = "";
  var table = "><+-.,[]"
  var option = document.getElementById("option").checked
  var code = document.getElementById("code").value
  var number = option ? parseInt(code, 10) : code.length;
  number = number.toString(2)
  if (number.length % 3 == 1) {
    number = number.slice(1)
    for (var i = 0; i < number.length; i += 3) {
      var instruction = number[i] + number[i + 1] + number[i + 2]
      instruction = parseInt(instruction, 2)
      result += table[instruction];
    }
  } else {
    result = "Error: program binary cannot be split into triplets."
  }
  document.getElementById("result").value = result;
}
Input as Number of 0's
<input id="option" type="checkbox" />
<br />
<br />
<input id="code" type="text" style="width:90%;" />
<br />
<br />
<input id="run" type="button" value="Run!" onclick="interpret()" />
<br />
<br />
<input id="result" type="text" style="width:90%;" />


3

Ciao ++

Il linguaggio più semplice da implementare E da imparare!

<h1>Hello++ Interpreter</h1>
<hr>
<h2>Code</h2>
<textarea id=c></textarea>
<br>
<button onclick='o.value="",c.value.replace(/[^h]/ig,"").split("").map(function($){$&&(o.value+="Hello World\n")})'>Say hello to the output!</button>
<h2>Output</h2>
<textarea id=o readonly></textarea>
<style>*{font-family:monospace}textarea{width:100%}</style>


3

CHIQRSX9 +

HQ9 + con completezza di Turing. Mi sono attenuto il più vicino possibile alle specifiche.

function interpret(c,i){
	c.split('').map(function(v,I){
		if(v=='c'||v=='C')out.push(i);
		else if(v=='h'||v=='H')out.push('Hello, world!\n');
		else if(v=='i'||v=='I')interpret(i,"");
		else if(v=='q'||v=='Q')out.push(c);
		else if(v=='r'||v=='R')out.push(i.replace(/[a-zA-Z]/g,function(C){return String.fromCharCode((C<="Z"?90:122)>=(C=C.charCodeAt(0)+13)?C:C-26);}));
		else if(v=='s'||v=='S')out.push(i.split('\n').sort().join('\n'));
		else if(v=='x'||v=='X')eval(c.split().join(0|Math.random()*256));
		else if(v=='9')for(var o,e,n=100,t=" on the wall";n-->-1;)o=e+t+", "+e+".\n"+(n>-1?"Take one down, pass it around, ":"Go to the store and buy some more, ")+(e=(0>n?99:n||"no more")+" bottle"+(1!=n?"s":"")+" of beer")+t+".\n",99>n&&out.push(o);
		else if(v=='+')acc++;
		else out.push("\n\t!ERROR!\t\n");
	});
  return out.join('').match(/\n\t!ERROR!\t\n/g)?'ERROR: Unknown command':out.join('')
}
<h1>CHIQRSX9+ Interpreter</h1>
<hr>
<h2>Code</h2>
<textarea id=c></textarea>
<br>
<h2>Input</h2>
<textarea id=i></textarea>
<br>
<button onclick='out=[],acc=0;o.value=interpret(c.value,i.value)'>Run!</button>
<h2>Output</h2>
<textarea id=o readonly></textarea>
<style>*{font-family:monospace}textarea{width:100%}</style>


3

Neoscript

Funziona solo su browser ES6

"use strict";

function nodejswrapper(url) {
    let data = $.ajax({
        type: "GET",
        url: url,
        async: false
    }).responseText;
    return new Function("let module={};" + data + "return module.exports;")();
}

let tokenize, parse, transpile;

function compile(code) {
    return transpile(parse(tokenize(code)));
}

console.log = function(msg) {
    $("#console").append((""+msg).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") + "<br />");
}
console.clear = function(msg) {
    $("#console").html("");
}

$(function() {
    tokenize = nodejswrapper("http://crossorigin.me/https://raw.githubusercontent.com/tuxcrafting/neoscript/master/src/tokenizer.js").tokenize;
    parse = nodejswrapper("http://crossorigin.me/https://raw.githubusercontent.com/tuxcrafting/neoscript/master/src/parser.js").parse;
    transpile = nodejswrapper("http://crossorigin.me/https://raw.githubusercontent.com/tuxcrafting/neoscript/master/src/transpilers/javascript.js").transpile;
    $("#run").on("click", function() {
        let code = $("#code").val();
        let js = compile(code);
        new Function(js)();
    });
});
#console {
    width: 400px;
    height: 400px;
    overflow: auto;
    background: black;
    color: white;
    float: right;
    font-family: monospace;
}
<script type="application/javascript" src="https://raw.githubusercontent.com/tuxcrafting/neoscript/master/src/stdlib/stdlib.js"></script>
<script type="application/javascript" src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<div id="console"></div>
<textarea id="code" cols="40" rows="15"></textarea><br />
<button id="run">Run</button>


2

Brainfuck

Cosa, questo è ancora il codice golf, giusto?

Una nota seria, ho implementato un sacco di lingue esoteriche in javascript qualche tempo fa, sentitevi liberi di usarle, è praticamente plug and play: https://dl.dropboxusercontent.com/u/69377299/lang%20js/ main.html

function run () {
  var code = document.getElementById("code").value;
  var inp  = document.getElementById("in").value;
  var ret  = x(code, inp);
  
  document.getElementById("out").value = ret;
}

function B(s,i,c) {
	i+=1+-c*2
	return s[i]==']['[+c]?i:B(s,s[i]==']['[+!c]?B(s,i,c):i,c)
}

function x(c, a) {
	var y, l=0, p=0, i=0, q=0, r='', t=[]
	for (; q<1000; q++) t[q] = 0

	for (;i<c.length; i++) {
		y = c.charCodeAt(i)
		p -= (y==60) - (y==62)
  		t[p] += y==44? (l>a.length? 0: a.charCodeAt(l++))-t[p]: -((y==45) - (y==43))
		if (y==46) r += String.fromCharCode(t[p])
		if (y==91 + (t[p]>0)*2) i = B(c,i,y==93)
	}

	return r;
}
Code: <input id="code"></input>
<button onclick="run()">Run</button>

<br>
Input: <input id="in"></input>

<br><br>
Output: <input id="out" disabled></input>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.