Delphi: Basic Brainfuck Interpreter

This is a really basic commandline brainfuck interpreter, it’s not written for speed or performance, it just shows you how a brainfuck interpreter should work. Of course you can speed it up by converting the code to a form of bytecode, working with pointers or even convert it to machine code.

program Brainfuck;

{$APPTYPE CONSOLE}

uses
  Classes;

const
  ARRAY_SIZE = 30000;

type
  TBFEngine = class
  private
    FScript: TStrings;
    FCompiled: AnsiString;
    FArr: array of Byte;
    FIndex: Integer;
    procedure Compile;
    procedure ClearArray;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Run;
    property Script: TStrings read FScript;
  end;

{ TBFEngine }

procedure TBFEngine.ClearArray;
var
  i, l: Integer;
begin
  l := Length(FArr);
  for i := 0 to l - 1 do
    FArr[i] := 0;
end;

procedure TBFEngine.Compile;
var
  i, l: Integer;
begin
  l := Length(FScript.Text);
  FCompiled := '';
  for i := 1 to l do
    if FScript.Text[i] in ['>', '<', '+', '-', '.', ',', '[', ']'] then
      FCompiled := FCompiled + FScript.Text[i];
end;

constructor TBFEngine.Create;
begin
  FScript := TStringList.Create;
  SetLength(FArr, ARRAY_SIZE);
end;

destructor TBFEngine.Destroy;
begin
  FScript.Free;
end;

procedure TBFEngine.Run;
var
  c: AnsiChar;
  i, j, l, t: Integer;
begin
  Compile;
  ClearArray;
  t := 0;
  FIndex := 0;
  l := Length(FCompiled);
  i := 1;
  while i <= l do
  begin
    case FCompiled[i] of
      '>':
        if FIndex <> (ARRAY_SIZE - 1) then
          Inc(FIndex);
      '<':
        if FIndex <> 0 then
          Dec(FIndex);
      '+': Inc(FArr[FIndex]);
      '-': Dec(FArr[FIndex]);
      '.': Write(Chr(FArr[FIndex]));
      ',': Read(FArr[FIndex]);
      '[':
        if not Boolean(FArr[FIndex]) then
          for j := i + 1 to l do
          begin
            c := FCompiled[j];
            if c = '[' then
              Inc(t)
            else if c = ']' then
              if t <> 0 then
                Dec(t)
              else begin
                i := j;
                Break;
              end;
          end;
      ']':
        if Boolean(FArr[FIndex]) then
          for j := i - 1 downto 1 do
          begin
            c := FCompiled[j];
            if c = ']' then
              Inc(t)
            else if c = '[' then
              if t <> 0 then
                Dec(t)
              else begin
                i := j;
                Break;
              end;
          end;
    end;
    Inc(i);
  end;
end;

var
  Engine: TBFEngine;
begin
  if ParamCount = 1 then
  begin
    Engine := TBFEngine.Create;
    Engine.Script.LoadFromFile(ParamStr(1));
    Engine.Run;
    Engine.Free;
  end;
end.

Hello world in brainfuck:
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.——.——–.>+.>.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.