work async, js compiler
This commit is contained in:
parent
4cb534838a
commit
c6d280dfd8
4 changed files with 228 additions and 333 deletions
|
@ -1,218 +0,0 @@
|
|||
import sys
|
||||
import re
|
||||
import time
|
||||
|
||||
class Interpreter:
|
||||
def __init__(self, commands_per_second=1_000_000, debug=False, comma_standart_input=True):
|
||||
self.debug = debug
|
||||
self.commands = ['+', '-', '>', '<', '.', ',', '[', ']']
|
||||
self.mp = 0 # memory pointer
|
||||
self.pc = 0 # program counter
|
||||
self.data = [0] * 2
|
||||
'''
|
||||
chceme mít k dispozici i konec datového pole, (abychom mohli zavolat '<' na 0)
|
||||
-> konec pole budeme mít jako self.data_end a kde jsme, poznáme podle self.is_at_end...
|
||||
pak můžeme podle potřeby zvětšovat pole ze začátku nebo z konce
|
||||
|
||||
!poznámka autora: dalo by se také udělat s jedním polem, tak že bychom 'posouvali' index 0...
|
||||
to mě ale nenapadlo, když jsem to psal, tak jsem to udělal takhle...
|
||||
'''
|
||||
self.data_end = [0] * 2 # tail is reversed
|
||||
self.is_at_end = False
|
||||
self.code = ""
|
||||
self.commands_per_second = commands_per_second
|
||||
self.MAX = 2**32 - 1
|
||||
|
||||
self.user_input = ""
|
||||
self.user_input_index = 0
|
||||
self.saved_output = ""
|
||||
self.comma_standart_input = comma_standart_input
|
||||
self.last_step = 0
|
||||
|
||||
def our_i32(self, value):
|
||||
if value == -1:
|
||||
return self.MAX
|
||||
if value == self.MAX + 1:
|
||||
return 0
|
||||
return value
|
||||
|
||||
def load_code_from_input(self):
|
||||
def expand_numbers(match):
|
||||
count = int(match.group(1))
|
||||
char = match.group(2)
|
||||
return char * count
|
||||
|
||||
self.code = ""
|
||||
code_filename = sys.argv[1]
|
||||
with open(code_filename) as code_file:
|
||||
for line in code_file:
|
||||
line = line.strip()
|
||||
line = line.split('//')[0].strip()
|
||||
line = re.sub(r'(\d+)(.)', expand_numbers, line)
|
||||
line = ''.join(filter(lambda c: c in self.commands, line))
|
||||
self.code += line
|
||||
|
||||
def load_code_from_string(self, code):
|
||||
def expand_numbers(match):
|
||||
count = int(match.group(1))
|
||||
char = match.group(2)
|
||||
return char * count
|
||||
|
||||
self.code = ""
|
||||
code = code.strip()
|
||||
code = re.sub(r'(\d+)(.)', expand_numbers, code)
|
||||
code = ''.join(filter(lambda c: c in self.commands, code))
|
||||
self.code += code
|
||||
|
||||
def print_overwrite(self, message, prev_len=[0]):
|
||||
sys.stdout.write('\r' + message + ' ' * max(prev_len[0] - len(message), 0))
|
||||
sys.stdout.flush()
|
||||
prev_len[0] = len(message)
|
||||
|
||||
def print_data(self, steps):
|
||||
to_print = "step: " + str(steps) + " "
|
||||
to_print += "mp: " + str(self.mp) + " | "
|
||||
for i in range(len(self.data)):
|
||||
to_print += str(self.data[i]) + " "
|
||||
to_print += "|"
|
||||
to_print += " end: | "
|
||||
for i in range(len(self.data_end)).__reversed__():
|
||||
to_print += str(self.data_end[i]) + " "
|
||||
to_print += "|"
|
||||
self.print_overwrite(to_print)
|
||||
return to_print
|
||||
|
||||
def get_value_at_mp(self):
|
||||
if not self.is_at_end:
|
||||
return self.data[self.mp]
|
||||
else:
|
||||
return self.data_end[self.MAX - self.mp]
|
||||
|
||||
def set_value_at_mp(self, value):
|
||||
if not self.is_at_end:
|
||||
self.data[self.mp] = value
|
||||
else:
|
||||
self.data_end[self.MAX - self.mp] = value
|
||||
|
||||
def handle_plus(self):
|
||||
self.set_value_at_mp(self.our_i32(self.get_value_at_mp() + 1))
|
||||
|
||||
def handle_minus(self):
|
||||
self.set_value_at_mp(self.our_i32(self.get_value_at_mp() - 1))
|
||||
|
||||
def handle_greater(self):
|
||||
temp = self.mp
|
||||
self.mp = self.our_i32(self.mp + 1)
|
||||
# kontrola, jesstli jsem ne přeskočil konec
|
||||
if self.mp > self.MAX - len(self.data_end):
|
||||
self.is_at_end = True
|
||||
return
|
||||
if temp > self.mp:
|
||||
self.is_at_end = False
|
||||
# rozšíření datového pole
|
||||
if self.mp >= len(self.data):
|
||||
self.data += [0] * (len(self.data))
|
||||
|
||||
def handle_less(self):
|
||||
temp = self.mp
|
||||
self.mp = self.our_i32(self.mp - 1)
|
||||
# kontrola, jestli jsem ne přeskočil začátek
|
||||
if self.mp < len(self.data):
|
||||
self.is_at_end = False
|
||||
return
|
||||
if temp < self.mp:
|
||||
self.is_at_end = True
|
||||
if self.MAX - self.mp >= len(self.data_end):
|
||||
self.data_end += [0] * (len(self.data_end))
|
||||
|
||||
def handle_dot(self):
|
||||
sys.stdout.write(chr(self.get_value_at_mp()))
|
||||
sys.stdout.flush()
|
||||
self.saved_output += chr(self.get_value_at_mp())
|
||||
|
||||
def handle_comma(self):
|
||||
if self.comma_standart_input:
|
||||
input_char = sys.stdin.read(1)
|
||||
else:
|
||||
if self.user_input_index < len(self.user_input):
|
||||
input_char = self.user_input[self.user_input_index]
|
||||
self.user_input_index += 1
|
||||
else:
|
||||
input_char = None
|
||||
if not input_char:
|
||||
self.set_value_at_mp(0)
|
||||
else:
|
||||
self.set_value_at_mp(ord(input_char))
|
||||
|
||||
def handle_left_bracket(self):
|
||||
if self.data[self.mp] == 0: # jump to the matching ]
|
||||
open_brackets = 1
|
||||
while open_brackets > 0:
|
||||
self.pc += 1
|
||||
if self.pc >= len(self.code):
|
||||
raise SyntaxError("Unmatched \"[\"")
|
||||
if self.code[self.pc] == "[":
|
||||
open_brackets += 1
|
||||
elif self.code[self.pc] == "]":
|
||||
open_brackets -= 1
|
||||
|
||||
def handle_right_bracket(self):
|
||||
if self.data[self.mp] != 0:
|
||||
close_brackets = 1
|
||||
while close_brackets > 0:
|
||||
self.pc -= 1
|
||||
if self.pc < 0:
|
||||
raise SyntaxError("Unmatched \"]\"")
|
||||
if self.code[self.pc] == "]":
|
||||
close_brackets += 1
|
||||
elif self.code[self.pc] == "[":
|
||||
close_brackets -= 1
|
||||
|
||||
def execute_loaded_code(self):
|
||||
steps = 0
|
||||
print("|Executing code|")
|
||||
while True:
|
||||
if self.pc >= len(self.code):
|
||||
break
|
||||
com = self.code[self.pc]
|
||||
if com == "+":
|
||||
self.handle_plus()
|
||||
elif com == "-":
|
||||
self.handle_minus()
|
||||
elif com == ">":
|
||||
self.handle_greater()
|
||||
elif com == "<":
|
||||
self.handle_less()
|
||||
elif com == ".":
|
||||
self.handle_dot()
|
||||
elif com == ",":
|
||||
self.handle_comma()
|
||||
elif com == "[":
|
||||
self.handle_left_bracket()
|
||||
elif com == "]":
|
||||
self.handle_right_bracket()
|
||||
# debug print
|
||||
if self.debug:
|
||||
self.print_data(steps)
|
||||
time.sleep(1 / self.commands_per_second)
|
||||
self.pc += 1
|
||||
steps += 1
|
||||
self.last_step = steps
|
||||
print("\n|Execution done|")
|
||||
|
||||
'''
|
||||
Usage:
|
||||
python interpreter.py <code_file> < <user_input>
|
||||
|
||||
nastavte si DEBUG na True, pokud chcete vidět debugovací výstup, pak ale nebude správně fungovat "."...
|
||||
nastavte si commands_per_second na 2, pokud chcete dva kroky za sekundu
|
||||
'''
|
||||
|
||||
DEBUG = True
|
||||
COMMANDS_PER_SECOND = 1000
|
||||
|
||||
if __name__ == "__main__":
|
||||
interpreter = Interpreter(commands_per_second=COMMANDS_PER_SECOND, debug=DEBUG)
|
||||
interpreter.load_code_from_input()
|
||||
print("Loaded code:", interpreter.code, "length:", len(interpreter.code))
|
||||
interpreter.execute_loaded_code()
|
|
@ -33,6 +33,14 @@
|
|||
margin-top: 1rem;
|
||||
}
|
||||
.btn:hover:not([disabled]) { background: var(--primary-light); }
|
||||
.btn-stop {
|
||||
background: #ef4444; color: #fff; font-weight: 600; cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
margin-top: 1rem; padding: 0.75rem 1.5rem; border: none; border-radius: 0.375rem;
|
||||
display: inline-block; text-decoration: none;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
.btn-stop:hover:not([disabled]) { background: #dc2626; }
|
||||
.btn[disabled] { opacity: 0.6; cursor: not-allowed; }
|
||||
.spinner {
|
||||
border: 2px solid #f3f3f3;
|
||||
|
@ -66,6 +74,13 @@
|
|||
top: 0; left: 0; width: 100%; height: 100%; opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.author {
|
||||
text-align: center;
|
||||
font-size: 0.8rem;
|
||||
color: var(--text);
|
||||
margin-top: 1rem;
|
||||
line-height: 2em;
|
||||
}
|
||||
@media screen and (max-width: 768px) {
|
||||
.flex { flex-direction: column; }
|
||||
.flex > div { width: 100%; }
|
||||
|
@ -74,7 +89,7 @@
|
|||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Brainfuck Compiler</h1>
|
||||
<h1>Brainfuck Compiler for M&M</h1>
|
||||
<form id="bf-form" class="card">
|
||||
<div class="flex">
|
||||
<div>
|
||||
|
@ -95,20 +110,209 @@
|
|||
</div>
|
||||
</div>
|
||||
<button type="button" id="run-btn" class="btn">Run</button>
|
||||
<button type="button" id="stop-btn" class="btn-stop" style="display: none;">Stop</button>
|
||||
</form>
|
||||
|
||||
<div class="card">
|
||||
<label for="output">Output</label>
|
||||
<div id="output"></div>
|
||||
<pre id="output"></pre>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<label for="last_state">State</label>
|
||||
<div id="last_state"></div>
|
||||
<pre id="last_state"></pre>
|
||||
</div>
|
||||
<div class="author">Created by TicVac 2025<br>vaclav.tichy.mam@gmail.com</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let abortSignal = false;
|
||||
const outElement = document.getElementById('output');
|
||||
const lastStateElement = document.getElementById('last_state');
|
||||
|
||||
class Interpreter {
|
||||
constructor({ commandsPerSecond = 1_000_000_000, debug = false} = {}) {
|
||||
this.debug = debug;
|
||||
this.commands = ['+', '-', '>', '<', '.', ',', '[', ']'];
|
||||
this.mp = 0; // memory pointer
|
||||
this.pc = 0; // program counter
|
||||
this.data = [0, 0];
|
||||
this.dataEnd = [0, 0]; // tail reversed
|
||||
this.isAtEnd = false;
|
||||
this.code = "";
|
||||
this.commandsPerSecond = commandsPerSecond;
|
||||
this.MAX = 2 ** 32 - 1;
|
||||
|
||||
this.userInput = "";
|
||||
this.userInputIndex = 0;
|
||||
this.savedOutput = "";
|
||||
}
|
||||
|
||||
ourI32(value) {
|
||||
if (value === -1) return this.MAX;
|
||||
if (value === this.MAX + 1) return 0;
|
||||
return value;
|
||||
}
|
||||
|
||||
loadCodeFromString(code) {
|
||||
const expandNumbers = (match, count, char) => {
|
||||
return char.repeat(parseInt(count, 10));
|
||||
};
|
||||
let cleaned = code.trim();
|
||||
cleaned = cleaned.replace(/(\d+)(.)/g, expandNumbers);
|
||||
cleaned = cleaned.split('').filter(c => this.commands.includes(c)).join('');
|
||||
this.code = cleaned;
|
||||
}
|
||||
|
||||
getValueAtMp() {
|
||||
if (!this.isAtEnd) {
|
||||
return this.data[this.mp];
|
||||
} else {
|
||||
return this.dataEnd[this.MAX - this.mp];
|
||||
}
|
||||
}
|
||||
|
||||
setValueAtMp(value) {
|
||||
if (!this.isAtEnd) {
|
||||
this.data[this.mp] = value;
|
||||
} else {
|
||||
this.dataEnd[this.MAX - this.mp] = value;
|
||||
}
|
||||
}
|
||||
|
||||
handlePlus() {
|
||||
this.setValueAtMp(this.ourI32(this.getValueAtMp() + 1));
|
||||
}
|
||||
|
||||
handleMinus() {
|
||||
this.setValueAtMp(this.ourI32(this.getValueAtMp() - 1));
|
||||
}
|
||||
|
||||
handleGreater() {
|
||||
const temp = this.mp;
|
||||
this.mp = this.ourI32(this.mp + 1);
|
||||
if (this.mp > this.MAX - this.dataEnd.length) {
|
||||
this.isAtEnd = true;
|
||||
return;
|
||||
}
|
||||
if (temp > this.mp) {
|
||||
this.isAtEnd = false;
|
||||
}
|
||||
if (this.mp >= this.data.length) {
|
||||
this.data = this.data.concat(new Array(this.data.length).fill(0));
|
||||
}
|
||||
}
|
||||
|
||||
handleLess() {
|
||||
const temp = this.mp;
|
||||
this.mp = this.ourI32(this.mp - 1);
|
||||
if (this.mp < this.data.length) {
|
||||
this.isAtEnd = false;
|
||||
return;
|
||||
}
|
||||
if (temp < this.mp) {
|
||||
this.isAtEnd = true;
|
||||
}
|
||||
if (this.MAX - this.mp >= this.dataEnd.length) {
|
||||
this.dataEnd = this.dataEnd.concat(new Array(this.dataEnd.length).fill(0));
|
||||
}
|
||||
}
|
||||
|
||||
handleDot() {
|
||||
const ch = String.fromCharCode(this.getValueAtMp());
|
||||
this.savedOutput += ch;
|
||||
}
|
||||
|
||||
handleComma() {
|
||||
let inputChar;
|
||||
if (this.commaStandardInput) {
|
||||
// Standard input ignored in this variant
|
||||
inputChar = null;
|
||||
} else {
|
||||
if (this.userInputIndex < this.userInput.length) {
|
||||
inputChar = this.userInput[this.userInputIndex++];
|
||||
} else {
|
||||
inputChar = null;
|
||||
}
|
||||
}
|
||||
if (!inputChar) {
|
||||
this.setValueAtMp(0);
|
||||
} else {
|
||||
this.setValueAtMp(inputChar.charCodeAt(0));
|
||||
}
|
||||
}
|
||||
|
||||
handleLeftBracket() {
|
||||
if (this.getValueAtMp() === 0) {
|
||||
let openBrackets = 1;
|
||||
while (openBrackets > 0) {
|
||||
this.pc++;
|
||||
if (this.pc >= this.code.length) {
|
||||
throw new SyntaxError('Unmatched "["');
|
||||
}
|
||||
if (this.code[this.pc] === '[') openBrackets++;
|
||||
if (this.code[this.pc] === ']') openBrackets--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleRightBracket() {
|
||||
if (this.getValueAtMp() !== 0) {
|
||||
let closeBrackets = 1;
|
||||
while (closeBrackets > 0) {
|
||||
this.pc--;
|
||||
if (this.pc < 0) {
|
||||
throw new SyntaxError('Unmatched "]"');
|
||||
}
|
||||
if (this.code[this.pc] === ']') closeBrackets++;
|
||||
if (this.code[this.pc] === '[') closeBrackets--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getState() {
|
||||
const dataMain = this.data.join(' ');
|
||||
const dataTail = [...this.dataEnd].reverse().join(' ');
|
||||
return `step: ${this.steps} mp: ${this.mp} | ${dataMain} | end: | ${dataTail} |`;
|
||||
}
|
||||
|
||||
async execute({ codeString, userInput = '', callback } = {}) {
|
||||
this.loadCodeFromString(codeString);
|
||||
this.userInput = userInput;
|
||||
let steps = 0;
|
||||
let breath = 100;
|
||||
while (this.pc < this.code.length) {
|
||||
const com = this.code[this.pc];
|
||||
switch (com) {
|
||||
case '+': this.handlePlus(); break;
|
||||
case '-': this.handleMinus(); break;
|
||||
case '>': this.handleGreater(); break;
|
||||
case '<': this.handleLess(); break;
|
||||
case '.': this.handleDot(); break;
|
||||
case ',': this.handleComma(); break;
|
||||
case '[': this.handleLeftBracket(); break;
|
||||
case ']': this.handleRightBracket(); break;
|
||||
}
|
||||
this.pc++;
|
||||
steps++;
|
||||
if (steps % breath === 0) {
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
}
|
||||
if (abortSignal) {
|
||||
console.log("Execution aborted");
|
||||
this.savedOutput = "Execution aborted";
|
||||
break;
|
||||
}
|
||||
outElement.textContent = this.savedOutput;
|
||||
lastStateElement.textContent = this.getState();
|
||||
}
|
||||
callback(this.savedOutput, this.getState());
|
||||
return this.savedOutput;
|
||||
}
|
||||
}
|
||||
|
||||
const stopBtn = document.getElementById('stop-btn');
|
||||
|
||||
// Setup drop zones with filename display
|
||||
function setupDropZone(dropZoneId, textareaId, textId) {
|
||||
const dropZone = document.getElementById(dropZoneId);
|
||||
|
@ -146,63 +350,14 @@
|
|||
setupDropZone('code-drop', 'code', 'code-drop-text');
|
||||
setupDropZone('input-drop', 'input', 'input-drop-text');
|
||||
|
||||
// Brainfuck Interpreter unchanged
|
||||
function runBrainfuck(code, input) {
|
||||
const tape = Array(30000).fill(0);
|
||||
let ptr = 0, inputPtr = 0, output = '';
|
||||
const loopStack = [];
|
||||
for (let i = 0; i < code.length; i++) {
|
||||
switch(code[i]) {
|
||||
case '>': ptr++; break;
|
||||
case '<': ptr--; break;
|
||||
case '+': tape[ptr] = (tape[ptr] + 1) % 256; break;
|
||||
case '-': tape[ptr] = (tape[ptr] + 255) % 256; break;
|
||||
case '.': output += String.fromCharCode(tape[ptr]); break;
|
||||
case ',': tape[ptr] = inputPtr < input.length ? input.charCodeAt(inputPtr++) : 0; break;
|
||||
case '[':
|
||||
if (tape[ptr] === 0) {
|
||||
let open = 1;
|
||||
while (open) {
|
||||
i++;
|
||||
if (code[i] === '[') open++;
|
||||
if (code[i] === ']') open--;
|
||||
}
|
||||
} else {
|
||||
loopStack.push(i);
|
||||
}
|
||||
break;
|
||||
case ']':
|
||||
if (tape[ptr] !== 0) { i = loopStack[loopStack.length - 1]; }
|
||||
else { loopStack.pop(); }
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
function formatForHTML(text, tabWidth = 4, spaces = true) {
|
||||
// 1) Escape &, <, >, " and '
|
||||
let s = text
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
|
||||
// 2) Convert tabs → a run of non-breaking spaces
|
||||
const nbspTab = " ".repeat(tabWidth);
|
||||
s = s.replace(/\t/g, nbspTab);
|
||||
|
||||
// 3) Optionally convert every single space →
|
||||
if (spaces) {
|
||||
s = s.replace(/ /g, " ");
|
||||
}
|
||||
|
||||
// 4) Convert newlines → <br>
|
||||
s = s.replace(/\r?\n/g, "<br>\n");
|
||||
|
||||
return s;
|
||||
function random_js(out, state) {
|
||||
console.log("random_js");
|
||||
const btn = document.getElementById('run-btn');
|
||||
btn.removeChild(btn.firstChild);
|
||||
document.getElementById('output').textContent = out;
|
||||
document.getElementById('last_state').textContent = state;
|
||||
btn.disabled = false;
|
||||
stopBtn.style.display = 'none';
|
||||
}
|
||||
|
||||
// Run button handler with spinner prepend
|
||||
|
@ -211,25 +366,23 @@
|
|||
const code = document.getElementById('code').value;
|
||||
const input = document.getElementById('input').value;
|
||||
if (btn.disabled) return;
|
||||
|
||||
outElement.textContent = "";
|
||||
lastStateElement.textContent = "";
|
||||
abortSignal = false;
|
||||
stopBtn.style.display = 'inline-block';
|
||||
btn.disabled = true;
|
||||
const spinner = document.createElement('div'); spinner.className = 'spinner';
|
||||
btn.insertBefore(spinner, btn.firstChild);
|
||||
|
||||
const url = '/brainfuck/process_code?code=' + encodeURIComponent(code) + "&user_input=" + encodeURIComponent(input);
|
||||
fetch(url, { method: 'GET', headers: { 'Content-Type': 'application/json' } })
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
// escape HTML entities in output
|
||||
console.log(data);
|
||||
document.getElementById('output').textContent = data.output;
|
||||
document.getElementById('last_state').textContent = data.end_state;
|
||||
document.getElementById('output').innerHTML = formatForHTML(data.output);
|
||||
})
|
||||
.catch(err => console.error(err))
|
||||
.finally(() => {
|
||||
btn.disabled = false;
|
||||
btn.removeChild(spinner);
|
||||
});
|
||||
// execution start
|
||||
const interpreter = new Interpreter({ commandsPerSecond: 1_000_000_000, debug: false });
|
||||
let out = interpreter.execute({ codeString: code, userInput: input, callback: random_js });
|
||||
});
|
||||
|
||||
stopBtn.addEventListener('click', () => {
|
||||
console.log("Stop button clicked");
|
||||
abortSignal = true;
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -3,6 +3,5 @@ from . import views
|
|||
|
||||
urlpatterns = [
|
||||
path('', views.index),
|
||||
path('process_code', views.process_code),
|
||||
]
|
||||
|
||||
|
|
|
@ -7,42 +7,3 @@ from typing import Dict
|
|||
def index(request):
|
||||
args = {}
|
||||
return TemplateResponse(request, 'brainfuck/index.html', args)
|
||||
|
||||
def process_code(request):
|
||||
qs = request.META['QUERY_STRING']
|
||||
params: Dict[str, str] = {}
|
||||
for pair in qs.split('&'):
|
||||
if not pair:
|
||||
continue
|
||||
key, sep, val = pair.partition('=')
|
||||
# decode key (still treat '+'→space in parameter names)
|
||||
decoded_key = unquote_plus(key)
|
||||
# decode value: unquote (leaves '+' intact), then percent-decode
|
||||
decoded_val = unquote(val)
|
||||
params[decoded_key] = decoded_val
|
||||
|
||||
print('params:', params)
|
||||
|
||||
code = params.get('code', '')
|
||||
input_data = params.get('user_input', '')
|
||||
# interpreter
|
||||
interpreter = Interpreter(commands_per_second=1_000_000_000_000, debug=True, comma_standart_input=False)
|
||||
interpreter.user_input = input_data
|
||||
interpreter.load_code_from_string(code)
|
||||
# TODO kill the process if it takes too long?
|
||||
try:
|
||||
interpreter.execute_loaded_code()
|
||||
out = interpreter.saved_output
|
||||
except Exception as e:
|
||||
print('Error:', e)
|
||||
out = 'Error: Code execution failed - ' + str(e)
|
||||
|
||||
end_state = interpreter.print_data(interpreter.last_step)
|
||||
|
||||
|
||||
return JSONResponse({
|
||||
'code': code,
|
||||
'input_data': input_data,
|
||||
'output': out,
|
||||
'end_state': end_state,
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue