Pure Prolog Interpreter.

Consulting file `interpreter.m'...
?- a = a.
No (more) solutions.
?- X = X.
No (more) solutions.
?- No (more) solutions.
?- No (more) solutions.
?- Y = Y.
No (more) solutions.
?- true ; true.
true ; true.
No (more) solutions.
?- :- interface.
:- module interpreter.
:- implementation.
:- import_module unsafe.
:- import_module store, tr_store, map, multi_map, assoc_list.
:- import_module list, string, term, varset, term_io, require, std_util.
:- import_module io.
:- mode database_lookup_pred_clause(in, in, out) is nondet.
:- mode database_lookup_clause(in, in, out) is nondet.
:- mode database_lookup_clause(in, in, out, out, out) is nondet.
:- mode database_assert_clause(in, in, in, out) is det.
:- mode database_init(out) is det.
:- mode deref_list(in, out, mdi, muo) is det.
:- mode deref(in, out, mdi, muo) is det.
:- mode not_occurs_list(in, in, mdi, muo) is semidet.
:- mode not_occurs(in, in, mdi, muo) is semidet.
:- mode unify_list(in, in, mdi, muo) is semidet.
:- mode unify(in, in, mdi, muo) is semidet.
:- mode solve(in, in, mdi, muo) is nondet.
:- mode my_term_to_term_list(in, out, in, out, in, out, mdi, muo) is det.
:- mode my_term_to_term(in, out, in, out, in, out, mdi, muo) is det.
:- mode my_term_to_term_list(in, out, mdi, muo) is det.
:- mode my_term_to_term(in, out, mdi, muo) is det.
:- mode term_to_my_term_list(in, out, in, out, mdi, muo) is det.
:- mode term_to_my_term(in, out, in, out, mdi, muo) is det.
:- mode term_to_my_term_list(in, out, mdi, muo) is det.
:- mode term_to_my_term(in, out, mdi, muo) is det.
:- mode consult_until_eof_2(in, in, out, di, uo) is det.
:- mode consult_until_eof(in, out, di, uo) is det.
:- mode consult(in, in, out, di, uo) is det.
:- mode consult_list(in, in, out, di, uo) is det.
:- mode write_solution(in, in, in, mdi, di, uo) is det.
:- mode print_solutions(in, in, in, mdi, in, di, uo) is cc_multi.
:- mode main_loop_2(in, in, di, uo) is cc_multi.
:- mode main_loop(in, di, uo) is cc_multi.
:- mode main(di, uo) is cc_multi.
:- pred database_lookup_pred_clause(db_pred, list(my_term(_2)), clause).
:- pred database_lookup_clause(database, my_term(_2), clause).
:- pred database_lookup_clause(database, my_term(_2), varset, term, term).
:- pred database_assert_clause(database, varset, term, database).
:- pred database_init(database).
:- pred deref_list(list(my_term(_2)), list(my_term(_2)), store(_2), store(_2)).
:- pred deref(my_term(_2), my_term(_2), store(_2), store(_2)).
:- pred not_occurs_list(list(my_term(_2)), my_var(_2), store(_2), store(_2)).
:- pred not_occurs(my_term(_2), my_var(_2), store(_2), store(_2)).
:- pred unify_list(list(my_term(_2)), list(my_term(_2)), store(_2), store(_2)).
:- pred unify(my_term(_2), my_term(_2), store(_2), store(_2)).
:- pred solve(database, my_term(_2), store(_2), store(_2)).
:- pred my_term_to_term_list(list(my_term(_2)), list(term), varset, varset, assoc_list(my_var(_2), var), assoc_list(my_var(_2), var), store(_2), store(_2)).
:- pred my_term_to_term(my_term(_2), term, varset, varset, assoc_list(my_var(_2), var), assoc_list(my_var(_2), var), store(_2), store(_2)).
:- pred my_term_to_term_list(list(my_term(_2)), list(term), store(_2), store(_2)).
:- pred my_term_to_term(my_term(_2), term, store(_2), store(_2)).
:- pred term_to_my_term_list(list(term), list(my_term(_2)), map(var, my_var(_2)), map(var, my_var(_2)), store(_2), store(_2)).
:- pred term_to_my_term(term, my_term(_2), map(var, my_var(_2)), map(var, my_var(_2)), store(_2), store(_2)).
:- pred term_to_my_term_list(list(term), list(my_term(_2)), store(_2), store(_2)).
:- pred term_to_my_term(term, my_term(_2), store(_2), store(_2)).
:- pred consult_until_eof_2(read_term, database, database, io__state, io__state).
:- pred consult_until_eof(database, database, io__state, io__state).
:- pred consult(string, database, database, io__state, io__state).
:- pred consult_list(list(string), database, database, io__state, io__state).
:- pred write_solution(varset, map(var, my_var(_2)), my_term(_2), store(_2), io__state, io__state).
:- pred print_solutions(varset, map(var, my_var(_2)), my_term(_2), store(_2), database, io__state, io__state).
:- pred main_loop_2(read_term, database, io__state, io__state).
:- pred main_loop(database, io__state, io__state).
:- pred main(io__state, io__state).
:- type clause ---> clause(varset, term, term).
:- type _2 / _3 ---> _2 / _3.
:- type db_pred ---> db_pred(list(clause), multi_map(string / int, clause)).
:- type database ---> database(list(clause), map(string / int, db_pred)).
:- type my_term(_2) ---> var(my_var(_2)) ; free ; functor(const, list(my_term(_2))).
:- type my_var(_2) == generic_mutvar(my_term(_2), _2).
No (more) solutions.
?- No (more) solutions.
?- print_solutions(_3, _4, _5, _6, _7) --> unsorted_aggregate((pred (_8 :: muo)) is nondet :- solve(_7, _5, unsafe_promise_unique(_6), _8), write_solution(_3, _4, _5)), io__write_string("No (more) solutions.\n").
consult_until_eof_2(term(_3, _4), _5, _6) --> { database_assert_clause(_5, _3, _4, _7) }, consult_until_eof(_7, _6).
consult_until_eof_2(error(_3, _4), _5, _6) --> io__write_string("Error reading term at line "), io__write_int(_4), io__write_string(" of standard input: "), io__write_string(_3), io__write_string("\n"), consult_until_eof(_5, _6).
consult_until_eof_2(eof, _3, _3) --> [].
my_term_to_term(_3, _4) --> { varset__init(_5) }, { _6 = [] }, my_term_to_term(_3, _4, _5, _7, _6, _8).
consult_list([_3 | _4], _5, _6) --> consult(_3, _5, _7), consult_list(_4, _7, _6).
consult_list([], _3, _3) --> [].
consult(_3, _4, _5) --> io__write_string("Consulting file `"), io__write_string(_3), io__write_string("\'...\n"), io__see(_3, _6), ({ _6 = ok } -> consult_until_eof(_4, _5), io__seen ; io__write_string("Error opening file `"), io__write_string(_3), io__write_string("\' for input.\n"), { _5 = _4 }).
consult_until_eof(_3, _4) --> term_io__read_term(_5), consult_until_eof_2(_5, _3, _4).
deref_list([_3 | _4], [_5 | _6]) --> deref(_3, _5), deref_list(_4, _6).
deref_list([], []) --> [].
main_loop(_3) --> io__write_string("?- "), term_io__read_term(_4), main_loop_2(_4, _3).
deref(functor(_3, _4), functor(_3, _5)) --> deref_list(_4, _5).
deref(var(_3), _4) --> tr_store__get_mutvar(_3, _5), ({ _5 \= free } -> deref(_5, _4) ; { _4 = var(_3) }).
deref(free, _3) --> { error("interpreter__deref: unexpected occurence of `free\'") }.
main --> io__write_string("Pure Prolog Interpreter.\n\n"), io__command_line_arguments(_3), ({ _3 = [] } -> io__stderr_stream(_4), io__write_string(_4, "Usage: interpreter filename ...\n"), io__set_exit_status(1) ; { database_init(_5) }, consult_list(_3, _5, _6), main_loop(_6)).
main_loop_2(term(_3, _4), _5) --> { store__new(_6) }, { map__init(_7) }, { term_to_my_term(_4, _8, _7, _9, _6, _10) }, print_solutions(_3, _9, _8, _10, _5), main_loop(_5).
main_loop_2(error(_3, _4), _5) --> io__write_string("Error reading term at line "), io__write_int(_4), io__write_string(" of standard input: "), io__write_string(_3), io__write_string("\n"), main_loop(_5).
main_loop_2(eof, _3) --> [].
my_term_to_term_list(_3, _4) --> { varset__init(_5) }, { _6 = [] }, my_term_to_term_list(_3, _4, _5, _7, _6, _8).
not_occurs(functor(_3, _4), _5) --> not_occurs_list(_4, _5).
not_occurs(var(_3), _4) --> { _3 \= _4 }, tr_store__get_mutvar(_3, _5), ({ _5 = free } -> [] ; not_occurs(_5, _4)).
my_term_to_term(functor(_3, _4), functor(_3, _5, _6), _7, _8, _9, _10) --> { context_init(_6) }, my_term_to_term_list(_4, _5, _7, _8, _9, _10).
my_term_to_term(free, variable(_3), _4, _5, _6, _6) --> { varset__new_var(_4, _3, _5) }, { error("my_term_to_term: unexpected free var") }.
my_term_to_term(var(_3), variable(_4), _5, _6, _7, _8) --> ({ assoc_list__search(_7, _3, _9) } -> { _4 = _9 }, { _10 = _5 }, { _11 = _7 } ; { varset__new_var(_5, _4, _10) }, { _11 = [_3 - _4 | _7] }), tr_store__get_mutvar(_3, _12), ({ _12 \= free } -> my_term_to_term(_12, _13, _10, _14, _11, _8), { varset__bind_var(_14, _4, _13, _6) } ; { _8 = _11 }, { _6 = _10 }).
my_term_to_term_list([_3 | _4], [_5 | _6], _7, _8, _9, _10) --> my_term_to_term(_3, _5, _7, _11, _9, _12), my_term_to_term_list(_4, _6, _11, _8, _12, _10).
my_term_to_term_list([], [], _3, _3, _4, _4) --> [].
not_occurs_list([_3 | _4], _5) --> not_occurs(_3, _5), not_occurs_list(_4, _5).
not_occurs_list([], _3) --> [].
term_to_my_term_list(_3, _4) --> { map__init(_5) }, term_to_my_term_list(_3, _4, _5, _6).
term_to_my_term(_3, _4) --> { map__init(_5) }, term_to_my_term(_3, _4, _5, _6).
solve(_3, _4) --> { database_lookup_clause(_3, _4, _5, _6, _7) }, term_to_my_term_list([_6, _7], [_8, _9]), unify(_4, _8), solve(_3, _9).
solve(_3, functor(atom("="), [_4, _5])) --> unify(_4, _5).
solve(_3, functor(atom(";"), [_4, _5])) --> solve(_3, _4) ; solve(_3, _5).
solve(_3, functor(atom(","), [_4, _5])) --> solve(_3, _4), solve(_3, _5).
solve(_3, functor(atom("true"), [])) --> [].
term_to_my_term(functor(_3, _4, _5), functor(_3, _6), _7, _8) --> term_to_my_term_list(_4, _6, _7, _8).
term_to_my_term(variable(_3), var(_4), _5, _6) --> { map__search(_5, _3, _7) } -> { _4 = _7 }, { _6 = _5 } ; tr_store__new_mutvar(free, _4), { map__det_insert(_5, _3, _4, _6) }.
unify(functor(_3, _4), functor(_3, _5)) --> unify_list(_4, _5).
unify(functor(_3, _4), var(_5)) --> tr_store__get_mutvar(_5, _6), ({ _6 \= free } -> unify(functor(_3, _4), _6) ; not_occurs_list(_4, _5), tr_store__set_mutvar(_5, functor(_3, _4))).
unify(var(_3), functor(_4, _5)) --> tr_store__get_mutvar(_3, _6), ({ _6 \= free } -> unify(_6, functor(_4, _5)) ; not_occurs_list(_5, _3), tr_store__set_mutvar(_3, functor(_4, _5))).
unify(var(_3), var(_4)) --> tr_store__get_mutvar(_3, _5), tr_store__get_mutvar(_4, _6), ({ _5 \= free } -> ({ _6 \= free } -> unify(_5, _6) ; deref(_5, _7), ({ _7 = var(_4) } -> [] ; not_occurs(_7, _4), tr_store__set_mutvar(_4, _7))) ; { _6 \= free } -> deref(_6, _8), ({ _8 = var(_3) } -> [] ; not_occurs(_8, _3), tr_store__set_mutvar(_3, _8)) ; { _3 = _4 } -> [] ; tr_store__set_mutvar(_3, var(_4))).
term_to_my_term_list([_3 | _4], [_5 | _6], _7, _8) --> term_to_my_term(_3, _5, _7, _9), term_to_my_term_list(_4, _6, _9, _8).
term_to_my_term_list([], [], _3, _3) --> [].
unify_list([_3 | _4], [_5 | _6]) --> unify(_3, _5), unify_list(_4, _6).
unify_list([], []) --> [].
write_solution(_3, _4, _5, _6) --> { map__keys(_4, _7) }, { map__values(_4, _8) }, { assoc_list__from_corresponding_lists(_8, _7, _9) }, { my_term_to_term(_5, _10, _3, _11, _9, _12, _6, _13) }, term_io__write_term_nl(_11, _10).
No (more) solutions.
?- 
