Skip to content
plpgsql brainfuck implementation
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
LICENSE
README.md

README.md

pg_brainfuck

-- Hello, World!
select brainfuck('+[-->-[>>+>-----<<]<--<---]>-.>>>+.>>..+++[.>]<<<<.+++.------.<<-.>>>>+.');

-- test from stdin
select brainfuck(',[.,]', 'test from stdin'::bytea);
select brainfuck(',[.[-],]', 'test from stdin'::bytea);
select brainfuck(',[>,]<[.<]', 'nidts morf tset'::bytea);
create or replace function brainfuck(
  in program text,
  in stdin bytea default ''::bytea,
  out stdout text
) as $$
  declare
    commands text[] := regexp_split_to_array(program, '');
    commands_size int := array_upper(commands, 1);

    cells int[] := array[]::int[];
    jumps int[] := array[]::int[];
    stack int[] := array[]::int[];

    depth int;
    index int := 1;
    pointer int := 0;
    read int := 0;
    subindex int;
  begin
    while index <= commands_size loop
      case commands[index]
      when '>' then
        pointer = pointer + 1;
      when '<' then
        pointer = pointer - 1;
      when '+' then
        cells[pointer] = coalesce(cells[pointer], 0) + 1;
        cells[pointer] = coalesce(nullif(cells[pointer], 256), 0);
      when '-' then
        cells[pointer] = coalesce(cells[pointer], 0) - 1;
        cells[pointer] = coalesce(nullif(cells[pointer], -1), 255);
      when '.' then
        continue when coalesce(cells[pointer], 0) = 0;
        stdout = coalesce(stdout, '') || chr(cells[pointer]);
      when ',' then
        begin
          cells[pointer] = get_byte(stdin, read);
          read = read + 1;
        exception when array_subscript_error then
          index = index + 1;
        end;
      when ']' then
        if array_length(stack, 1) > 0 then
          subindex = stack[array_upper(stack, 1)];
          stack = array_remove(stack, subindex);
          jumps[subindex] = index;
          index = subindex - 1;
        end if;
      when '[' then
        if coalesce(cells[pointer], 0) != 0 then
          stack = array_append(stack, index);
        elsif jumps[index] is not null then
          index = jumps[index];
        else
          depth = 1;
          index = index + 1;
          subindex = index;

          while subindex <= commands_size loop
            case commands[subindex]
            when '[' then depth = depth + 1;
            when ']' then depth = depth - 1;
            else end case;

            if depth = 0 then
              jumps[index] = subindex;
              index = subindex;
              exit;
            end if;

            subindex = subindex + 1;
          end loop;
        end if;
      else end case;

      index = index + 1;
    end loop;
  end;
$$ language plpgsql immutable;
You can’t perform that action at this time.