interpreter

This commit is contained in:
nora 2021-06-23 17:01:15 +02:00
parent b30fa04dcc
commit e815fd8c66
8 changed files with 647 additions and 19 deletions

View file

@ -1,3 +1,7 @@
$main-color: #282c34;
$main-color-brighter: #323942;
$font-color: ghostwhite;
.App {
text-align: center;
}
@ -8,16 +12,48 @@
}
.App-header {
background-color: #282c34;
background-color: $main-color;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
color: $font-color;
}
.App-link {
color: #61dafb;
}
.bf-input {
.code-input {
resize: none;
width: 80vw;
height: 400px;
font-size: 100px;
}
}
.bf-run {
margin: 20px;
button {
height: 50px;
width: 200px;
}
}
.bf-output {
.output-area {
resize: none;
width: 80vw;
height: 200px;
font-size: 20px;
}
}
textarea {
background-color: $main-color-brighter;
color: $font-color;
}

View file

@ -1,13 +1,35 @@
import './App.scss';
import CodeInput from "./components/CodeInput";
import ProgramOutput from "./components/ProgramOutput";
import React, {useState} from "react";
import Interpreter from "./brainfuck/Interpreter";
import RunInfo from "./components/RunInfo";
function App() {
const [interpreter, setInterpreter] = useState<Interpreter | null>(null);
const [out, setOut] = useState("");
const [input, setInput] = useState("");
const outHandler = (char: number) => {
setOut(out => out + String.fromCharCode(char))
}
const inHandler = (): number => {
return 65;
}
const start = () => setInterpreter(new Interpreter(input, outHandler, inHandler));
const next = () => interpreter?.next();
const prev = () => interpreter?.prev();
return (
<div className="App-header">
<div className="bf-input">
<textarea placeholder="Input your code here..."/>
</div>
<CodeInput setInput={input => setInput(input)}/>
<RunInfo nextHandler={next} prevHandler={prev} startHandler={start} interpreter={interpreter}/>
<ProgramOutput text={out}/>
</div>
);
}
export default App;
export default App;

View file

@ -0,0 +1,76 @@
export default class Interpreter {
private readonly _array: Uint8Array;
private _pointer: number;
private readonly _code: string;
private _codePointer: number;
private _inHandler: (() => number);
private _outHandler: ((char: number) => void);
constructor(code: string, outHandler: ((char: number) => void), inHandler: (() => number)) {
const buf = new ArrayBuffer(32000);
this._array = new Uint8Array(buf);
this._pointer = 0;
this._code = code;
this._codePointer = 0;
this._inHandler = inHandler;
this._outHandler = outHandler;
}
public next() {
switch (this._code[++this._codePointer]) {
case '+':
this._array[this._pointer]++;
break;
case '-':
this._array[this._pointer]--;
break;
case '>':
this._pointer++;
break;
case '<':
this._pointer--;
break;
case '.':
this._outHandler(this._array[this._pointer]);
break;
case ',':
this._array[this._pointer] = this._inHandler();
break;
case '[':
console.error("does not support [ for now")
break;
case ']':
console.error("does not support ] for now")
break;
default: {
}
}
console.log("next step")
}
public prev() {
}
get value(): number {
return this._array[this._pointer];
}
get array(): Uint8Array {
return this._array;
}
get pointer(): number {
return this._pointer;
}
get code(): string {
return this._code;
}
get codePointer(): number {
return this._codePointer;
}
}

View file

@ -0,0 +1,23 @@
import React, {useState} from 'react';
interface CodeInputProps {
setInput: ((input: string) => void),
}
const CodeInput = ({setInput}: CodeInputProps) => {
const [fontSize, setFontSize] = useState(40);
return (
<div>
<div className="bf-input">
<div>
<label htmlFor="bf-input-fontsize-range">Font Size</label>
<input type="range" id="bf-input-fontsize-range" onChange={v => setFontSize(+v.target.value)}/>
</div>
<textarea onChange={e => setInput(e.target.value)} style={{fontSize}} className="code-input" placeholder="Input your code here..."/>
</div>
</div>
);
};
export default CodeInput;

View file

@ -0,0 +1,15 @@
import React from 'react';
interface ProgramOutputProps {
text: string
}
const ProgramOutput = ({text}: ProgramOutputProps) => {
return (
<div className="bf-output">
<textarea readOnly className="output-area" value={text}/>
</div>
);
};
export default ProgramOutput;

View file

@ -0,0 +1,28 @@
import React from 'react';
import Interpreter from "../brainfuck/Interpreter";
interface RunInfoProps {
nextHandler: () => void,
prevHandler: () => void,
startHandler: () => void,
interpreter: Interpreter | null,
}
const RunInfo = ({interpreter, ...props}: RunInfoProps) => {
return (
<div className="bf-run">
<div>
<button onClick={props.startHandler}>Start</button>
<button onClick={props.nextHandler}>Next</button>
<button onClick={props.prevHandler}>Previous</button>
</div>
{interpreter &&
<div>Pointer: {interpreter.pointer} value {interpreter.value}</div>
}
</div>
);
}
;
export default RunInfo;