%%% -*- erlang-indent-level: 2 -*-
%%%-------------------------------------------------------------------
%%% Author: Kostis Sagonas
%%%
%%% Contains tests for correct execution of comparison operators.
%%%-------------------------------------------------------------------
-module(basic_comparisons).
-export([test/0]).
test() ->
Ns = [0, 0.0, 42, 42.0, gazonk],
T1F4 = [true, false, false, false, false],
T2F3 = [true, true, false, false, false],
F1T4 = [false, true, true, true, true],
F2T3 = [false, false, true, true, true],
%% tests for calls
T1F4 = [eq_exact_call(0, N) || N <- Ns],
F1T4 = [ne_exact_call(0, N) || N <- Ns],
T2F3 = [eq_call(0, N) || N <- Ns],
F2T3 = [ne_call(0, N) || N <- Ns],
%% tests for guards
T1F4 = [eq_exact_guard(0, N) || N <- Ns],
F1T4 = [ne_exact_guard(0, N) || N <- Ns],
T2F3 = [eq_guard(0, N) || N <- Ns],
F2T3 = [ne_guard(0, N) || N <- Ns],
%% some more tests
ok = test_against_zero(),
ok = test_against_other_terms(),
ok = test_sofs_func(),
ok.
test_against_zero() ->
Xs = [0, 1, 0.0],
[true, false, false] = [is_zero_int(X) || X <- Xs],
[true, false, true] = [is_zero_num(X) || X <- Xs],
[false, true, true] = [is_nonzero_int(X) || X <- Xs],
[false, true, false] = [is_nonzero_num(X) || X <- Xs],
ok.
test_against_other_terms() ->
TTT = {true, true, true},
FFF = {false, false, false},
TTT = {is_foo_exact(foo), is_foo_term1(foo), is_foo_term2(foo)},
FFF = {is_foo_exact(bar), is_foo_term1(bar), is_foo_term2(bar)},
FFF = {is_nonfoo_exact(foo), is_nonfoo_term1(foo), is_nonfoo_term2(foo)},
TTT = {is_nonfoo_exact(bar), is_nonfoo_term1(bar), is_nonfoo_term2(bar)},
Tup = {a, {42}, [c]},
TTT = {is_tuple_skel(Tup), is_tuple_exact(Tup), is_tuple_term(Tup)},
BNi = <<42>>,
TTT = {is_bin_exact(BNi), is_bin_term1(BNi), is_bin_term2(BNi)},
BNf = <<42/float>>,
FFF = {is_bin_exact(BNf), is_bin_term1(BNf), is_bin_term2(BNf)},
ok.
test_sofs_func() ->
L = [0, 0.0],
ok = sofs_func(L, L, L).
%%--------------------------------------------------------------------
%% Test for comparison operators used in body calls
eq_exact_call(X, Y) -> X =:= Y.
ne_exact_call(X, Y) -> X =/= Y.
eq_call(X, Y) -> X == Y.
ne_call(X, Y) -> X /= Y.
%%--------------------------------------------------------------------
%% Tests for comparison operators used as guards
eq_exact_guard(X, Y) when X =:= Y -> true;
eq_exact_guard(_, _) -> false.
ne_exact_guard(X, Y) when X =/= Y -> true;
ne_exact_guard(_, _) -> false.
eq_guard(X, Y) when X == Y -> true;
eq_guard(_, _) -> false.
ne_guard(X, Y) when X /= Y -> true;
ne_guard(_, _) -> false.
%%--------------------------------------------------------------------
is_zero_int(N) when N =:= 0 -> true;
is_zero_int(_) -> false.
is_nonzero_int(N) when N =/= 0 -> true;
is_nonzero_int(_) -> false.
is_zero_num(N) when N == 0 -> true;
is_zero_num(_) -> false.
is_nonzero_num(N) when N /= 0 -> true;
is_nonzero_num(_) -> false.
%%--------------------------------------------------------------------
%% There should not really be any difference in the generated code
%% for the following three functions.
is_foo_exact(A) when A =:= foo -> true;
is_foo_exact(_) -> false.
is_foo_term1(A) when A == foo -> true;
is_foo_term1(_) -> false.
is_foo_term2(A) when foo == A -> true;
is_foo_term2(_) -> false.
%%--------------------------------------------------------------------
%% Same for these cases
is_nonfoo_exact(A) when A =/= foo -> true;
is_nonfoo_exact(_) -> false.
is_nonfoo_term1(A) when A /= foo -> true;
is_nonfoo_term1(_) -> false.
is_nonfoo_term2(A) when foo /= A -> true;
is_nonfoo_term2(_) -> false.
%%--------------------------------------------------------------------
is_tuple_skel({A,{B},[C]}) when is_atom(A), is_integer(B), is_atom(C) -> true;
is_tuple_skel(T) when is_tuple(T) -> false.
is_tuple_exact(T) when T =:= {a,{42},[c]} -> true;
is_tuple_exact(T) when is_tuple(T) -> false.
is_tuple_term(T) when T == {a,{42.0},[c]} -> true;
is_tuple_term(T) when is_tuple(T) -> false.
%%--------------------------------------------------------------------
%% But for binaries the treatment has to be different, due to the need
%% for construction of the binary in the guard.
is_bin_exact(B) when B =:= <<42>> -> true;
is_bin_exact(_) -> false.
is_bin_term1(B) when B == <<42>> -> true;
is_bin_term1(_) -> false.
is_bin_term2(B) when <<42>> == B -> true;
is_bin_term2(_) -> false.
%%--------------------------------------------------------------------
%% a test from sofs.erl which failed at some point
sofs_func([X | Ts], X0, L) when X /= X0 ->
sofs_func(Ts, X, L);
sofs_func([X | _Ts], X0, _L) when X == X0 ->
ok;
sofs_func([], _X0, L) ->
L.