%%% BEGIN pibfi_interpreter.erl %%% %%% %%% pibfi - Platonic Ideal Brainf*ck Interpreter %%% Copyright (c)2003 Cat's Eye Technologies. All rights reserved. %%% %%% Redistribution and use in source and binary forms, with or without %%% modification, are permitted provided that the following conditions %%% are met: %%% %%% Redistributions of source code must retain the above copyright %%% notice, this list of conditions and the following disclaimer. %%% %%% Redistributions in binary form must reproduce the above copyright %%% notice, this list of conditions and the following disclaimer in %%% the documentation and/or other materials provided with the %%% distribution. %%% %%% Neither the name of Cat's Eye Technologies nor the names of its %%% contributors may be used to endorse or promote products derived %%% from this software without specific prior written permission. %%% %%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND %%% CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, %%% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF %%% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE %%% DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE %%% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, %%% OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, %%% PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, %%% OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON %%% ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, %%% OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY %%% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE %%% POSSIBILITY OF SUCH DAMAGE. %% @doc Interpreter for pibfi. %% %% @end -module(pibfi_interpreter). -vsn('2003.0427'). -copyright('Copyright (c)2003 Cat`s Eye Technologies. All rights reserved.'). -export([interpret/4]). %% @spec interpret(program(), ParserOptions::[{atom(), term()}], %% Tape::pid(), IoPid::pid()) -> ok %% @doc Interprets a Brainf*ck program. If the program is given in %% an unparsed (list or binary) form, it will be parsed into a %% tuple form before proceeding. interpret(Program, ParserOptions, TapePid, IoPid) when is_binary(Program) -> interpret(pibfi_parser:parse(Program, ParserOptions), 1, TapePid, IoPid); interpret(Program, ParserOptions, TapePid, IoPid) when is_list(Program) -> interpret(pibfi_parser:parse(Program, ParserOptions), 1, TapePid, IoPid); interpret(Program, ParserOptions, TapePid, IoPid) -> [StatusCmd] = pibfi_options:get_option(ParserOptions, statuscmd, "#"), interpret(Program, 1, TapePid, IoPid, StatusCmd). interpret(Program, IP, TapePid, IoPid, StatusCmd) when IP > size(Program) -> ok; interpret(Program, IP, TapePid, IoPid, StatusCmd) -> Instruction = element(IP, Program), case Instruction of {instruction, Row, Col, Ins} -> pibfi_statistics:update_program(Row, Col, Ins); {while, Row, Col, Block} -> ok end, case execute(Instruction, TapePid, IoPid, StatusCmd) of stop -> stop; _ -> interpret(Program, IP + 1, TapePid, IoPid, StatusCmd) end. %% @spec execute(instruction(), Tape::pid(), IO::pid(), StatusCmd) -> ok %% @doc Executes a single Brainf*ck instruction. execute({instruction, Row, Column, $>}=I, TapePid, IoPid, StatusCmd) -> pibfi_tape:right(TapePid); execute({instruction, Row, Column, $<}=I, TapePid, IoPid, StatusCmd) -> pibfi_tape:left(TapePid); execute({instruction, Row, Column, $+}=I, TapePid, IoPid, StatusCmd) -> pibfi_tape:increment(TapePid); execute({instruction, Row, Column, $-}=I, TapePid, IoPid, StatusCmd) -> pibfi_tape:decrement(TapePid); execute({instruction, Row, Column, {$>, N}}=I, TapePid, IoPid, StatusCmd) -> pibfi_tape:right(TapePid, N); execute({instruction, Row, Column, {$<, N}}=I, TapePid, IoPid, StatusCmd) -> pibfi_tape:left(TapePid, N); execute({instruction, Row, Column, {$+, N}}=I, TapePid, IoPid, StatusCmd) -> pibfi_tape:increment(TapePid, N); execute({instruction, Row, Column, {$-, N}}=I, TapePid, IoPid, StatusCmd) -> pibfi_tape:decrement(TapePid, N); execute({instruction, Row, Column, $.}=I, TapePid, IoPid, StatusCmd) -> Cell = pibfi_tape:read(TapePid), pibfi_io:output(IoPid, Cell), ok; execute({instruction, Row, Column, $,}=I, TapePid, IoPid, StatusCmd) -> % ce_log:write("input"), case pibfi_io:input(IoPid) of nop -> ok; stop -> stop; Character when is_integer(Character) -> % ce_log:write("input ~c", [Character]), pibfi_tape:write(TapePid, Character), % ce_log:write("input stored as ~p", [pibfi_tape:read(TapePid)]), ok end; execute({instruction, Row, Column, StatusCmd}=I, TapePid, IoPid, StatusCmd) -> pibfi_statistics:dump(), ok; execute({while, Row, Column, SubProgram}=I, TapePid, IoPid, StatusCmd) when tuple(SubProgram) -> pibfi_statistics:update_program(Row, Column, $[), case pibfi_tape:read(TapePid) of 0 -> pibfi_statistics:update_program(Row, Column, $]), ok; _ -> case interpret(SubProgram, 1, TapePid, IoPid, StatusCmd) of stop -> stop; _ -> pibfi_statistics:update_program(Row, Column, $]), execute(I, TapePid, IoPid, StatusCmd) end end; execute(_, TapePid, IoPid, StatusCmd) -> ok. %%% END of pibfi_interpreter.erl %%%