Packages
template_compiler
2.3.1
3.6.0
3.5.0
3.4.1
3.4.0
3.3.0
3.2.0
3.1.0
3.0.0
2.14.0
2.13.2
2.13.1
2.13.0
2.12.0
2.11.0
2.10.1
2.10.0
2.9.0
2.8.1
2.8.0
2.7.0
2.6.0
2.5.0
2.4.0
2.3.1
2.3.0
2.2.0
2.1.1
2.1.0
2.0.0
1.6.0
1.5.1
1.5.0
1.4.0
1.3.3
1.3.2
1.3.1
1.3.0
1.2.0
1.1.0
1.0.2
1.0.1
1.0.0
1.0.0-alpha8
1.0.0-alpha7
1.0.0-alpha6
1.0.0-alpha5
1.0.0-alpha4
1.0.0-alpha3
1.0.0-alpha2
Zotonic Template Compiler
Current section
Files
Jump to
Current section
Files
src/template_compiler_operators.erl
%% @author Marc Worrell <marc@worrell.nl>
%% @copyright 2010-2022 Marc Worrell
%% @doc Operators for expression evaluation in templates
%% Copyright 2010-2022 Marc Worrell
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
-module(template_compiler_operators).
-author("Marc Worrell <marc@worrell.nl>").
-export([
'not'/3,
'xor'/4,
concat/4,
subtract/4,
add/4,
sub/4,
divide/4,
multiply/4,
modulo/4,
negate/3,
ge/4,
le/4,
gt/4,
lt/4,
eq/4,
ne/4
]).
'not'(false, _Runtime, _Context) -> true;
'not'(true, _Runtime, _Context) -> false;
'not'(undefined, _Runtime, _Context) -> true;
'not'(A, Runtime, Context) ->
not Runtime:to_bool(A, Context).
'xor'(A, A, _Runtime, _Context) -> false;
'xor'(A, B, Runtime, Context) ->
A1 = Runtime:to_simple_value(A, Context),
B1 = Runtime:to_simple_value(B, Context),
Runtime:to_bool(A1, Context) xor Runtime:to_bool(B1, Context).
concat(A, undefined, _Runtime, _Context) when is_binary(A) -> A;
concat(undefined, B, _Runtime, _Context) when is_binary(B) -> B;
concat({trans, _} = Tr, B, Runtime, Context) ->
concat(Runtime:to_simple_value(Tr, Context), B, Runtime, Context);
concat(A, {trans, _} = Tr, Runtime, Context) ->
concat(A, Runtime:to_simple_value(Tr, Context), Runtime, Context);
concat(A, undefined, Runtime, Context) ->
to_maybe_list(A, Runtime, Context);
concat(undefined, B, Runtime, Context) ->
to_maybe_list(B, Runtime, Context);
concat(A, B, _Runtime, _Context) when is_list(A), is_list(B) ->
A++B;
concat(A, B, _Runtime, _Context) when is_binary(A), is_binary(B) ->
<<A/binary, B/binary>>;
concat(A, B, Runtime, Context) when is_binary(A); is_binary(B) ->
concat(
to_maybe_binary(A, Runtime, Context),
to_maybe_binary(B, Runtime, Context),
Runtime, Context);
concat(A, B, Runtime, Context) ->
concat(
to_maybe_list(A, Runtime, Context),
to_maybe_list(B, Runtime, Context),
Runtime, Context).
subtract(A, undefined, _Runtime, _Context) ->
A;
subtract(undefined, _, _Runtime, _Context) ->
undefined;
subtract(A, B, _Runtime, _Context) when is_list(A), is_list(B) ->
A--B;
subtract(A, B, Runtime, Context) ->
subtract(
to_maybe_list(A, Runtime, Context),
to_maybe_list(B, Runtime, Context),
Runtime, Context).
add(A, B, Runtime, Context) ->
case to_numbers(A, B, Runtime, Context) of
{undefined, _} -> undefined;
{_, undefined} -> undefined;
{A1, B1} -> A1 + B1
end.
sub(A, B, Runtime, Context) ->
case to_numbers(A, B, Runtime, Context) of
{undefined, _} -> undefined;
{_, undefined} -> undefined;
{A1, B1} -> A1 - B1
end.
divide(A, B, Runtime, Context) ->
case to_numbers(A, B, Runtime, Context) of
{undefined, _} -> undefined;
{_, undefined} -> undefined;
{_, 0} -> undefined;
{_, 0.0} -> undefined;
{A1, B1} -> A1 / B1
end.
multiply(A, B, Runtime, Context) ->
case to_numbers(A, B, Runtime, Context) of
{undefined, _} -> undefined;
{_, undefined} -> undefined;
{A1, B1} -> A1 * B1
end.
modulo(A, B, Runtime, Context) ->
case to_numbers(A, B, Runtime, Context) of
{undefined, _} -> undefined;
{_, undefined} -> undefined;
{_, 0} -> undefined;
{_, 0.0} -> undefined;
{A1, B1} -> A1 rem B1
end.
negate(undefined, _Runtime, _Context) ->
undefined;
negate(A, _Runtime, _Context) when is_number(A) ->
0 - A;
negate(A, Runtime, Context) ->
negate(to_maybe_integer(A, Runtime, Context), Runtime, Context).
ge(Input, Value, Runtime, Context) ->
case to_values(Input, Value, Runtime, Context) of
{undefined, _} -> undefined;
{_, undefined} -> undefined;
{A, B} -> A >= B
end.
le(Input, Value, Runtime, Context) ->
case to_values(Input, Value, Runtime, Context) of
{undefined, _} -> undefined;
{_, undefined} -> undefined;
{A, B} -> A =< B
end.
gt(Input, Value, Runtime, Context) ->
case to_values(Input, Value, Runtime, Context) of
{undefined, _} -> undefined;
{_, undefined} -> undefined;
{A, B} -> A > B
end.
lt(Input, Value, Runtime, Context) ->
case to_values(Input, Value, Runtime, Context) of
{undefined, _} -> undefined;
{_, undefined} -> undefined;
{A, B} -> A < B
end.
eq(A, A, _Runtime, _Context) -> true;
eq(Input, Value, Runtime, Context) ->
{A, B} = to_values(Input, Value, Runtime, Context),
A == B.
ne(A, A, _Runtime, _Context) -> false;
ne(Input, Value, Runtime, Context) ->
{A, B} = to_values(Input, Value, Runtime, Context),
A /= B.
%% @doc Convert the two parameters to compatible values
to_values(undefined, B, _Runtime, _Context) ->
{undefined, B};
to_values(A, undefined, _Runtime, _Context) ->
{A, undefined};
to_values({trans, _} = Tr, B, Runtime, Context) ->
to_values(Runtime:to_simple_value(Tr, Context), B, Runtime, Context);
to_values(A, {trans, _} = Tr, Runtime, Context) ->
to_values(A, Runtime:to_simple_value(Tr, Context), Runtime, Context);
to_values(A, B, _Runtime, _Context) when is_number(A), is_number(B) ->
{A,B};
to_values(A, B, Runtime, Context) when is_boolean(A); is_boolean(B) ->
{z_convert:to_bool(Runtime:to_simple_value(A, Context)),
z_convert:to_bool(Runtime:to_simple_value(B, Context))};
to_values(A, B, Runtime, Context) when is_integer(A); is_integer(B) ->
{to_maybe_integer(A, Runtime, Context),
to_maybe_integer(B, Runtime, Context)};
to_values(A, B, Runtime, Context) when is_float(A); is_float(B) ->
{to_maybe_float(A, Runtime, Context),
to_maybe_float(B, Runtime, Context)};
to_values(A, B, _Runtime, _Context) when is_binary(A), is_binary(B) ->
{A,B};
to_values(A, B, _Runtime, _Context) when is_list(A), is_list(B) ->
{A,B};
to_values(A, B, Runtime, Context) when is_binary(A); is_binary(B) ->
{to_maybe_binary(A, Runtime, Context),
to_maybe_binary(B, Runtime, Context)};
to_values(A, B, Runtime, Context) when is_tuple(A), is_tuple(B) ->
{Runtime:to_simple_value(A, Context),
Runtime:to_simple_value(B, Context)};
to_values(A, B, Runtime, Context) when is_binary(A); is_binary(B) ->
{to_maybe_binary(A, Runtime, Context),
to_maybe_binary(B, Runtime, Context)};
to_values(A, B, Runtime, Context) ->
{to_maybe_list(A, Runtime, Context),
to_maybe_list(B, Runtime, Context)}.
%% @doc Convert the two parameters to compatible numerical values
to_numbers(undefined, B, _Runtime, _Context) ->
{undefined, B};
to_numbers(A, undefined, _Runtime, _Context) ->
{A, undefined};
to_numbers(A, B, _Runtime, _Context) when is_number(A), is_number(B) ->
{A,B};
to_numbers(A, B, Runtime, Context) when is_float(A); is_float(B) ->
{to_maybe_float(A, Runtime, Context), to_maybe_float(B, Runtime, Context)};
to_numbers(A, B, Runtime, Context) ->
{to_maybe_integer(A, Runtime, Context), to_maybe_integer(B, Runtime, Context)}.
to_maybe_integer(A, _Runtime, _Context) when is_number(A) ->
A;
to_maybe_integer(A, Runtime, Context) ->
try
A1 = Runtime:to_simple_value(A, Context),
z_convert:to_integer(A1)
catch
_:_ -> undefined
end.
to_maybe_float(A, _Runtime, _Context) when is_float(A) ->
A;
to_maybe_float(A, Runtime, Context) ->
try
A1 = Runtime:to_simple_value(A, Context),
z_convert:to_float(A1)
catch
_:_ -> undefined
end.
to_maybe_binary(A, _Runtime, _Context) when is_binary(A) ->
A;
to_maybe_binary(A, Runtime, Context) ->
try
A1 = Runtime:to_simple_value(A, Context),
z_convert:to_binary(A1)
catch
_:_ -> undefined
end.
to_maybe_list(A, _Runtime, _Context) when is_list(A) ->
A;
to_maybe_list(A, Runtime, Context) ->
try
A1 = Runtime:to_simple_value(A, Context),
z_convert:to_list(A1)
catch
_:_ -> undefined
end.