:- set_prolog_flag(verbose,silent).
:- prompt(_, '').
:- use_module(library(readutil)).

main:-
	process,
	halt.

/* Exemplo 1 (declaração) */
foo(42).
foo('bar').
foo([_,_,_|_]).

/* Exemplo 2 (declaração) */
bar(X,Y,Z) :-
    X = Y,
    foo(X),
    X = Z.

/* Exemplo 3 (declaração) */
distancia(ponto(X1,Y1), ponto(X2,Y2), D) :-
    !,
    D is sqrt((X1-X2)**2 + (Y1-Y2)**2).
distancia(_,_,_) :- throw(tipo_invalido).

process:-
	/* Exemplo 1 (uso) */
	( foo(42)             -> writeln('foo(42) é true')             ; writeln('foo(42) é false')),
	( foo(10)             -> writeln('foo(10) é true')             ; writeln('foo(10) é false')),
	( foo(1.23)           -> writeln('foo(1.23) é true')           ; writeln('foo(1.23) é false')),
	( foo([1,2,3,4,5])    -> writeln('foo([1,2,3,4,5]) é true')    ; writeln('foo([1,2,3,4,5]) é false')),
	( foo([1,2])          -> writeln('foo([1,2]) é true')          ; writeln('foo([1,2]) é false')),
	( foo(qualquer_coisa) -> writeln('foo(qualquer_coisa) é true') ; writeln('foo(qualquer_coisa) é false')),
	
	writeln('foo(QualquerCoisa) pode ser:'),
	findall(QualquerCoisa, (foo(QualquerCoisa), write('    '), writeln(QualquerCoisa)), _),
	
	nl,
	
	/* Exemplo 2 (uso) */
	bar(X, [1,A,3], [B,2,C]),
	writeln('bar(X, [1,A,3], [B,2,C])'),
	write('    X = '), writeln(X),
	write('    A = '), writeln(A),
	write('    B = '), writeln(B),
	write('    C = '), writeln(C),
	
	writeln('bar(P,_,Q), write(\'Testando: \'), writeln(P), Q = \'bar\' pode ser:'),
	findall(P, (
	    bar(P,_,Q), 
	    write('Testando: '), writeln(P), 
	    Q = 'bar',
	    write('Aceitou: '), writeln(P)
	), _),

	nl,
	
	/* Exemplo 3 (uso) */
    distancia(ponto(1,2), ponto(3,4), D),
    
    writeln('distancia(ponto(1,2), ponto(3,4), D)'),
    write('    D = '), writeln(D),
	
    write('distancia(ponto(1,2), ponto(3,4), 5) é '),
    (distancia(ponto(1,2), ponto(3,4), 5) -> writeln(true) ; writeln(false)),
    
    catch((
        distancia(foo, bar, baz) ->
        writeln('Ooops! distancia(foo, bar, baz) executou com sucesso!!!') ;
        writeln('Ooops! distancia(foo, bar, baz) executou com falha!!!')
    ), tipo_invalido, writeln('Tipo inválido em distancia(foo, bar, baz)')).


:- main.