$ include ;

const proc: snusp (in string: sourceCode, in integer: memSize, inout file: input, inout file: output) is func
  local
    var array string: instructions is 0 times ;
    var array char: memory is 0 times ' ';
    var integer: dataPointer is 1;
    var integer: instrPtrRow is 0;
    var integer: instrPtrColumn is 0;
    var integer: rowDir is 0;
    var integer: columnDir is 1;
    var integer: helpDir is 0;
    var integer: row is 0;
  begin
    instructions:= split(sourceCode, );
    memory:= memSize times '\0;';

    for key row range instructions do
      if pos(instructions[row], '$') <> 0 then
        instrPtrRow:= row;
        instrPtrColumn:= pos(instructions[row], '$');
      end if;
    end for;

    while instrPtrRow >= 1 and instrPtrRow <= length(instructions) and
        instrPtrColumn >= 1 and instrPtrColumn <= length(instructions[instrPtrRow]) do
      case instructions[instrPtrRow][instrPtrColumn] of
        when {'>'}:  incr(dataPointer);
        when {'<'}:  decr(dataPointer);
        when {'+'}:  incr(memory[dataPointer]);
        when {'-'}:  decr(memory[dataPointer]);
        when {'.'}:  write(output, memory[dataPointer]);
        when {','}:  memory[dataPointer]:= getc(input);
        when {'/'}:  helpDir:= rowDir;
                     rowDir:= -columnDir;
                     columnDir:= -helpDir;
        when {'\\'}: helpDir:= rowDir;
                     rowDir:= columnDir;
                     columnDir:= helpDir;
        when {'!'}:  instrPtrRow +:= rowDir;
                     instrPtrColumn +:= columnDir;
        when {'?'}:  if memory[dataPointer] = '\0;' then
                       instrPtrRow +:= rowDir;
                       instrPtrColumn +:= columnDir;
                     end if;
      end case;
      instrPtrRow +:= rowDir;
      instrPtrColumn +:= columnDir;
    end while;
  end func;


const string: helloWorld is ;

const proc: main is func
  begin
    snusp(helloWorld, 5, IN, OUT);
  end func;