-
Notifications
You must be signed in to change notification settings - Fork 8
/
My smallest code interpreter (aka Brainf**k).js
64 lines (61 loc) · 2.58 KB
/
My smallest code interpreter (aka Brainf**k).js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*
Description:
Inspired from real-world Brainf**k, we want to create an interpreter of that language which will support the following instructions (the machine memory or 'data' should behave like a potentially infinite array of bytes, initialized to 0):
> increment the data pointer (to point to the next cell to the right).
< decrement the data pointer (to point to the next cell to the left).
+ increment (increase by one, truncate overflow: 255 + 1 = 0) the byte at the data pointer.
- decrement (decrease by one, treat as unsigned byte: 0 - 1 = 255 ) the byte at the data pointer.
. output the byte at the data pointer.
, accept one byte of input, storing its value in the byte at the data pointer.
[ if the byte at the data pointer is zero, then instead of moving the instruction pointer forward to the next command, jump it forward to the command after the matching ] command.
] if the byte at the data pointer is nonzero, then instead of moving the instruction pointer forward to the next command, jump it back to the command after the matching [ command.
The function will take in input...
the program code, a string with the sequence of machine instructions,
the program input, a string, eventually empty, that will be interpreted as an array of bytes using each character's ASCII code and will be consumed by the , instruction
... and will return ...
the output of the interpreted code (always as a string), produced by the . instruction.
*/
code = code.split('').filter(c => '><+-.,[]'.includes(c))
let output = '',
ptr = 0,
brackets = 0,
i
const data = [0],
map = {
'>': () => {
ptr++
if (ptr >= data.length) data.push(0)
},
'<': () => ptr--,
'+': () => (data[ptr] = (data[ptr] + 1) % 256),
'-': () => (data[ptr] = (data[ptr] - 1) % 256),
',': () => {
data[ptr] = input.charCodeAt(0)
input = input.slice(1)
},
'.': () => (output += String.fromCharCode(data[ptr])),
'[': () => {
if (data[ptr]) return
for (let j = i + 1; j < code.length; j++)
if (code[j] === '[') brackets++
else if (code[j] === ']')
if (brackets) brackets--
else {
i = j
break
}
},
']': () => {
if (!data[ptr]) return
for (let j = i - 1; j >= 0; j--)
if (code[j] === ']') brackets++
else if (code[j] === '[')
if (brackets) brackets--
else {
i = j
break
}
}
}
for (i = 0; i < code.length; i++) map[code[i]]()
return output