%% Attempt 1, BF interpreter for erlang %% %% %% > Move pointer forward %% < Move pointer back %% + Increment value at pointer %% - Decrement value at pointer %% . Print value at current pointer position as char %% [ If current value is 0, jump forward to after the corresponding ] %% ] If current value is NOT 0, jump backward to after the corresponding [ %% %% %% How to use: %% %% Put in bf.erl %% apt-get install erl %% erl %% P = "" %% c("bf"). %% bf:bf(P). -module(bf). -export([bf/1]). %% Convenience method, run code with 0 pointer and empty memory bf(Code) -> bf(Code, 0, [], []). %% Run out of code, return final memory layout bf([], P, M, _) -> ok; %% Step through code bf([I|RestOfCode], P, M, PreviousCode) -> V = get_mem(P, M), %% You can't use a function in a guard! %%io:format("~c ~w~n", [I, V]), case ([I]) of ">" -> bf(RestOfCode, P+1, M, [I|PreviousCode]); "<" -> bf(RestOfCode, P-1, M, [I|PreviousCode]); "+" -> bf(RestOfCode, P, set_mem(P, get_mem(P,M)+1, M), [I|PreviousCode]); "-" -> bf(RestOfCode, P, set_mem(P, get_mem(P,M)-1, M), [I|PreviousCode]); "[" -> if V == 0 -> %%io:format("jumping forward"), jump(RestOfCode, P, M, 1, [I|PreviousCode]); true -> bf(RestOfCode, P, M, [I|PreviousCode]) end; "]" -> if V /= 0 -> %%io:format("jumping back"), jump_back([I|RestOfCode], P, M, 1, PreviousCode); true -> bf(RestOfCode, P, M, [I|PreviousCode]) end; "." -> io:format("~c",[get_mem(P, M)]), bf(RestOfCode, P, M, [I|PreviousCode]); _ -> bf(RestOfCode, P, M, [I|PreviousCode]) end. %% Jump forward to matching ] %% Short-circuit for end condition. jump([I|RestOfCode], P, M, 1, PreviousCode) when [I] == "]" -> bf(RestOfCode, P, M, [I|PreviousCode]); %% Scan forward counting up and down for [ and ] (we start at 1) jump([I|RestOfCode], P, M, C, PreviousCode) -> case ([I]) of "[" -> jump(RestOfCode, P, M, C+1, [I|PreviousCode]); "]" -> jump(RestOfCode, P, M, C-1, [I|PreviousCode]); _ -> jump(RestOfCode, P, M, C, [I|PreviousCode]) end. %% Jump backward to matching [ %% Short-circuit for end condition. jump_back(RestOfCode, P, M, 1, [I|PreviousCode]) when [I] == "[" -> bf([I|RestOfCode], P, M, PreviousCode); %% Scan backward counting up and down for [ and ] (we start at 1) jump_back(RestOfCode, P, M, C, [I|PreviousCode]) -> case ([I]) of "[" -> jump_back([I|RestOfCode], P, M, C-1, PreviousCode); "]" -> jump_back([I|RestOfCode], P, M, C+1, PreviousCode); _ -> jump_back([I|RestOfCode], P, M, C, PreviousCode) end. %% Memory manipulation %% get_mem gets the value for the given position get_mem(P, M) -> if (P < length(M)) -> lists:nth(P+1, M); true -> 0 end. %% set_mem puts the value in the given position set_mem(P, V, M) -> if (P < length(M)) -> {Before, T} = lists:split(P, M), [_|After] = T, Before ++ [V] ++ After; (P == length(M)) -> M ++ [V]; true -> M ++ lists:duplicate(P-length(M)-1,0) ++ [V] end.