% vim: ft=mercury ts=4 sw=4 et

%  Compiling this module as follows with rotd-2011-02-14 and before:
%
%     mmc --infer-all bug186a.m
%
% results in:
%
%     Uncaught Mercury exception:
%     Software Error: unique_modes.m: Unexpected: call to implied mode?
%
% Test case derived from Vladimir Gubarkov's brainfuck interpreter,
% <http://www.xonix.info/2011/02/brainfuck-mercury.html>.  See also:
% <http://www.mercury.csse.unimelb.edu.au/mailing-lists/mercury-users/mercury-users.201102/0004.html>

:- module bug186a.
:- interface.

:- import_module io.

:- pred main(io::di, io::uo) is det.

:- implementation.

:- import_module list.
:- import_module string.
:- import_module char.
:- import_module solutions.
:- import_module require.
:- import_module int.
:- import_module bool.

:- type bf_cmd
    --->    plus
    ;       cycle(list(bf_cmd)).

chars_to_ast(Chars) = Ast :-
    (  
        one_solution(
            (pred(Ast_::out) is nondet :- ast(Ast_, Chars, []:list(char))),
            Ast0)
    ->
        Ast = Ast0
    ;
        error("Program invalid (parse error)!")
    ).

one_solution(Pred, Solution) :-
    solutions(Pred, [Solution| _]).

% Works with this line uncommented.
%:- mode ast(out, in, out) is multi.

ast([plus|Cmds]) --> ['+'], ast(Cmds).
ast([cycle(Cycle)|Cmds]) --> ['['], ast(Cycle), [']'], ast(Cmds).
ast([]) --> [].

:- type bf_option ---> print_ast; help; do_not_optimize.

main(!IO).
