:- module match.
/*-----------------------------------------------------*/
:- interface.

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

/*-----------------------------------------------------*/
:- implementation.
:- import_module list, int, std_util, string.

main --> 
    io__command_line_arguments(Args),
    (
	{ Args = [P1,N1,P2] } ->
	{ solutions( match(P1, N1, P2), Sols) },
	io__write_string("Pattern '"), io__write_string(P1), 
	io__write_string("' matches '"), io__write_string(N1), 
	io__write_string("' as '"), io__write_string(P2), 
	io__write_string("' matches the following:\n\n"), 
	write_sols(Sols)
    ;                 
        io__write_string("Usage: match <p1> <n1> <p2>\n")
    ).

:- pred write_sols(list(string)::in, io__state::di, 
           io__state::uo) is det.
write_sols([])-->
    io__write_string("\n*** No (more) solutions\n\n").
write_sols([S|Ss])-->
    io__write_string("    "), io__write_string(S), 
    io__write_string("\n"), write_sols(Ss).

:- pred match(string::in, string::in, string::in, 
      string::out) is nondet.
match(Pattern1, Name1, Pattern2, Name2):-
    string__to_char_list(Pattern1, Ps1),
    string__to_char_list(Name1, Cs1),
    string__to_char_list(Pattern2, Ps2),
    match_list(Ps1, Cs1, L),
    match_list(Ps2, Cs2, L),
    string__from_char_list(Cs2, Name2).

:- type subst ---> any(list(character))  ;  one(character).

:- pred match_list(list(character), list(character), list(subst)).
:- mode match_list(in, in, out) is nondet.
:- mode match_list(in, out, in) is nondet.
match_list([], [], []).
match_list([?|Ps], Cs, [one(X)|L]):-
    Cs = [X|Cs1],
    match_list(Ps, Cs1, L).
match_list([*|Ps], Cs, [any(X)|L]):-
    list__append(X, Cs1, Cs),
    match_list(Ps, Cs1, L).
match_list([\, C|Ps],  [C|Cs], L):-
    match_list(Ps, Cs, L).
match_list([C|Ps], [C|Cs], L):-
    C \= (*), C \= (?), C \= (\), 
    match_list(Ps, Cs, L).


