138 lines
3.6 KiB
ObjectPascal
138 lines
3.6 KiB
ObjectPascal
program Execute_Brain;
|
|
|
|
{$APPTYPE CONSOLE}
|
|
|
|
uses
|
|
Winapi.Windows,
|
|
System.SysUtils;
|
|
|
|
const
|
|
DataSize = 1024; // Size of Data segment
|
|
MaxNest = 1000; // Maximum nesting depth of []
|
|
|
|
function Readkey: Char;
|
|
var
|
|
InputRec: TInputRecord;
|
|
NumRead: Cardinal;
|
|
KeyMode: DWORD;
|
|
StdIn: THandle;
|
|
begin
|
|
StdIn := GetStdHandle(STD_INPUT_HANDLE);
|
|
GetConsoleMode(StdIn, KeyMode);
|
|
SetConsoleMode(StdIn, 0);
|
|
|
|
repeat
|
|
ReadConsoleInput(StdIn, InputRec, 1, NumRead);
|
|
if (InputRec.EventType and KEY_EVENT <> 0) and InputRec.Event.KeyEvent.bKeyDown then
|
|
begin
|
|
if InputRec.Event.KeyEvent.AsciiChar <> #0 then
|
|
begin
|
|
Result := InputRec.Event.KeyEvent.UnicodeChar;
|
|
Break;
|
|
end;
|
|
end;
|
|
until FALSE;
|
|
|
|
SetConsoleMode(StdIn, KeyMode);
|
|
end;
|
|
|
|
procedure ExecuteBF(Source: string);
|
|
var
|
|
Dp: pByte; // Used as the Data Pointer
|
|
DataSeg: Pointer; // Start of the DataSegment (Cell 0)
|
|
Ip: pChar; // Used as instruction Pointer
|
|
LastIp: Pointer; // Last adr of code.
|
|
JmpStack: array[0..MaxNest - 1] of pChar; // Stack to Keep track of active "[" locations
|
|
JmpPnt: Integer; // Stack pointer ^^
|
|
JmpCnt: Word; // Used to count brackets when skipping forward.
|
|
|
|
begin
|
|
|
|
// Set up then data segment
|
|
getmem(DataSeg, dataSize);
|
|
Dp := DataSeg;
|
|
// fillbyte(dp^,dataSize,0);
|
|
FillChar(Dp^, DataSize, 0);
|
|
|
|
// Set up the JmpStack
|
|
JmpPnt := -1;
|
|
|
|
// Set up Instruction Pointer
|
|
Ip := @Source[1];
|
|
LastIp := @Source[length(Source)];
|
|
if Ip = nil then
|
|
exit;
|
|
|
|
// Main Execution loop
|
|
repeat { until Ip > LastIp }
|
|
case Ip^ of
|
|
'<':
|
|
dec(Dp);
|
|
'>':
|
|
inc(Dp);
|
|
'+':
|
|
inc(Dp^);
|
|
'-':
|
|
dec(Dp^);
|
|
'.':
|
|
write(chr(Dp^));
|
|
',':
|
|
Dp^ := ord(ReadKey);
|
|
'[':
|
|
if Dp^ = 0 then
|
|
begin
|
|
// skip forward until matching bracket;
|
|
JmpCnt := 1;
|
|
while (JmpCnt > 0) and (Ip <= LastIp) do
|
|
begin
|
|
inc(Ip);
|
|
case Ip^ of
|
|
'[':
|
|
inc(JmpCnt);
|
|
']':
|
|
dec(JmpCnt);
|
|
#0:
|
|
begin
|
|
Writeln('Error brackets don''t match');
|
|
halt;
|
|
end;
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
// Add location to Jump stack
|
|
inc(JmpPnt);
|
|
JmpStack[JmpPnt] := Ip;
|
|
end;
|
|
']':
|
|
if Dp^ > 0 then
|
|
// Jump Back to matching [
|
|
Ip := JmpStack[JmpPnt]
|
|
else // Remove Jump from stack
|
|
dec(JmpPnt);
|
|
end;
|
|
inc(Ip);
|
|
until Ip > LastIp;
|
|
freemem(DataSeg, dataSize);
|
|
end;
|
|
|
|
const
|
|
HelloWorldWiki = '++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>' +
|
|
'---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.';
|
|
pressESCtoCont = '>[-]+++++++[<++++++++++>-]<->>[-]+++++++[<+++++++++++' +
|
|
'+>-]<->>[-]++++[<++++++++>-]+>[-]++++++++++[<++++++++' +
|
|
'++>-]>[-]++++++++[<++++++++++++++>-]<.++.+<.>..<<.<<.' +
|
|
'-->.<.>>.>>+.-----.<<.[<<+>>-]<<.>>>>.-.++++++.<++++.' +
|
|
'+++++.>+.<<<<++.>+[>+<--]>++++...';
|
|
waitForEsc = '[-]>[-]++++[<+++++++>-]<->[-]>+[[-]<<[>+>+<<-]' + '>>[<' +
|
|
'<+>>-],<[->-<]>]';
|
|
|
|
begin
|
|
// Execute "Hello World" example from Wikipedia
|
|
ExecuteBF(HelloWorldWiki);
|
|
|
|
// Print text "press ESC to continue....." and wait for ESC to be pressed
|
|
ExecuteBF(pressESCtoCont + waitForEsc);
|
|
end.
|