diff --git a/ibfi-ts/src/App.scss b/ibfi-ts/src/App.scss
index adfc14f..ea759ab 100644
--- a/ibfi-ts/src/App.scss
+++ b/ibfi-ts/src/App.scss
@@ -51,12 +51,8 @@ $medium-color: #78787f;
border: $border;
}
- .pointer {
-
- }
-
th, td {
- width: 30px;
+ min-width: 60px;
text-align: center;
}
}
@@ -69,6 +65,13 @@ $medium-color: #78787f;
width: 200px;
}
+ .program-input-area {
+ resize: none;
+ width: 80vw;
+ height: 50px;
+ font-size: 30px;
+ }
+
.error {
background-color: #664242FF;
}
diff --git a/ibfi-ts/src/App.tsx b/ibfi-ts/src/App.tsx
index b719e72..28f65f3 100644
--- a/ibfi-ts/src/App.tsx
+++ b/ibfi-ts/src/App.tsx
@@ -1,22 +1,18 @@
import './App.scss';
-import CodeInput from "./components/CodeInput";
+import CodeInput, {CodeOptions} from "./components/CodeInput";
import ProgramOutput from "./components/ProgramOutput";
import React, {useCallback, useState} from "react";
import Runner from "./components/Runner";
function App() {
const [out, setOut] = useState("");
- const [input, setInput] = useState("");
+ const [input, setInput] = useState<[string, CodeOptions]>(["", {}]);
const [running, setRunning] = useState(false);
const outHandler = useCallback((char: number) => {
setOut(out => out + String.fromCharCode(char))
}, []);
- const inHandler = useCallback((): number => {
- return 65;
- }, []);
-
const runHandler = (run: boolean) => {
setRunning(run);
if (!run) {
@@ -24,12 +20,14 @@ function App() {
}
}
+ const inputHandler = (code: string, options: CodeOptions) => setInput([code, options]);
+
return (
{
- !running &&
setInput(input)}/>
+ !running &&
}
-
+
{
running &&
}
diff --git a/ibfi-ts/src/brainfuck/Interpreter.ts b/ibfi-ts/src/brainfuck/Interpreter.ts
index 82cc6b8..0664fca 100644
--- a/ibfi-ts/src/brainfuck/Interpreter.ts
+++ b/ibfi-ts/src/brainfuck/Interpreter.ts
@@ -1,3 +1,5 @@
+import {CodeOptions} from "../components/CodeInput";
+
type InHandler = (() => number);
type OutHandler = ((char: number) => void);
type ErrorHandler = ((msg: string) => void);
@@ -6,25 +8,31 @@ export default class Interpreter {
private readonly _array: Uint8Array;
private _pointer: number;
private readonly _code: string;
- private _codePointer: number;
+ private _programCounter: number;
private readonly _inHandler: InHandler;
private readonly _outHandler: OutHandler;
private readonly _errorHandler: ErrorHandler;
- constructor(code: string, outHandler: OutHandler, inHandler: InHandler, errorHandler: ErrorHandler) {
+ constructor(input: [string, CodeOptions], outHandler: OutHandler, inHandler: InHandler, errorHandler: ErrorHandler) {
const buf = new ArrayBuffer(32000);
this._array = new Uint8Array(buf);
this._pointer = 0;
- this._code = code;
- this._codePointer = 0;
+
+ if (input[1].minify) {
+ this._code = minify(input[0])
+ } else {
+ this._code = input[0];
+ }
+
+ this._programCounter = 0;
this._inHandler = inHandler;
this._outHandler = outHandler;
this._errorHandler = errorHandler;
}
public next() {
- switch (this._code[this._codePointer++]) {
+ switch (this._code[this._programCounter++]) {
case '+':
this._array[this._pointer]++;
break;
@@ -45,13 +53,18 @@ export default class Interpreter {
this._outHandler(this.value);
break;
case ',':
- this._array[this._pointer] = this._inHandler();
+ try {
+ this._array[this._pointer] = this._inHandler();
+ } catch {
+ this._programCounter--;
+ this._errorHandler("Could not read input, trying again next time.")
+ }
break;
case '[':
if (this.value === 0) {
let level = 0;
while (this.lastInstruction !== ']' || level > -1) {
- this._codePointer++;
+ this._programCounter++;
if (this.lastInstruction === '[') level++;
else if (this.lastInstruction === ']') level--;
}
@@ -61,20 +74,20 @@ export default class Interpreter {
if (this.value !== 0) {
let level = 0;
while (this.lastInstruction !== '[' || level > -1) {
- this._codePointer--;
+ this._programCounter--;
if (this.lastInstruction === '[') level--;
else if (this.lastInstruction === ']') level++;
}
}
break;
case undefined:
- this._pointer--;
+ this._pointer = this._code.length;
console.warn("reached end");
break;
default: {
}
}
- console.log(`char: ${this.code[this.codePointer - 1]} pointer: ${this.pointer} value: ${this.array[this.pointer]}`)
+ console.log(`char: ${this.code[this.programCounter - 1]} pointer: ${this.pointer} value: ${this.array[this.pointer]}`)
}
public prev() {
@@ -82,11 +95,11 @@ export default class Interpreter {
}
get reachedEnd(): boolean {
- return this._codePointer === this._code.length - 1;
+ return this._programCounter === this._code.length;
}
get lastInstruction(): string {
- return this._code[this._codePointer - 1];
+ return this._code[this._programCounter - 1];
}
get value(): number {
@@ -105,7 +118,14 @@ export default class Interpreter {
return this._code;
}
- get codePointer(): number {
- return this._codePointer;
+ get programCounter(): number {
+ return this._programCounter;
}
-}
\ No newline at end of file
+}
+
+const CHARS = ['+', '-', '<', '>', '.', ',', '[', ']'];
+const minify = (code: string): string =>
+ code.split("")
+ .filter(c => CHARS.includes(c))
+ .join("");
+
diff --git a/ibfi-ts/src/components/CodeDisplay.tsx b/ibfi-ts/src/components/CodeDisplay.tsx
index 0affb6f..da3b88b 100644
--- a/ibfi-ts/src/components/CodeDisplay.tsx
+++ b/ibfi-ts/src/components/CodeDisplay.tsx
@@ -13,7 +13,7 @@ const CodeDisplay = ({code, index}: CodeDisplayProps) => {
return (
{firstCodePart}
- {code[index]}
+ {code[index] || " "}
{secondCodePart}
);
diff --git a/ibfi-ts/src/components/CodeInput.tsx b/ibfi-ts/src/components/CodeInput.tsx
index 9c2c23e..179b7bd 100644
--- a/ibfi-ts/src/components/CodeInput.tsx
+++ b/ibfi-ts/src/components/CodeInput.tsx
@@ -1,27 +1,48 @@
import React, {useState} from 'react';
-interface CodeInputProps {
- setInput: ((input: string) => void),
+export interface CodeOptions {
+ minify?: boolean
}
-const CodeInput = ({setInput}: CodeInputProps) => {
+interface CodeInputProps {
+ setInput: ((code: string, options: CodeOptions) => void),
+ code: string
+}
+
+const CodeInput = ({code, setInput}: CodeInputProps) => {
const [fontSize, setFontSize] = useState(40);
+ const [codeOptions, setCodeOptions] = useState({});
+
+
const setStart = () => {
setInput(
- "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.");
+ "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.",
+ codeOptions);
+ }
+
+ const changeMinify = (e: React.ChangeEvent) => {
+ setCodeOptions(old => ({...old, minify: e.target.checked}))
+ setInput(code, codeOptions);
}
return (
);
diff --git a/ibfi-ts/src/components/RunDisplay.tsx b/ibfi-ts/src/components/RunDisplay.tsx
index aa930ca..7ba8706 100644
--- a/ibfi-ts/src/components/RunDisplay.tsx
+++ b/ibfi-ts/src/components/RunDisplay.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import Interpreter from "../brainfuck/Interpreter";
-const MAX_TABLE_COLUMNS = 30;
+const MAX_TABLE_COLUMNS = 20;
interface RunDisplayProps {
interpreter: Interpreter,
diff --git a/ibfi-ts/src/components/Runner.tsx b/ibfi-ts/src/components/Runner.tsx
index c62112d..6683834 100644
--- a/ibfi-ts/src/components/Runner.tsx
+++ b/ibfi-ts/src/components/Runner.tsx
@@ -1,33 +1,47 @@
-import React, {useCallback, useEffect, useState} from 'react';
+import React, {useCallback, useEffect, useRef, useState} from 'react';
import Interpreter from "../brainfuck/Interpreter";
import CodeDisplay from "./CodeDisplay";
import RunDisplay from "./RunDisplay";
+import {CodeOptions} from "./CodeInput";
interface RunInfoProps {
- input: string,
+ input: [string, CodeOptions],
setRunning: (running: boolean) => void,
running: boolean
- inHandler: () => number,
outHandler: (char: number) => void,
}
-const Runner = ({setRunning, running, inHandler, outHandler, input}: RunInfoProps) => {
+const Runner = ({setRunning, running, outHandler, input}: RunInfoProps) => {
const [speed, setSpeed] = useState(0);
const [interpreter, setInterpreter] = useState(null);
const [error, setError] = useState(null);
const [, setRerenderNumber] = useState(0);
- const errorHandler = (msg: string) => {
- setError(msg);
+ 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 errorHandler = (msg: string) => setError(msg);
+
const startHandler = useCallback(() => {
setSpeed(0);
- setInterpreter(new Interpreter(input, outHandler, inHandler, errorHandler));
+ setInterpreter(new Interpreter(input, outHandler, inputHandler, errorHandler));
setRunning(false);
setRunning(true);
- }, [input, inHandler, outHandler, setRunning]);
+ }, [input, outHandler, setRunning]);
const stopHandler = () => setRunning(false);
@@ -58,7 +72,7 @@ const Runner = ({setRunning, running, inHandler, outHandler, input}: RunInfoProp
{
running && interpreter && <>
-
+
>
}
@@ -78,7 +92,13 @@ const Runner = ({setRunning, running, inHandler, outHandler, input}: RunInfoProp
>
}
{
- error && Error: '{error}'
+ error && {error}
+ }
+ {
+ running &&
}
);