import React, {useCallback, useContext, useEffect, useRef, useState} from 'react'; import Interpreter from "../brainfuck/Interpreter"; import CodeDisplay from "./CodeDisplay"; import RunDisplay from "./RunDisplay"; import {OptionContext} from "../App"; interface RunInfoProps { code: string, setRunning: (running: boolean) => void, running: boolean outHandler: (char: number) => void, } const Runner = ({setRunning, running, outHandler, code}: RunInfoProps) => { const [speed, setSpeed] = useState(0); const [interpreter, setInterpreter] = useState(null); const [info, setInfo] = useState(null); const [startTime, setStartTime] = useState(0); const [, setRerenderNumber] = useState(0); const options = useContext(OptionContext); const rerender = () => setRerenderNumber(n => n + 1); const inputArea = useRef(null); const inputHandler = () => { if (!inputArea.current) { throw new Error("Could not read input") } const value = inputArea.current.value; if (value.length < 1) { throw new Error("No input found"); } const char = value.charCodeAt(0); inputArea.current.value = value.substr(1); return char; } const startHandler = useCallback(() => { if (options.directStart) { setSpeed(100); } else { setSpeed(0); } setStartTime(Date.now); setInterpreter(new Interpreter([code, options], outHandler, inputHandler)); setRunning(false); setRunning(true); }, [options, code, outHandler, setRunning]); const stopHandler = () => { setRunning(false); setInfo(null); } const nextHandler = useCallback(() => { setInfo(null); try { interpreter?.next(); } catch (e) { setInfo(e.message); setSpeed(0); } if (interpreter?.reachedEnd) { setSpeed(0); setInfo(`Finished Execution. Took ${(Date.now() - startTime) / 1000}s`) } rerender(); }, [interpreter, startTime]); useEffect(() => { if (running) { if (speed === 0) { return; } const interval = setInterval(() => { nextHandler(); }, 1000 / (speed * 10)); return () => clearInterval(interval); } }, [running, nextHandler, speed]); return (
{ running && interpreter && <> }
{running && } {running && }
{ running && interpreter && <> } {info &&
{info}
} { running &&
Input: