PageRenderTime 61ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/compiler/test/guard_SUITE.erl

https://github.com/bsmr-erlang/otp
Erlang | 2277 lines | 1761 code | 393 blank | 123 comment | 212 complexity | 03a13aa4038ad066497dd8c8125137f1 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, MPL-2.0-no-copyleft-exception, Apache-2.0
  1. %%
  2. %% %CopyrightBegin%
  3. %%
  4. %% Copyright Ericsson AB 2001-2018. All Rights Reserved.
  5. %%
  6. %% Licensed under the Apache License, Version 2.0 (the "License");
  7. %% you may not use this file except in compliance with the License.
  8. %% You may obtain a copy of the License at
  9. %%
  10. %% http://www.apache.org/licenses/LICENSE-2.0
  11. %%
  12. %% Unless required by applicable law or agreed to in writing, software
  13. %% distributed under the License is distributed on an "AS IS" BASIS,
  14. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. %% See the License for the specific language governing permissions and
  16. %% limitations under the License.
  17. %%
  18. %% %CopyrightEnd%
  19. %%
  20. -module(guard_SUITE).
  21. -include_lib("common_test/include/ct.hrl").
  22. -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
  23. init_per_group/2,end_per_group/2,
  24. misc/1,const_cond/1,basic_not/1,complex_not/1,nested_nots/1,
  25. semicolon/1,complex_semicolon/1,comma/1,
  26. or_guard/1,more_or_guards/1,
  27. complex_or_guards/1,and_guard/1,
  28. xor_guard/1,more_xor_guards/1,
  29. old_guard_tests/1,complex_guard/1,
  30. build_in_guard/1,gbif/1,
  31. t_is_boolean/1,is_function_2/1,
  32. tricky/1,rel_ops/1,rel_op_combinations/1,literal_type_tests/1,
  33. basic_andalso_orelse/1,traverse_dcd/1,
  34. check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1,
  35. bad_constants/1,bad_guards/1,
  36. guard_in_catch/1,beam_bool_SUITE/1]).
  37. suite() -> [{ct_hooks,[ts_install_cth]}].
  38. all() ->
  39. [{group,p}].
  40. groups() ->
  41. [{p,[parallel],
  42. [misc,const_cond,basic_not,complex_not,nested_nots,
  43. semicolon,complex_semicolon,comma,or_guard,
  44. more_or_guards,complex_or_guards,and_guard,xor_guard,
  45. more_xor_guards,build_in_guard,
  46. old_guard_tests,complex_guard,gbif,
  47. t_is_boolean,is_function_2,tricky,
  48. rel_ops,rel_op_combinations,
  49. literal_type_tests,basic_andalso_orelse,traverse_dcd,
  50. check_qlc_hrl,andalso_semi,t_tuple_size,binary_part,
  51. bad_constants,bad_guards,guard_in_catch,beam_bool_SUITE]}].
  52. init_per_suite(Config) ->
  53. test_lib:recompile(?MODULE),
  54. Config.
  55. end_per_suite(_Config) ->
  56. ok.
  57. init_per_group(_GroupName, Config) ->
  58. Config.
  59. end_per_group(_GroupName, Config) ->
  60. Config.
  61. misc(Config) when is_list(Config) ->
  62. 42 = case id(42) of
  63. X when -X -> ok;
  64. X -> X
  65. end,
  66. {a,b,c} = misc_1([{{a,b,c}},{[4]},{[3]},{-2}]),
  67. none = misc_1([{{a,b,c}},{[4]},{[3]},{-3}]),
  68. none = misc_1([{{a,b,c}},{[4]},{[7]},{-2}]),
  69. none = misc_1([{{a,b,c}},{[4]},{[3]},{[1,2,3]}]),
  70. {ok,buf,<<>>} = get_data({o,true,raw}, 0, buf),
  71. {ok,buf,<<>>} = get_data({o,true,raw}, 42, buf),
  72. {ok,buf,<<>>} = get_data({o,false,raw}, 0, buf),
  73. error = get_data({o,false,raw}, 42, buf),
  74. {ok,buf,<<>>} = get_data({o,true,0}, 0, buf),
  75. {ok,buf,<<>>} = get_data({o,true,0}, 42, buf),
  76. {ok,buf,<<>>} = get_data({o,false,0}, 0, buf),
  77. error = get_data({o,false,0}, 42, buf),
  78. relief = misc_2(0),
  79. error = misc_2(1),
  80. error = misc_2(true),
  81. if
  82. is_integer(Config) =/= true ->
  83. ok
  84. end,
  85. true = misc_3(1, 0),
  86. true = misc_3(0, 0),
  87. false = misc_3(0, 2),
  88. %% Abuse of boolean values.
  89. Zero = id(0),
  90. One = id(1),
  91. ok = if (Zero == 0) > false -> ok end,
  92. ok = if (Zero == 0) =:= (One == 1) -> ok end,
  93. ok = if (Zero == 0) =:= (One == 1) -> ok end,
  94. ok = if is_atom(Zero > One) -> ok end,
  95. error = if abs(Zero > One) -> ok; true -> error end,
  96. ok = if is_integer(Zero) >= is_integer(One) -> ok end,
  97. ok.
  98. misc_1([{W},{X},{Y},{Z}]) ->
  99. if
  100. X > Y andalso abs(Z) =:= 2 ->
  101. id(W);
  102. true ->
  103. none
  104. end.
  105. misc_2(0) -> relief;
  106. misc_2(Adapter = 1) when Adapter -> franklin;
  107. misc_2(_) -> error.
  108. misc_3(LenUp, LenDw) ->
  109. if
  110. %% Cover handling of #k_alt{}.
  111. LenUp >= 1 orelse ((LenDw >= 2) xor true) -> true;
  112. true -> false
  113. end.
  114. get_data({o,Active,Raw}, BytesToRead, Buffer)
  115. when Raw =:= raw; Raw =:= 0 ->
  116. if
  117. Active =/= false orelse BytesToRead =:= 0 ->
  118. {ok,Buffer,<<>>};
  119. true ->
  120. error
  121. end.
  122. const_cond(Config) when is_list(Config) ->
  123. ok = const_cond({}, 0),
  124. ok = const_cond({a}, 1),
  125. error = const_cond({a,b}, 3),
  126. error = const_cond({a}, 0),
  127. error = const_cond({a,b}, 1),
  128. ok.
  129. const_cond(T, Sz) ->
  130. case T of
  131. _X when false -> never;
  132. _X when is_tuple(T), eq == eq, tuple_size(T) == Sz -> ok;
  133. _X when is_tuple(T), eq == leq, tuple_size(T) =< Sz -> ok;
  134. _X -> error
  135. end.
  136. basic_not(Config) when is_list(Config) ->
  137. True = id(true),
  138. False = id(false),
  139. Glurf = id(glurf),
  140. A = id(5),
  141. B = id(37.5),
  142. C = id(-1),
  143. D = id(5),
  144. ATuple = {False,True,Glurf},
  145. check(fun() -> if not false -> ok; true -> error end end, ok),
  146. check(fun() -> if not true -> ok; true -> error end end, error),
  147. check(fun() -> if not False -> ok; true -> error end end, ok),
  148. check(fun() -> if not True -> ok; true -> error end end, error),
  149. check(fun() -> if A > B -> gt; A < B -> lt; A == B -> eq end end, lt),
  150. check(fun() -> if A > C -> gt; A < C -> lt; A == C -> eq end end, gt),
  151. check(fun() -> if A > D -> gt; A < D -> lt; A == D -> eq end end, eq),
  152. check(fun() -> if not (7 > 453) -> le; not (7 < 453) -> ge;
  153. not (7 == 453) -> ne; true -> eq end end, le),
  154. check(fun() -> if not (7 > -8) -> le; not (7 < -8) -> ge;
  155. not (7 == -8) -> ne; true -> eq end end, ge),
  156. check(fun() -> if not (7 > 7) -> le; not (7 < 7) -> ge;
  157. not (7 == 7) -> ne; true -> eq end end, le),
  158. check(fun() -> if not (A > B) -> le; not (A < B) -> ge;
  159. not (A == B) -> ne; true -> eq end end, le),
  160. check(fun() -> if not (A > C) -> le; not (A < C) -> ge;
  161. not (A == C) -> ne; true -> eq end end, ge),
  162. check(fun() -> if not (A > D) -> le; not (A < D) -> ge;
  163. not (A == D) -> ne; true -> eq end end, le),
  164. check(fun() -> if not element(1, ATuple) -> ok; true -> error end end, ok),
  165. check(fun() -> if not element(2, ATuple) -> ok; true -> error end end, error),
  166. check(fun() -> if not element(3, ATuple) -> ok; true -> error end end, error),
  167. check(fun() -> if not glurf -> ok; true -> error end end, error),
  168. check(fun() -> if not Glurf -> ok; true -> error end end, error),
  169. check(fun() -> if not (not true) -> broken end end, broken),
  170. check(fun() -> if not (True xor True) -> ok end end, ok),
  171. check(fun() -> if not (True xor False) -> ok;
  172. true -> error end end, error),
  173. ok.
  174. complex_not(Config) when is_list(Config) ->
  175. ATuple = id({false,true,gurka}),
  176. check(fun() -> if not(element(1, ATuple)) -> ok; true -> error end end, ok),
  177. check(fun() -> if not(element(2, ATuple)) -> ok; true -> error end end, error),
  178. check(fun() -> if not(element(3, ATuple) == gurka) -> ok;
  179. true -> error end end, error),
  180. check(fun() -> if not(element(3, ATuple) =/= gurka) -> ok;
  181. true -> error end end, ok),
  182. check(fun() -> if {a,not(element(2, ATuple))} == {a,false} -> ok;
  183. true -> error end end, ok),
  184. check(fun() -> if {a,not(element(1, ATuple))} == {a,false} -> ok;
  185. true -> error end end, error),
  186. check(fun() -> if not(element(1, ATuple) or element(3, ATuple)) -> ok;
  187. true -> error end end, error),
  188. %% orelse
  189. check(fun() -> if not(element(1, ATuple) orelse element(3, ATuple)) -> ok;
  190. true -> error end end, error),
  191. %% complex_not_1/4
  192. ok = complex_not_1(1, 1, 1, a),
  193. error = complex_not_1(1, 1, 1, []),
  194. error = complex_not_1(1, 1, 3, a),
  195. error = complex_not_1(1, 1, 3, []),
  196. error = complex_not_1(1, 2, 1, a),
  197. error = complex_not_1(1, 2, 1, []),
  198. error = complex_not_1(1, 2, 3, a),
  199. error = complex_not_1(1, 2, 3, []),
  200. %% complex_not_2/4
  201. ok = complex_not_2(1, 2, 0, x),
  202. error = complex_not_2(1, 2, 0, []),
  203. error = complex_not_2(1, 2, 3, x),
  204. error = complex_not_2(1, 2, 3, []),
  205. error = complex_not_2(1, 1, 0, x),
  206. error = complex_not_2(1, 1, 0, []),
  207. error = complex_not_2(1, 1, 3, x),
  208. error = complex_not_2(1, 1, 3, []),
  209. ok.
  210. complex_not_1(A, B, C, D) ->
  211. Res = complex_not_1a(A, B, C, D),
  212. Res = complex_not_1b(A, B, C, D).
  213. complex_not_1a(A, B, C, D)
  214. when (not (A < B)) andalso (not (B < C)) andalso (not is_list(D)) ->
  215. ok;
  216. complex_not_1a(_, _, _, _) ->
  217. error.
  218. complex_not_1b(A, B, C, D)
  219. when (not (A < B)) and (not (B < C)) and (not is_list(D)) ->
  220. ok;
  221. complex_not_1b(_, _, _, _) ->
  222. error.
  223. complex_not_2(A, B, C, D) ->
  224. Res = complex_not_2a(A, B, C, D),
  225. Res = complex_not_2b(A, B, C, D).
  226. complex_not_2a(A, B, C, D)
  227. when A < B andalso not (B < C) andalso not is_list(D) ->
  228. ok;
  229. complex_not_2a(_, _, _, _) ->
  230. error.
  231. complex_not_2b(A, B, C, D)
  232. when A < B, not (B < C), not is_list(D) ->
  233. ok;
  234. complex_not_2b(_, _, _, _) ->
  235. error.
  236. nested_nots(Config) when is_list(Config) ->
  237. true = nested_not_1(0, 0),
  238. true = nested_not_1(0, 1),
  239. true = nested_not_1(a, b),
  240. true = nested_not_1(10, 0),
  241. false = nested_not_1(z, a),
  242. false = nested_not_1(3.4, {anything,goes}),
  243. false = nested_not_1(3.4, atom),
  244. true = nested_not_1(3.0, [list]),
  245. true = nested_not_2(false, false, 42),
  246. true = nested_not_2(false, true, 42),
  247. true = nested_not_2(true, false, 42),
  248. true = nested_not_2(true, true, 42),
  249. true = nested_not_2(false, false, atom),
  250. false = nested_not_2(false, true, atom),
  251. false = nested_not_2(true, false, atom),
  252. false = nested_not_2(true, true, atom),
  253. ok.
  254. nested_not_1(X, Y) ->
  255. Res = nested_not_1a(X, Y),
  256. Res = nested_not_1b(X, Y).
  257. nested_not_1a(X, Y) when not (((X>Y) or not(is_atom(X))) and
  258. (is_atom(Y) or (X==3.4))) ->
  259. true;
  260. nested_not_1a(_, _) ->
  261. false.
  262. nested_not_1b(X, Y) when not (((X>Y) orelse not(is_atom(X))) andalso
  263. (is_atom(Y) orelse (X==3.4))) ->
  264. true;
  265. nested_not_1b(_, _) ->
  266. false.
  267. nested_not_2(X, Y, Z) ->
  268. Res = nested_not_2a(X, Y, Z, true),
  269. Res = nested_not_2b(X, Y, Z, true).
  270. nested_not_2a(X, Y, Z, True)
  271. when not(True and not((not(X) and not(Y)) or not(is_atom(Z)))) ->
  272. true;
  273. nested_not_2a(_, _, _, _) ->
  274. false.
  275. nested_not_2b(X, Y, Z, True)
  276. when not(True andalso not((not(X) andalso not(Y)) orelse not(is_atom(Z)))) ->
  277. true;
  278. nested_not_2b(_, _, _, _) ->
  279. false.
  280. semicolon(Config) when is_list(Config) ->
  281. %% True/false combined using ';' (literal atoms).
  282. check(fun() -> if true; false -> ok end end, ok),
  283. check(fun() -> if false; true -> ok end end, ok),
  284. check(fun() -> if true; true -> ok end end, ok),
  285. check(fun() -> if false; false -> ok; true -> error end end, error),
  286. check(fun() ->
  287. {'EXIT',{if_clause,_}} = (catch if false; false -> ok end),
  288. exit
  289. end, exit),
  290. %% True/false combined used ';'.
  291. True = id(true),
  292. False = id(false),
  293. check(fun() -> if True; False -> ok end end, ok),
  294. check(fun() -> if False; True -> ok end end, ok),
  295. check(fun() -> if True; True -> ok end end, ok),
  296. check(fun() -> if False; False -> ok; true -> error end end, error),
  297. check(fun() ->
  298. {'EXIT',{if_clause,_}} = (catch if False; False -> ok end),
  299. exit
  300. end, exit),
  301. %% Combine true/false with a non-boolean value.
  302. Glurf = id(glurf),
  303. check(fun() -> if True; Glurf -> ok end end, ok),
  304. check(fun() -> if Glurf; True -> ok end end, ok),
  305. check(fun() -> if Glurf; Glurf -> ok; true -> error end end, error),
  306. check(fun() -> if False; Glurf -> ok; true -> error end end, error),
  307. check(fun() -> if Glurf; False -> ok; true -> error end end, error),
  308. check(fun() ->
  309. {'EXIT',{if_clause,_}} = (catch if Glurf; Glurf -> ok end),
  310. exit
  311. end, exit),
  312. %% Combine true/false with errors.
  313. ATuple = id({false,true,gurka}),
  314. check(fun() -> if True; element(42, ATuple) -> ok end end, ok),
  315. check(fun() -> if element(42, ATuple); True -> ok end end, ok),
  316. check(fun() -> if element(42, ATuple); element(42, ATuple) -> ok;
  317. true -> error end end, error),
  318. check(fun() -> if False; element(42, ATuple) -> ok;
  319. true -> error end end, error),
  320. check(fun() -> if element(42, ATuple);
  321. False -> ok; true -> error end end, error),
  322. check(fun() ->
  323. {'EXIT',{if_clause,_}} =
  324. (catch if element(42, ATuple);
  325. element(42, ATuple) -> ok end),
  326. exit
  327. end, exit),
  328. ok.
  329. complex_semicolon(Config) when is_list(Config) ->
  330. ok = csemi1(int, {blurf}),
  331. ok = csemi1(string, {blurf}),
  332. ok = csemi1(float, [a]),
  333. error = csemi1(35, 42),
  334. %% 2
  335. ok = csemi2({}, {a,b,c}),
  336. ok = csemi2({1,3.5}, {a,b,c}),
  337. ok = csemi2(dum, {a,b,c}),
  338. ok = csemi2({45,-19.3}, {}),
  339. ok = csemi2({45,-19.3}, {dum}),
  340. ok = csemi2({45,-19.3}, {dum,dum}),
  341. error = csemi2({45}, {dum}),
  342. error = csemi2([], {dum}),
  343. error = csemi2({dum}, []),
  344. error = csemi2([], []),
  345. %% 3
  346. csemi3(fun csemi3a/4),
  347. csemi3(fun csemi3b/4),
  348. csemi3(fun csemi3c/4),
  349. %% 4
  350. csemi4(fun csemi4a/4),
  351. csemi4(fun csemi4b/4),
  352. csemi4(fun csemi4c/4),
  353. csemi4(fun csemi4d/4),
  354. %% 4, 'orelse' instead of 'or'
  355. csemi4_orelse(fun csemi4_orelse_a/4),
  356. csemi4_orelse(fun csemi4_orelse_b/4),
  357. csemi4_orelse(fun csemi4_orelse_c/4),
  358. csemi4_orelse(fun csemi4_orelse_d/4),
  359. %% 5
  360. error = csemi5(0, 0),
  361. ok = csemi5(5, 0),
  362. ok = csemi5(4, -4),
  363. ok = csemi5(10, -4),
  364. %% 6
  365. error = csemi6({a}, 0),
  366. ok = csemi6({a,b}, 0),
  367. ok = csemi6({}, 3),
  368. ok = csemi6({a,b,c}, 3),
  369. %% 7
  370. error = csemi7(#{a=>1}, 1, 0),
  371. error = csemi7(<<>>, 1, 0),
  372. ok = csemi7(#{a=>1}, 3, 0),
  373. ok = csemi7(#{a=>1}, 0, 3),
  374. ok = csemi7(#{a=>1}, 3, 3),
  375. ok = csemi7(#{a=>1, b=>3}, 0, 0),
  376. %% 8: Make sure that funs cannot be copied into guards.
  377. ok = csemi8(true),
  378. error = csemi8(false),
  379. error = csemi8(42),
  380. ok.
  381. csemi1(Type, Val) when is_list(Val), Type == float;
  382. Type == int; Type == string -> ok;
  383. csemi1(_, _) -> error.
  384. csemi2(A, B) when tuple_size(A) > 1; tuple_size(B) > 2 -> ok;
  385. csemi2(_, _) -> error.
  386. csemi3(Csemi3) ->
  387. ok = Csemi3({}, {a,b,c}, [0], [0]),
  388. ok = Csemi3({1,3.5}, {a,b,c}, -1, -1),
  389. ok = Csemi3(dum, {a,b,c}, 0.0, 0.0),
  390. ok = Csemi3(dum, {c}, b, a),
  391. ok = Csemi3(dum, <<1,2,3>>, 0.0, 0.0),
  392. ok = Csemi3(<<3.5/float>>, {a,b,c}, -1, -1),
  393. ok = Csemi3({45,-19.3}, {}, [], []),
  394. ok = Csemi3({45,-19.3}, {dum}, 42, 42),
  395. ok = Csemi3({45,-19.3}, {dum,dum}, 33, 33),
  396. ok = Csemi3({45}, {dum}, 1.0, 0),
  397. ok = Csemi3([a], {dum}, 1.0, 0),
  398. ok = Csemi3({dum}, [], 1.0, 0),
  399. ok = Csemi3([], [], 1.0, 0),
  400. ok = Csemi3(blurf, {dum}, 1.0, 0),
  401. ok = Csemi3({a}, blurf, 1.0, 0),
  402. ok = Csemi3([a], [dum], 1.0, 0),
  403. ok = Csemi3({dum}, [], 1.0, 0),
  404. ok = Csemi3([], [], 1.0, 0),
  405. error = Csemi3({45}, {dum}, 0, 0),
  406. error = Csemi3([a], {dum}, 0, 0),
  407. error = Csemi3({dum}, [], 0, 0),
  408. error = Csemi3([], [], 0, 0),
  409. ok.
  410. csemi3a(A, B, X, Y) when X > Y; size(A) > 1; size(B) > 2 -> ok;
  411. csemi3a(_, _, _, _) -> error.
  412. csemi3b(A, B, X, Y) when size(A) > 1; X > Y; size(B) > 2 -> ok;
  413. csemi3b(_, _, _, _) -> error.
  414. csemi3c(A, B, X, Y) when size(A) > 1; size(B) > 2; X > Y -> ok;
  415. csemi3c(_, _, _, _) -> error.
  416. csemi4(Test) ->
  417. ok = Test({a,b}, 2, {c,d}, 2),
  418. ok = Test({1,2,3}, 0, [], 0),
  419. ok = Test({}, 2, blurf, 0),
  420. ok = Test({}, 2, {1}, 2),
  421. error = Test([], 4, {}, 0),
  422. error = Test({}, 0, [a,b], 4),
  423. error = Test({}, 0, [a,b], 0),
  424. error = Test([], 0, {}, 0),
  425. error = Test({}, 0, {}, 0),
  426. ok.
  427. csemi4a(A, X, B, Y) when (tuple_size(A) > 1) or (X > 1);
  428. (tuple_size(B) > 1) or (Y > 1) -> ok;
  429. csemi4a(_, _, _, _) -> error.
  430. csemi4b(A, X, B, Y) when (X > 1) or (tuple_size(A) > 1);
  431. (tuple_size(B) > 1) or (Y > 1) -> ok;
  432. csemi4b(_, _, _, _) -> error.
  433. csemi4c(A, X, B, Y) when (tuple_size(A) > 1) or (X > 1);
  434. (Y > 1) or (tuple_size(B) > 1) -> ok;
  435. csemi4c(_, _, _, _) -> error.
  436. csemi4d(A, X, B, Y) when (X > 1) or (tuple_size(A) > 1);
  437. (Y > 1) or (tuple_size(B) > 1) -> ok;
  438. csemi4d(_, _, _, _) -> error.
  439. csemi4_orelse(Test) ->
  440. ok = Test({a,b}, 2, {c,d}, 2),
  441. ok = Test({1,2,3}, 0, [], 0),
  442. ok = Test({}, 2, blurf, 0),
  443. ok = Test({}, 2, {1}, 2),
  444. error = Test([], 1, {}, 0),
  445. ok.
  446. csemi4_orelse_a(A, X, B, Y) when (tuple_size(A) > 1) orelse (X > 1);
  447. (tuple_size(B) > 1) orelse (Y > 1) -> ok;
  448. csemi4_orelse_a(_, _, _, _) -> error.
  449. csemi4_orelse_b(A, X, B, Y) when (X > 1) orelse (tuple_size(A) > 1);
  450. (tuple_size(B) > 1) orelse (Y > 1) -> ok;
  451. csemi4_orelse_b(_, _, _, _) -> error.
  452. csemi4_orelse_c(A, X, B, Y) when (tuple_size(A) > 1) orelse (X > 1);
  453. (Y > 1) orelse (tuple_size(B) > 1) -> ok;
  454. csemi4_orelse_c(_, _, _, _) -> error.
  455. csemi4_orelse_d(A, X, B, Y) when (X > 1) or (tuple_size(A) > 1);
  456. (Y > 1) or (tuple_size(B) > 1) -> ok;
  457. csemi4_orelse_d(_, _, _, _) -> error.
  458. csemi5(A, B) when hd([A+B]) > 1; abs(B) > 2 -> ok;
  459. csemi5(_, _) -> error.
  460. csemi6(A, B) when hd([tuple_size(A)]) > 1; abs(B) > 2 -> ok;
  461. csemi6(_, _) -> error.
  462. csemi7(A, B, C) when A#{a:=B} > #{a=>1}; abs(C) > 2 -> ok;
  463. csemi7(_, _, _) -> error.
  464. csemi8(Together) ->
  465. case fun csemi8/1 of
  466. Typically when Together; Typically, Together -> ok;
  467. _ -> error
  468. end.
  469. comma(Config) when is_list(Config) ->
  470. %% ',' combinations of literal true/false.
  471. check(fun() -> if true, false -> ok; true -> error end end, error),
  472. check(fun() -> if false, true -> ok; true -> error end end, error),
  473. check(fun() -> if true, true -> ok end end, ok),
  474. check(fun() -> if false, false -> ok; true -> error end end, error),
  475. check(fun() ->
  476. {'EXIT',{if_clause,_}} =
  477. (catch if true, false -> ok;
  478. false, true -> ok;
  479. false, false -> ok
  480. end),
  481. exit
  482. end, exit),
  483. %% ',' combinations of true/false in variables.
  484. True = id(true),
  485. False = id(false),
  486. check(fun() -> if True, False -> ok; true -> error end end, error),
  487. check(fun() -> if False, True -> ok; true -> error end end, error),
  488. check(fun() -> if True, True -> ok end end, ok),
  489. check(fun() -> if False, False -> ok; true -> error end end, error),
  490. check(fun() ->
  491. {'EXIT',{if_clause,_}} =
  492. (catch if True, False -> ok;
  493. False, True -> ok;
  494. False, False -> ok
  495. end),
  496. exit
  497. end, exit),
  498. %% ',' combinations of true/false, and non-boolean in variables.
  499. Glurf = id(glurf),
  500. check(fun() -> if True, Glurf -> ok; true -> error end end, error),
  501. check(fun() -> if Glurf, True -> ok; true -> error end end, error),
  502. check(fun() -> if True, True -> ok end end, ok),
  503. check(fun() -> if Glurf, Glurf -> ok; true -> error end end, error),
  504. check(fun() ->
  505. {'EXIT',{if_clause,_}} =
  506. (catch if True, Glurf -> ok;
  507. Glurf, True -> ok;
  508. Glurf, Glurf -> ok
  509. end),
  510. exit
  511. end, exit),
  512. %% ',' combinations of true/false with errors.
  513. ATuple = id({a,b,c}),
  514. check(fun() -> if True, element(42, ATuple) -> ok;
  515. true -> error end end, error),
  516. check(fun() -> if element(42, ATuple), True -> ok;
  517. true -> error end end, error),
  518. check(fun() -> if True, True -> ok end end, ok),
  519. check(fun() -> if element(42, ATuple), element(42, ATuple) -> ok;
  520. true -> error end end, error),
  521. check(fun() ->
  522. {'EXIT',{if_clause,_}} =
  523. (catch if True, element(42, ATuple) -> ok;
  524. element(42, ATuple), True -> ok;
  525. element(42, ATuple), element(42, ATuple) -> ok
  526. end),
  527. exit
  528. end, exit),
  529. ok.
  530. or_guard(Config) when is_list(Config) ->
  531. True = id(true),
  532. False = id(false),
  533. Glurf = id(glurf),
  534. %% 'or' combinations of literal true/false.
  535. check(fun() -> if true or false -> ok end end, ok),
  536. check(fun() -> if false or true -> ok end end, ok),
  537. check(fun() -> if true or true -> ok end end, ok),
  538. check(fun() -> if false or false -> ok; true -> error end end, error),
  539. check(fun() -> if glurf or true -> ok; true -> error end end, error),
  540. check(fun() -> if true or glurf -> ok; true -> error end end, error),
  541. check(fun() -> if glurf or glurf -> ok; true -> error end end, error),
  542. check(fun() ->
  543. {'EXIT',{if_clause,_}} = (catch if false or false -> ok end),
  544. exit
  545. end, exit),
  546. %% 'or' combinations using variables containing true/false.
  547. check(fun() -> if True or False -> ok end end, ok),
  548. check(fun() -> if False or True -> ok end end, ok),
  549. check(fun() -> if True or True -> ok end end, ok),
  550. check(fun() -> if False or False -> ok; true -> error end end, error),
  551. check(fun() -> if True or Glurf -> ok; true -> error end end, error),
  552. check(fun() -> if Glurf or True -> ok; true -> error end end, error),
  553. check(fun() -> if Glurf or Glurf -> ok; true -> error end end, error),
  554. check(fun() ->
  555. {'EXIT',{if_clause,_}} = (catch if False or False -> ok end),
  556. exit
  557. end, exit),
  558. ok.
  559. more_or_guards(Config) when is_list(Config) ->
  560. True = id(true),
  561. False = id(false),
  562. ATuple = id({false,true,gurka}),
  563. check(fun() ->
  564. if element(42, ATuple) or False -> ok;
  565. true -> error end
  566. end, error),
  567. check(fun() ->
  568. if False or element(42, ATuple) -> ok;
  569. true -> error end
  570. end, error),
  571. check(fun() ->
  572. if element(18, ATuple) or element(42, ATuple) -> ok;
  573. true -> error end
  574. end, error),
  575. check(fun() ->
  576. if True or element(42, ATuple) -> ok;
  577. true -> error end
  578. end, error),
  579. check(fun() ->
  580. if element(42, ATuple) or True -> ok;
  581. true -> error end
  582. end, error),
  583. check(fun() ->
  584. if element(1, ATuple) or element(42, ATuple) or True -> ok;
  585. true -> error end
  586. end, error),
  587. check(fun() ->
  588. if element(1, ATuple) or True or element(42, ATuple) -> ok;
  589. true -> error end
  590. end, error),
  591. check(fun() ->
  592. if
  593. (<<False:8>> == <<0>>) or element(2, ATuple) -> ok;
  594. true -> error end
  595. end, error),
  596. check(fun() ->
  597. if
  598. element(2, ATuple) or (<<True:8>> == <<1>>) -> ok;
  599. true -> error end
  600. end, error),
  601. check(fun() ->
  602. if element(2, ATuple) or element(42, ATuple) -> ok;
  603. true -> error end
  604. end, error),
  605. check(fun() ->
  606. if
  607. element(1, ATuple) or
  608. element(2, ATuple) or
  609. element(19, ATuple) -> ok;
  610. true -> error end
  611. end, error),
  612. ok.
  613. complex_or_guards(Config) when is_list(Config) ->
  614. %% complex_or_1/2
  615. ok = complex_or_1({a,b,c,d}, {1,2,3}),
  616. ok = complex_or_1({a,b,c,d}, {1}),
  617. ok = complex_or_1({a}, {1,2,3}),
  618. error = complex_or_1({a}, {1}),
  619. error = complex_or_1(1, 2),
  620. error = complex_or_1([], {a,b,c,d}),
  621. error = complex_or_1({a,b,c,d}, []),
  622. %% complex_or_2/1
  623. ok = complex_or_2({true,{}}),
  624. ok = complex_or_2({false,{a}}),
  625. ok = complex_or_2({false,{a,b,c}}),
  626. ok = complex_or_2({true,{a,b,c,d}}),
  627. error = complex_or_2({blurf,{a,b,c}}),
  628. error = complex_or_2({true}),
  629. error = complex_or_2({true,no_tuple}),
  630. error = complex_or_2({true,[]}),
  631. %% complex_or_3/2
  632. ok = complex_or_3({true}, {}),
  633. ok = complex_or_3({false}, {a}),
  634. ok = complex_or_3({false}, {a,b,c}),
  635. ok = complex_or_3({true}, {a,b,c,d}),
  636. ok = complex_or_3({false}, <<1,2,3>>),
  637. ok = complex_or_3({true}, <<1,2,3,4>>),
  638. error = complex_or_3(blurf, {a,b,c}),
  639. error = complex_or_3({false}, <<1,2,3,4>>),
  640. error = complex_or_3([], <<1,2>>),
  641. error = complex_or_3({true}, 45),
  642. error = complex_or_3(<<>>, <<>>),
  643. %% complex_or_4/2
  644. ok = complex_or_4(<<1,2,3>>, {true}),
  645. ok = complex_or_4(<<1,2,3>>, {false}),
  646. ok = complex_or_4(<<1,2,3>>, {true}),
  647. ok = complex_or_4({1,2,3}, {true}),
  648. error = complex_or_4({1,2,3,4}, {false}),
  649. error = complex_or_4(<<1,2,3,4>>, []),
  650. error = complex_or_4([], {true}),
  651. %% complex_or_5/2
  652. ok = complex_or_5(<<1>>, {false}),
  653. ok = complex_or_5(<<1,2,3>>, {true}),
  654. ok = complex_or_5(<<1,2,3,4>>, {false}),
  655. ok = complex_or_5({1,2,3}, {false}),
  656. ok = complex_or_5({1,2,3,4}, {false}),
  657. error = complex_or_5(blurf, {false}),
  658. error = complex_or_5(<<1>>, klarf),
  659. error = complex_or_5(blurf, klarf),
  660. %% complex_or_6/2
  661. ok = complex_or_6({true,true}, {1,2,3,4}),
  662. ok = complex_or_6({true,true}, <<1,2,3,4>>),
  663. ok = complex_or_6({false,false}, <<1,2,3,4>>),
  664. ok = complex_or_6({false,true}, <<1>>),
  665. ok = complex_or_6({true,false}, {1}),
  666. ok = complex_or_6({true,true}, {1}),
  667. error = complex_or_6({false,false}, {1}),
  668. error = complex_or_6({true}, {1,2,3,4}),
  669. error = complex_or_6({}, {1,2,3,4}),
  670. error = complex_or_6([], {1,2,3,4}),
  671. error = complex_or_6([], {1,2,3,4}),
  672. error = complex_or_6({true,false}, klurf),
  673. ok.
  674. complex_or_1(A, B) ->
  675. if
  676. ((3 < tuple_size(A)) and (tuple_size(A) < 9)) or
  677. ((2 < tuple_size(B)) and (tuple_size(B) < 7)) -> ok;
  678. true -> error
  679. end.
  680. complex_or_2(Tuple) ->
  681. if
  682. element(1, Tuple) or not (tuple_size(element(2, Tuple)) > 3) -> ok;
  683. true -> error
  684. end.
  685. complex_or_3(A, B) ->
  686. if
  687. not (size(B) > 3) or element(1, A) -> ok;
  688. true -> error
  689. end.
  690. complex_or_4(A, B) ->
  691. if
  692. not (is_tuple(A) and (size(A) > 3)) or element(1, B) -> ok;
  693. true -> error
  694. end.
  695. complex_or_5(A, B) ->
  696. if
  697. not (is_tuple(A) or (size(A) > 3)) or not element(1, B) -> ok;
  698. true -> error
  699. end.
  700. complex_or_6(A, B) ->
  701. if
  702. not (not element(1, A) and not element(2, A)) or
  703. not (not (size(B) > 3)) -> ok;
  704. true -> error
  705. end.
  706. and_guard(Config) when is_list(Config) ->
  707. %% 'and' combinations of literal true/false.
  708. check(fun() -> if true and false -> ok; true -> error end end, error),
  709. check(fun() -> if false and true -> ok; true -> error end end, error),
  710. check(fun() -> if true and true -> ok end end, ok),
  711. check(fun() -> if false and false -> ok; true -> error end end, error),
  712. check(fun() -> if glurf and true -> ok; true -> error end end, error),
  713. check(fun() -> if true and glurf -> ok; true -> error end end, error),
  714. check(fun() -> if glurf and glurf -> ok; true -> error end end, error),
  715. check(fun() ->
  716. {'EXIT',{if_clause,_}} =
  717. (catch if true and false -> ok;
  718. false and true -> ok;
  719. false and false -> ok
  720. end),
  721. exit
  722. end, exit),
  723. %% 'and' combinations of true/false in variables.
  724. True = id(true),
  725. False = id(false),
  726. check(fun() -> if True and False -> ok; true -> error end end, error),
  727. check(fun() -> if False and True -> ok; true -> error end end, error),
  728. check(fun() -> if True and True -> ok end end, ok),
  729. check(fun() -> if False and False -> ok; true -> error end end, error),
  730. check(fun() ->
  731. {'EXIT',{if_clause,_}} =
  732. (catch if True and False -> ok;
  733. False and True -> ok;
  734. False and False -> ok
  735. end),
  736. exit
  737. end, exit),
  738. %% 'and' combinations of true/false and a non-boolean in variables.
  739. Glurf = id(glurf),
  740. check(fun() -> if True and Glurf -> ok; true -> error end end, error),
  741. check(fun() -> if Glurf and True -> ok; true -> error end end, error),
  742. check(fun() -> if True and True -> ok end end, ok),
  743. check(fun() -> if Glurf and Glurf -> ok; true -> error end end, error),
  744. check(fun() ->
  745. {'EXIT',{if_clause,_}} =
  746. (catch if True and Glurf -> ok;
  747. Glurf and True -> ok;
  748. Glurf and Glurf -> ok
  749. end),
  750. exit
  751. end, exit),
  752. %% 'and' combinations of true/false with errors.
  753. ATuple = id({a,b,c}),
  754. check(fun() -> if True and element(42, ATuple) -> ok;
  755. true -> error end end, error),
  756. check(fun() -> if element(42, ATuple) and True -> ok;
  757. true -> error end end, error),
  758. check(fun() -> if True and True -> ok end end, ok),
  759. check(fun() -> if element(42, ATuple) and element(42, ATuple) -> ok;
  760. true -> error end end, error),
  761. check(fun() ->
  762. {'EXIT',{if_clause,_}} =
  763. (catch if True and element(42, ATuple) -> ok;
  764. element(42, ATuple) and True -> ok;
  765. element(42, ATuple) and element(42, ATuple) -> ok
  766. end),
  767. exit
  768. end, exit),
  769. ok = relprod({'Set',a,b}, {'Set',a,b}),
  770. ok = and_same_var(42),
  771. {'EXIT',{if_clause,_}} = (catch and_same_var(x)),
  772. ok.
  773. and_same_var(V) ->
  774. B = is_integer(V),
  775. if
  776. B or B -> ok
  777. end.
  778. relprod(R1, R2) when (erlang:size(R1) =:= 3) and (erlang:element(1,R1) =:= 'Set'), (erlang:size(R2) =:= 3) and (erlang:element(1,R2) =:= 'Set') ->
  779. ok.
  780. xor_guard(Config) when is_list(Config) ->
  781. %% 'xor' combinations of literal true/false.
  782. check(fun() -> if true xor false -> ok end end, ok),
  783. check(fun() -> if false xor true -> ok end end, ok),
  784. check(fun() -> if true xor true -> ok; true -> error end end, error),
  785. check(fun() -> if false xor false -> ok; true -> error end end, error),
  786. check(fun() ->
  787. {'EXIT',{if_clause,_}} = (catch if false xor false -> ok end),
  788. exit
  789. end, exit),
  790. check(fun() ->
  791. {'EXIT',{if_clause,_}} = (catch if true xor true -> ok end),
  792. exit
  793. end, exit),
  794. %% 'xor' combinations using variables containing true/false.
  795. True = id(true),
  796. False = id(false),
  797. check(fun() -> if True xor False -> ok end end, ok),
  798. check(fun() -> if False xor True -> ok end end, ok),
  799. check(fun() -> if True xor True -> ok; true -> error end end, error),
  800. check(fun() -> if False xor False -> ok; true -> error end end, error),
  801. check(fun() ->
  802. {'EXIT',{if_clause,_}} = (catch if False xor False -> ok end),
  803. exit
  804. end, exit),
  805. check(fun() ->
  806. {'EXIT',{if_clause,_}} = (catch if True xor True -> ok end),
  807. exit
  808. end, exit),
  809. ok.
  810. more_xor_guards(Config) when is_list(Config) ->
  811. True = id(true),
  812. False = id(false),
  813. ATuple = id({false,true,gurka}),
  814. check(fun() ->
  815. if element(42, ATuple) xor False -> ok;
  816. true -> error end
  817. end, error),
  818. check(fun() ->
  819. if False xor element(42, ATuple) xor False -> ok;
  820. true -> error end
  821. end, error),
  822. check(fun() ->
  823. if element(18, ATuple) xor element(42, ATuple) -> ok;
  824. true -> error end
  825. end, error),
  826. check(fun() ->
  827. if True xor element(42, ATuple) -> ok;
  828. true -> error end
  829. end, error),
  830. check(fun() ->
  831. if element(42, ATuple) xor True -> ok;
  832. true -> error end
  833. end, error),
  834. ok.
  835. build_in_guard(Config) when is_list(Config) ->
  836. SubBin = <<5.0/float>>,
  837. B = <<1,SubBin/binary,3.5/float>>,
  838. if
  839. B =:= <<1,SubBin/binary,3.5/float>> -> ok
  840. end.
  841. old_guard_tests(Config) when list(Config) ->
  842. %% Check that all the old guard tests are still recognized.
  843. list = og(Config),
  844. atom = og(an_atom),
  845. binary = og(<<1,2>>),
  846. float = og(3.14),
  847. integer = og(43),
  848. a_function = og(fun() -> ok end),
  849. pid = og(self()),
  850. reference = og(make_ref()),
  851. tuple = og({}),
  852. number = on(45.333),
  853. number = on(-19),
  854. ok.
  855. og(V) when atom(V) -> atom;
  856. og(V) when binary(V) -> binary;
  857. og(V) when float(V) -> float;
  858. og(V) when integer(V) -> integer;
  859. og(V) when function(V) -> a_function;
  860. og(V) when list(V) -> list;
  861. og(V) when pid(V) -> pid;
  862. og(V) when port(V) -> port;
  863. og(V) when reference(V) -> reference;
  864. og(V) when tuple(V) -> tuple;
  865. og(_) -> what.
  866. on(V) when number(V) -> number;
  867. on(_) -> not_number.
  868. complex_guard(_Config) ->
  869. _ = [true = do_complex_guard(X, Y, Z) ||
  870. X <- [4,5], Y <- [4,5], Z <- [4,5]],
  871. _ = [true = do_complex_guard(X, Y, Z) ||
  872. X <- [1,2,3], Y <- [1,2,3], Z <- [1,2,3]],
  873. _ = [catch do_complex_guard(X, Y, Z) ||
  874. X <- [1,2,3,4,5], Y <- [0,6], Z <- [1,2,3,4,5]],
  875. ok.
  876. do_complex_guard(X1, Y1, Z1) ->
  877. if
  878. ((X1 =:= 4) or (X1 =:= 5)) and
  879. ((Y1 =:= 4) or (Y1 =:= 5)) and
  880. ((Z1 =:= 4) or (Z1 =:= 5)) or
  881. ((X1 =:= 1) or (X1 =:= 2) or (X1 =:= 3)) and
  882. ((Y1 =:= 1) or (Y1 =:= 2) or (Y1 =:= 3)) and
  883. ((Z1 =:= 1) or (Z1 =:= 2) or (Z1 =:= 3)) ->
  884. true
  885. end.
  886. gbif(Config) when is_list(Config) ->
  887. error = gbif_1(1, {false,true}),
  888. ok = gbif_1(2, {false,true}),
  889. ok.
  890. gbif_1(P, T) when element(P, T) -> ok;
  891. gbif_1(_, _) -> error.
  892. t_is_boolean(Config) when is_list(Config) ->
  893. true = is_boolean(true),
  894. true = is_boolean(false),
  895. true = is_boolean(id(true)),
  896. true = is_boolean(id(false)),
  897. false = is_boolean(glurf),
  898. false = is_boolean(id(glurf)),
  899. false = is_boolean([]),
  900. false = is_boolean(id([])),
  901. false = is_boolean(42),
  902. false = is_boolean(id(-42)),
  903. false = is_boolean(math:pi()),
  904. false = is_boolean(384793478934378924978439789873478934897),
  905. false = is_boolean(id(self())),
  906. false = is_boolean(id({x,y,z})),
  907. false = is_boolean(id([a,b,c])),
  908. false = is_boolean(id(make_ref())),
  909. false = is_boolean(id(<<1,2,3>>)),
  910. false = is_boolean({id(x),y,z}),
  911. false = is_boolean([id(a),b,c]),
  912. ok = bool(true),
  913. ok = bool(false),
  914. ok = bool(id(true)),
  915. ok = bool(id(false)),
  916. error = bool(glurf),
  917. error = bool(id(glurf)),
  918. error = bool([]),
  919. error = bool(id([])),
  920. error = bool(42),
  921. error = bool(id(-42)),
  922. error = bool(math:pi()),
  923. error = bool(384793478934378924978439789873478934897),
  924. error = bool(id(self())),
  925. error = bool(id({x,y,z})),
  926. error = bool(id([a,b,c])),
  927. error = bool(id(make_ref())),
  928. error = bool(id(<<1,2,3>>)),
  929. true = my_is_bool(true),
  930. true = my_is_bool(false),
  931. false = my_is_bool([]),
  932. false = my_is_bool([1,2,3,4]),
  933. false = my_is_bool({a,b,c}),
  934. ok.
  935. bool(X) when is_boolean(X) -> ok;
  936. bool(_) -> error.
  937. my_is_bool(V) ->
  938. Res = my_is_bool_a(V),
  939. Res = my_is_bool_b(V).
  940. my_is_bool_a(V) ->
  941. case V of
  942. true -> true;
  943. false -> true;
  944. _ -> false
  945. end.
  946. my_is_bool_b(V) ->
  947. case V of
  948. false -> true;
  949. true -> true;
  950. _ -> false
  951. end.
  952. is_function_2(Config) when is_list(Config) ->
  953. true = is_function(id(fun ?MODULE:all/1), 1),
  954. true = is_function(id(fun() -> ok end), 0),
  955. false = is_function(id(fun ?MODULE:all/1), 0),
  956. false = is_function(id(fun() -> ok end), 1),
  957. {'EXIT',{badarg,_}} =
  958. (catch is_function(id(fun() -> ok end), -1) orelse error),
  959. {'EXIT',{badarg,_}} =
  960. (catch is_function(id(fun() -> ok end), '') orelse error),
  961. F = fun(_) -> ok end,
  962. if
  963. is_function(F, 1) -> ok
  964. end.
  965. tricky(Config) when is_list(Config) ->
  966. not_ok = tricky_1(1, 2),
  967. not_ok = tricky_1(1, blurf),
  968. not_ok = tricky_1(foo, 2),
  969. not_ok = tricky_1(a, b),
  970. error = tricky_2(0.5),
  971. error = tricky_2(a),
  972. error = tricky_2({a,b,c}),
  973. false = rb(100000, [1], 42),
  974. true = rb(100000, [], 42),
  975. true = rb(555, [a,b,c], 19),
  976. error = tricky_3(42),
  977. error = tricky_3(42.0),
  978. error = tricky_3(<<>>),
  979. error = tricky_3(#{}),
  980. error = tricky_3({a,b}),
  981. ok.
  982. tricky_1(X, Y) when abs((X == 1) or (Y == 2)) -> ok;
  983. tricky_1(_, _) -> not_ok.
  984. tricky_2(X) when float(X) or float(X) -> ok;
  985. tricky_2(_) -> error.
  986. tricky_3(X)
  987. when abs(X) or bit_size(X) or byte_size(X) or ceil(X) or
  988. float(X) or floor(X) or length(X) or
  989. map_size(X) or node() or node(X) or round(X) or
  990. self() or size(X) or tl(X) or trunc(X) or tuple_size(X) ->
  991. ok;
  992. tricky_3(_) ->
  993. error.
  994. %% From dets_v9:read_buckets/11, simplified.
  995. rb(Size, ToRead, SoFar) when SoFar + Size < 81920; ToRead == [] -> true;
  996. rb(_, _, _) -> false.
  997. -define(T(Op,A,B),
  998. ok = if A Op B -> ok; true -> error end,
  999. ok = if not (A Op B) -> error; true -> ok end,
  1000. (fun(X, Y, True, False) ->
  1001. ok = if X Op Y -> ok; true -> error end,
  1002. ok = if False; X Op Y; False -> ok; true -> error end,
  1003. ok = if X Op Y, True -> ok; true -> error end,
  1004. ok = if not (X Op Y) -> error; true -> ok end,
  1005. ok = if False; not (X Op Y); False -> error; true -> ok end
  1006. end)(id(A), id(B), id(true), id(false))).
  1007. -define(F(Op,A,B),
  1008. ok = if A Op B -> error; true -> ok end,
  1009. ok = if not (A Op B) -> ok; true -> error end,
  1010. (fun(X, Y, True, False) ->
  1011. ok = if X Op Y -> error; true -> ok end,
  1012. ok = if False; X Op Y; False -> error; true -> ok end,
  1013. ok = if not (X Op Y); False -> ok; true -> error end,
  1014. ok = if not (X Op Y), True -> ok; true -> error end
  1015. end)(id(A), id(B), id(true), id(false))).
  1016. rel_ops(Config) when is_list(Config) ->
  1017. ?T(=/=, 1, 1.0),
  1018. ?F(=/=, 2, 2),
  1019. ?F(=/=, {a}, {a}),
  1020. ?F(/=, a, a),
  1021. ?F(/=, 0, 0.0),
  1022. ?T(/=, 0, 1),
  1023. ?F(/=, {a}, {a}),
  1024. ?T(==, 1, 1.0),
  1025. ?F(==, a, {}),
  1026. ?F(=:=, 1, 1.0),
  1027. ?T(=:=, 42.0, 42.0),
  1028. ?F(>, a, b),
  1029. ?T(>, 42, 1.0),
  1030. ?F(>, 42, 42.0),
  1031. ?T(<, a, b),
  1032. ?F(<, 42, 1.0),
  1033. ?F(<, 42, 42.0),
  1034. ?T(=<, 1.5, 5),
  1035. ?F(=<, -9, -100.344),
  1036. ?T(=<, 42, 42.0),
  1037. ?T(>=, 42, 42.0),
  1038. ?F(>=, a, b),
  1039. ?T(>=, 1.0, 0),
  1040. %% Coverage of beam_block:is_exact_eq_ok/1 and collect/1.
  1041. true = any_atom /= id(42),
  1042. true = [] /= id(42),
  1043. %% Coverage of beam_utils:bif_to_test/3
  1044. Empty = id([]),
  1045. ?T(==, [], Empty),
  1046. %% Cover beam_ssa_dead:turn_op('/=').
  1047. ok = (fun(A, B) when is_atom(A) ->
  1048. X = id(A /= B),
  1049. if
  1050. X -> ok;
  1051. true -> error
  1052. end
  1053. end)(a, b),
  1054. ok = (fun(A, B) when is_atom(A) ->
  1055. X = id(B /= A),
  1056. if
  1057. X -> ok;
  1058. true -> error
  1059. end
  1060. end)(a, b),
  1061. %% Cover beam_ssa_dead.
  1062. Arrow = fun([T1,T2]) when T1 == $>, T2 == $>;
  1063. T1 == $<, T2 == $| -> true;
  1064. (_) -> false
  1065. end,
  1066. true = Arrow(">>"),
  1067. true = Arrow("<|"),
  1068. false = Arrow("><"),
  1069. false = Arrow(""),
  1070. ok.
  1071. -undef(TestOp).
  1072. rel_op_combinations(Config) when is_list(Config) ->
  1073. Digits0 = lists:seq(16#0030, 16#0039) ++
  1074. lists:seq(16#0660, 16#0669) ++
  1075. lists:seq(16#06F0, 16#06F9),
  1076. Digits = gb_sets:from_list(Digits0),
  1077. rel_op_combinations_1(16#0700, Digits),
  1078. BrokenRange0 = lists:seq(3, 5) ++
  1079. lists:seq(10, 12) ++ lists:seq(14, 20),
  1080. BrokenRange = gb_sets:from_list(BrokenRange0),
  1081. rel_op_combinations_2(30, BrokenRange),
  1082. Red0 = [{I,2*I} || I <- lists:seq(0, 50)] ++
  1083. [{I,5*I} || I <- lists:seq(51, 80)],
  1084. Red = gb_trees:from_orddict(Red0),
  1085. rel_op_combinations_3(100, Red).
  1086. rel_op_combinations_1(0, _) ->
  1087. ok;
  1088. rel_op_combinations_1(N, Digits) ->
  1089. Bool = gb_sets:is_member(N, Digits),
  1090. Bool = is_digit_1(N),
  1091. Bool = is_digit_2(N),
  1092. Bool = is_digit_3(N),
  1093. Bool = is_digit_4(N),
  1094. Bool = is_digit_5(N),
  1095. Bool = is_digit_6(N),
  1096. Bool = is_digit_7(N),
  1097. Bool = is_digit_8(N),
  1098. Bool = is_digit_9(42, N),
  1099. Bool = is_digit_10(N, 0),
  1100. Bool = is_digit_11(N, 0),
  1101. rel_op_combinations_1(N-1, Digits).
  1102. is_digit_1(X) when 16#0660 =< X, X =< 16#0669 -> true;
  1103. is_digit_1(X) when 16#0030 =< X, X =< 16#0039 -> true;
  1104. is_digit_1(X) when 16#06F0 =< X, X =< 16#06F9 -> true;
  1105. is_digit_1(_) -> false.
  1106. is_digit_2(X) when (16#0030-1) < X, X =< 16#0039 -> true;
  1107. is_digit_2(X) when (16#0660-1) < X, X =< 16#0669 -> true;
  1108. is_digit_2(X) when (16#06F0-1) < X, X =< 16#06F9 -> true;
  1109. is_digit_2(_) -> false.
  1110. is_digit_3(X) when 16#0660 =< X, X < (16#0669+1) -> true;
  1111. is_digit_3(X) when 16#0030 =< X, X < (16#0039+1) -> true;
  1112. is_digit_3(X) when 16#06F0 =< X, X < (16#06F9+1) -> true;
  1113. is_digit_3(_) -> false.
  1114. is_digit_4(X) when (16#0660-1) < X, X < (16#0669+1) -> true;
  1115. is_digit_4(X) when (16#0030-1) < X, X < (16#0039+1) -> true;
  1116. is_digit_4(X) when (16#06F0-1) < X, X < (16#06F9+1) -> true;
  1117. is_digit_4(_) -> false.
  1118. is_digit_5(X) when X >= 16#0660, X =< 16#0669 -> true;
  1119. is_digit_5(X) when X >= 16#0030, X =< 16#0039 -> true;
  1120. is_digit_5(X) when X >= 16#06F0, X =< 16#06F9 -> true;
  1121. is_digit_5(_) -> false.
  1122. is_digit_6(X) when X > (16#0660-1), X =< 16#0669 -> true;
  1123. is_digit_6(X) when X > (16#0030-1), X =< 16#0039 -> true;
  1124. is_digit_6(X) when X > (16#06F0-1), X =< 16#06F9 -> true;
  1125. is_digit_6(_) -> false.
  1126. is_digit_7(X) when 16#0660 =< X, X =< 16#0669 -> true;
  1127. is_digit_7(X) when 16#0030 =< X, X =< 16#003A, X =/= 16#003A -> true;
  1128. is_digit_7(X) when 16#06F0 =< X, X =< 16#06F9 -> true;
  1129. is_digit_7(_) -> false.
  1130. is_digit_8(X) when X =< 16#0039, X > (16#0030-1) -> true;
  1131. is_digit_8(X) when X =< 16#06F9, X > (16#06F0-1) -> true;
  1132. is_digit_8(X) when X =< 16#0669, X > (16#0660-1) -> true;
  1133. is_digit_8(16#0670) -> false;
  1134. is_digit_8(_) -> false.
  1135. is_digit_9(A, 0) when A =:= 42 -> false;
  1136. is_digit_9(_, X) when X > 16#065F, X < 16#066A -> true;
  1137. is_digit_9(_, X) when 16#0030 =< X, X =< 16#0039 -> true;
  1138. is_digit_9(_, X) when 16#06F0 =< X, X =< 16#06F9 -> true;
  1139. is_digit_9(_, _) -> false.
  1140. is_digit_10(0, 0) -> false;
  1141. is_digit_10(X, _) when X < 16#066A, 16#0660 =< X -> true;
  1142. is_digit_10(X, _) when 16#0030 =< X, X =< 16#0039 -> true;
  1143. is_digit_10(X, _) when 16#06F0 =< X, X =< 16#06F9 -> true;
  1144. is_digit_10(_, _) -> false.
  1145. is_digit_11(0, 0) -> false;
  1146. is_digit_11(X, _) when X =< 16#0669, 16#0660 =< X -> true;
  1147. is_digit_11(X, _) when 16#0030 =< X, X =< 16#0039 -> true;
  1148. is_digit_11(X, _) when 16#06F0 =< X, X =< 16#06F9 -> true;
  1149. is_digit_11(_, _) -> false.
  1150. rel_op_combinations_2(0, _) ->
  1151. ok;
  1152. rel_op_combinations_2(N, Range) ->
  1153. Bool = gb_sets:is_member(N, Range),
  1154. Bool = broken_range_1(N),
  1155. Bool = broken_range_2(N),
  1156. Bool = broken_range_3(N),
  1157. Bool = broken_range_4(N),
  1158. Bool = broken_range_5(N),
  1159. Bool = broken_range_6(N),
  1160. Bool = broken_range_7(N),
  1161. Bool = broken_range_8(N),
  1162. Bool = broken_range_9(N),
  1163. Bool = broken_range_10(N),
  1164. Bool = broken_range_11(N),
  1165. Bool = broken_range_12(N),
  1166. Bool = broken_range_13(N),
  1167. rel_op_combinations_2(N-1, Range).
  1168. broken_range_1(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1169. broken_range_1(X) when X >= 3, X =< 5 -> true;
  1170. broken_range_1(_) -> false.
  1171. broken_range_2(X) when X >= 10, X =< 12 -> true;
  1172. broken_range_2(X) when X >= 14, X =< 20 -> true;
  1173. broken_range_2(X) when X >= 3, X =< 5 -> true;
  1174. broken_range_2(_) -> false.
  1175. broken_range_3(X) when X >= 10, X =< 12 -> true;
  1176. broken_range_3(X) when X >= 14, X < 21 -> true;
  1177. broken_range_3(3) -> true;
  1178. broken_range_3(4) -> true;
  1179. broken_range_3(5) -> true;
  1180. broken_range_3(_) -> false.
  1181. broken_range_4(X) when X =< 5, X >= 3 -> true;
  1182. broken_range_4(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1183. broken_range_4(X) when X =< 100 -> false;
  1184. broken_range_4(_) -> false.
  1185. broken_range_5(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1186. broken_range_5(X) when X > 2, X =< 5 -> true;
  1187. broken_range_5(_) -> false.
  1188. broken_range_6(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1189. broken_range_6(X) when X > 2, X < 6 -> true;
  1190. broken_range_6(_) -> false.
  1191. broken_range_7(X) when X > 2, X < 6 -> true;
  1192. broken_range_7(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1193. broken_range_7(X) when X > 30 -> false;
  1194. broken_range_7(_) -> false.
  1195. broken_range_8(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1196. broken_range_8(X) when X =:= 3 -> true;
  1197. broken_range_8(X) when X >= 3, X =< 5 -> true;
  1198. broken_range_8(_) -> false.
  1199. broken_range_9(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1200. broken_range_9(X) when X =:= 13 -> false;
  1201. broken_range_9(X) when X >= 3, X =< 5 -> true;
  1202. broken_range_9(_) -> false.
  1203. broken_range_10(X) when X >= 3, X =< 5 -> true;
  1204. broken_range_10(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1205. broken_range_10(X) when X =/= 13 -> false;
  1206. broken_range_10(_) -> false.
  1207. broken_range_11(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1208. broken_range_11(X) when is_tuple(X), X =:= 10 -> true;
  1209. broken_range_11(X) when X >= 3, X =< 5 -> true;
  1210. broken_range_11(_) -> false.
  1211. broken_range_12(X) when X >= 3, X =< 5 -> true;
  1212. broken_range_12(X) when X >= 10, X =< 20, X =/= 13 -> true;
  1213. broken_range_12(X) when X < 30, X > 20 -> false;
  1214. broken_range_12(_) -> false.
  1215. broken_range_13(X) when X >= 10, X =< 20, 13 =/= X -> true;
  1216. broken_range_13(X) when X >= 3, X =< 5 -> true;
  1217. broken_range_13(_) -> false.
  1218. rel_op_combinations_3(0, _) ->
  1219. ok;
  1220. rel_op_combinations_3(N, Red) ->
  1221. Val = case gb_trees:lookup(N, Red) of
  1222. none -> none;
  1223. {value,V} -> V
  1224. end,
  1225. Val = redundant_1(N),
  1226. Val = redundant_2(N),
  1227. Val = redundant_3(N),
  1228. Val = redundant_4(N),
  1229. Val = redundant_5(N),
  1230. Val = redundant_6(N),
  1231. Val = redundant_7(N),
  1232. Val = redundant_8(N),
  1233. Val = redundant_9(N),
  1234. Val = redundant_10(N),
  1235. Val = redundant_11(N),
  1236. Val = redundant_11(N),
  1237. rel_op_combinations_3(N-1, Red).
  1238. redundant_1(X) when X >= 51, X =< 80 -> 5*X;
  1239. redundant_1(X) when X < 51 -> 2*X;
  1240. redundant_1(_) -> none.
  1241. redundant_2(X) when X < 51 -> 2*X;
  1242. redundant_2(X) when X >= 51, X =< 80 -> 5*X;
  1243. redundant_2(_) -> none.
  1244. redundant_3(X) when X < 51 -> 2*X;
  1245. redundant_3(X) when X =< 80, X >= 51 -> 5*X;
  1246. redundant_3(X) when X =/= 100 -> none;
  1247. redundant_3(_) -> none.
  1248. redundant_4(X) when X < 51 -> 2*X;
  1249. redundant_4(X) when X =< 80, X > 50 -> 5*X;
  1250. redundant_4(X) when X =/= 100 -> none;
  1251. redundant_4(_) -> none.
  1252. redundant_5(X) when X < 51 -> 2*X;
  1253. redundant_5(X) when X > 50, X < 81 -> 5*X;
  1254. redundant_5(X) when X =< 10 -> none;
  1255. redundant_5(_) -> none.
  1256. redundant_6(X) when X > 50, X =< 80 -> 5*X;
  1257. redundant_6(X) when X < 51 -> 2*X;
  1258. redundant_6(_) -> none.
  1259. redundant_7(X) when is_integer(X), X >= 51, X =< 80 -> 5*X;
  1260. redundant_7(X) when is_integer(X), X < 51 -> 2*X;
  1261. redundant_7(_) -> none.
  1262. redundant_8(X) when X >= 51, X =< 80 -> 5*X;
  1263. redundant_8(X) when X < 51 -> 2*X;
  1264. redundant_8(_) -> none.
  1265. redundant_9(X) when X >= 51, X =< 80 -> 5*X;
  1266. redundant_9(X) when X < 51 -> 2*X;
  1267. redundant_9(90) -> none;
  1268. redundant_9(X) when X =/= 90 -> none;
  1269. redundant_9(_) -> none.
  1270. redundant_10(X) when X >= 51, X =< 80 -> 5*X;
  1271. redundant_10(X) when X < 51 -> 2*X;
  1272. redundant_10(90) -> none;
  1273. redundant_10(X) when X =:= 90 -> none;
  1274. redundant_10(_) -> none.
  1275. redundant_11(X) when X < 51 -> 2*X;
  1276. redundant_11(X) when X =:= 10 -> 2*X;
  1277. redundant_11(X) when X >= 51, X =< 80 -> 5*X;
  1278. redundant_11(_) -> none.
  1279. redundant_12(X) when X >= 50, X =< 80 -> 2*X;
  1280. redundant_12(X) when X < 51 -> 5*X;
  1281. redundant_12(_) -> none.
  1282. %% Test type tests on literal values. (From emulator test suites.)
  1283. literal_type_tests(Config) when is_list(Config) ->
  1284. case ?MODULE of
  1285. guard_SUITE -> literal_type_tests_1(Config);
  1286. _ -> {skip,"Enough to run this case once."}
  1287. end.
  1288. literal_type_tests_1(Config) ->
  1289. %% Generate an Erlang module with all different type of type tests.
  1290. Tests = make_test([{T,L} || T <- type_tests(), L <- literals()] ++
  1291. [{is_function,L1,L2} ||
  1292. L1 <- literals(), L2 <- literals()]),
  1293. Mod = literal_test,
  1294. Anno = erl_anno:new(0),
  1295. Func = {function, Anno, test, 0, [{clause,Anno,[],[],Tests}]},
  1296. Form = [{attribute,Anno,module,Mod},
  1297. {attribute,Anno,compile,export_all},
  1298. Func, {eof,999}],
  1299. %% Print generated code for inspection.
  1300. lists:foreach(fun (F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Form),
  1301. %% Test compile:form/1. This implies full optimization (default).
  1302. {ok,Mod,Code1} = compile:forms(Form),
  1303. smoke_disasm(Config, Mod, Code1),
  1304. {module,Mod} = code:load_binary(Mod, Mod, Code1),
  1305. Mod:test(),
  1306. true = code:delete(Mod),
  1307. code:purge(Mod),
  1308. %% Test compile:form/2. Turn off all optimizations.
  1309. {ok,Mod,Code2} = compile:forms(Form, [binary,report,time,
  1310. no_copt,no_postopt]),
  1311. smoke_disasm(Config, Mod, Code2),
  1312. {module,Mod} = code:load_binary(Mod, Mod, Code2),
  1313. Mod:test(),
  1314. true = code:delete(Mod),
  1315. code:purge(Mod),
  1316. ok.
  1317. make_test([{T,L1,L2}|Ts]) ->
  1318. [test(T, L1, L2)|make_test(Ts)];
  1319. make_test([{T,L}|Ts]) ->
  1320. [test(T, L)|make_test(Ts)];
  1321. make_test([]) -> [].
  1322. test(T, L) ->
  1323. S0 = io_lib:format("begin io:format(\"~~p~n\", [{~p,~p}]), if ~w(~w) -> true; true -> false end end. ", [T,L,T,L]),
  1324. S = lists:flatten(S0),
  1325. {ok,Toks,_Line} = erl_scan:string(S),
  1326. {ok,E} = erl_parse:parse_exprs(Toks),
  1327. {value,Val,_Bs} = erl_eval:exprs(E, []),
  1328. Anno = erl_anno:new(0),
  1329. {match,Anno,{atom,Anno,Val},hd(E)}.
  1330. test(T, L1, L2) ->
  1331. S0 = io_lib:format("begin io:format(\"~~p~n\", [{~p,~p,~p}]), if ~w(~w, ~w) -> true; true -> false end end. ", [T,L1,L2,T,L1,L2]),
  1332. S = lists:flatten(S0),
  1333. {ok,Toks,_Line} = erl_scan:string(S),
  1334. {ok,E} = erl_parse:parse_exprs(Toks),
  1335. {value,Val,_Bs} = erl_eval:exprs(E, []),
  1336. Anno = erl_anno:new(0),
  1337. {match,Anno,{atom,Anno,Val},hd(E)}.
  1338. smoke_disasm(Config, Mod, Bin) ->
  1339. Priv = proplists:get_value(priv_dir, Config),
  1340. File = filename:join(Priv, atom_to_list(Mod)++".beam"),
  1341. ok = file:write_file(File, Bin),
  1342. test_lib:smoke_disasm(File).
  1343. literals() ->
  1344. [42,
  1345. 3.14,
  1346. -3,
  1347. 32982724987789283473473838474,
  1348. [],
  1349. xxxx,
  1350. {a,b,c},
  1351. [a,list],
  1352. <<1,2,3>>,
  1353. <<42:17>>].
  1354. type_tests() ->
  1355. [is_boolean,
  1356. is_integer,
  1357. is_float,
  1358. is_number,
  1359. is_atom,
  1360. is_list,
  1361. is_tuple,
  1362. is_pid,
  1363. is_reference,
  1364. is_port,
  1365. is_binary,
  1366. is_bitstring,
  1367. is_function,
  1368. is_map].
  1369. basic_andalso_orelse(Config) when is_list(Config) ->
  1370. T = id({type,integers,23,42}),
  1371. 65 = if
  1372. ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso
  1373. element(2, T)) == integers ->
  1374. element(3, T) + element(4, T);
  1375. true -> error
  1376. end,
  1377. 65 = case [] of
  1378. [] when ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso
  1379. element(2, T)) == integers ->
  1380. element(3, T) + element(4, T)
  1381. end,
  1382. 42 = basic_rt({type,integers,40,2}),
  1383. 5.0 = basic_rt({vector,{3.0,4.0}}),
  1384. 20 = basic_rt(['+',3,7]),
  1385. {'Set',a,b} = basic_rt({{'Set',a,b},{'Set',a,b}}),
  1386. 12 = basic_rt({klurf,4}),
  1387. error = basic_rt({type,integers,40,2,3}),
  1388. error = basic_rt({kalle,integers,40,2}),
  1389. error = basic_rt({kalle,integers,40,2}),
  1390. error = basic_rt({1,2}),
  1391. error = basic_rt([]),
  1392. RelProdBody =
  1393. fun(R1, R2) ->
  1394. if
  1395. (erlang:size(R1) =:= 3) andalso (erlang:element(1,R1) =:= 'Set'),
  1396. (erlang:size(R2) =:= 3) andalso (erlang:element(1,R2) =:= 'Set') ->
  1397. ok
  1398. end
  1399. end,
  1400. ok = RelProdBody({'Set',a,b}, {'Set',a,b}),
  1401. %% 'andalso'/'orelse' with calls known to fail already at compile time.
  1402. %% Used to crash the code generator.
  1403. error = (fun() ->
  1404. R = {vars,true},
  1405. if
  1406. is_record(R, vars, 2) andalso element(99, R) -> ok;
  1407. true -> error
  1408. end
  1409. end)(),
  1410. error = (fun(X) ->
  1411. L = {a,b,c},
  1412. if
  1413. is_list(X) andalso length(L) > 4 -> ok;
  1414. true -> error
  1415. end
  1416. end)([]),
  1417. ok.
  1418. basic_rt(T) when is_tuple(T) andalso tuple_size(T) =:= 4 andalso element(1, T) =:= type andalso
  1419. element(2, T) == integers ->
  1420. element(3, T) + element(4, T);
  1421. basic_rt(T) when is_tuple(T) andalso tuple_size(T) =:= 2 andalso element(1, T) =:= vector ->
  1422. {X,Y} = element(2, T),
  1423. if
  1424. is_float(X), is_float(Y) ->
  1425. math:sqrt(X*X+Y*Y)
  1426. end;
  1427. basic_rt(['+',A,B]) ->
  1428. 2*id(A+B);
  1429. basic_rt({R1,R2}) when erlang:size(R1) =:= 3 andalso erlang:element(1,R1) =:= 'Set',
  1430. erlang:size(R2) =:= 3 andalso erlang:element(1,R2) =:= 'Set' ->
  1431. R1 = id(R1),
  1432. R2 = id(R2),
  1433. R1;
  1434. basic_rt(T) when is_tuple(T) andalso tuple_size(T) =:= 2 andalso element(1, T) =:= klurf ->
  1435. 3*id(element(2, T));
  1436. basic_rt(_) ->
  1437. error.
  1438. traverse_dcd(Config) when is_list(Config) ->
  1439. L0 = [{log_header,dcd_log,"1.0",a,b,c},{log_header,dcd_log,"2.0",a,b,c},
  1440. {log_header,dcd_log,"0.0",a,b,c},blurf],
  1441. {cont,[{log_header,dcd_log,"0.0",a,b,c},blurf],log,funny} =
  1442. traverse_dcd({cont,L0}, log, funny),
  1443. L1 = [{log_header,dcd_log,"1.0"}],
  1444. {cont,L1,log,funny} = traverse_dcd({cont,L1}, log, funny),
  1445. L2 = [{a,tuple}],
  1446. {cont,L2,log,funny} = traverse_dcd({cont,L2}, log, funny),
  1447. ok.
  1448. %% The function starts out with 3 arguments in {x,0}, {x,1}, {x,2}.
  1449. %% The outer match of a two tuple will places the first element in {x,3} and
  1450. %% second in {x,4}. The guard for the first clause must make ensure that all of those
  1451. %% registers are restored before entering the second clause.
  1452. %%
  1453. %% (From mnesia_checkpoint.erl, modified.)
  1454. traverse_dcd({Cont,[LogH|Rest]},Log,Fun)
  1455. when is_tuple(LogH) andalso tuple_size(LogH) =:= 6 andalso element(1, LogH) =:= log_header
  1456. andalso erlang:element(2,LogH) == dcd_log,
  1457. is_tuple(LogH) andalso tuple_size(LogH) =:= 6 andalso element(1, LogH) =:= log_header
  1458. andalso erlang:element(3,LogH) >= "1.0" ->
  1459. traverse_dcd({Cont,Rest},Log,Fun);
  1460. traverse_dcd({Cont,Recs},Log,Fun) ->
  1461. {Cont,Recs,Log,Fun}.
  1462. check_qlc_hrl(Config) when is_list(Config) ->
  1463. St = {r1,false,dum},
  1464. foo = cqlc(qlc, q, [{lc,1,2,3}], St),
  1465. foo = cqlc(qlc, q, [{lc,1,2,3},b], St),
  1466. St = cqlc(qlc, q, [], St),
  1467. St = cqlc(qlc, blurf, [{lc,1,2,3},b], St),
  1468. St = cqlc(q, q, [{lc,1,2,3},b], St),
  1469. St = cqlc(qlc, q, [{lc,1,2,3},b,c], St),
  1470. St = cqlc(qlc, q, [a,b], St),
  1471. {r1,true,kalle} = cqlc(qlc, q, [{lc,1,2,3},b], {r1,true,kalle}),
  1472. ok.
  1473. %% From erl_lint.erl; original name was check_qlc_hrl/4.
  1474. cqlc(M, F, As, St) ->
  1475. Arity = length(As),
  1476. case As of
  1477. [{lc,_L,_E,_Qs}|_] when M =:= qlc, F =:= q,
  1478. Arity < 3,
  1479. not (((element(1, St) =:= r1) orelse fail) and (tuple_size(St) =:= 3) and element(2, St)) ->
  1480. foo;
  1481. _ ->
  1482. St
  1483. end.
  1484. %% OTP-7679: Thanks to Hunter Morris.
  1485. andalso_semi(Config) when is_list(Config) ->
  1486. ok = andalso_semi_foo(0),
  1487. ok = andalso_semi_foo(1),
  1488. fc(catch andalso_semi_foo(2)),
  1489. ok = andalso_semi_bar([a,b,c]),
  1490. ok = andalso_semi_bar(1),
  1491. fc(catch andalso_semi_bar([a,b])),
  1492. ok.
  1493. andalso_semi_foo(Bar) when is_integer(Bar) andalso Bar =:= 0; Bar =:= 1 ->
  1494. ok.
  1495. andalso_semi_bar(Bar) when is_list(Bar) andalso length(Bar) =:= 3; Bar =:= 1 ->
  1496. ok.
  1497. t_tuple_size(Config) when is_list(Config) ->
  1498. 10 = do_tuple_size({1,2,3,4}),
  1499. fc(catch do_tuple_size({1,2,3})),
  1500. fc(catch do_tuple_size(42)),
  1501. error = ludicrous_tuple_size({a,b,c}),
  1502. error = ludicrous_tuple_size([a,b,c]),
  1503. good_ip({1,2,3,4}),
  1504. good_ip({1,2,3,4,5,6,7,8}),
  1505. error = validate_ip({42,11}),
  1506. error = validate_ip(atom),
  1507. ok.
  1508. do_tuple_size(T) when tuple_size(T) =:= 4 ->
  1509. {A,B,C,D} = T,
  1510. A+B+C+D.
  1511. ludicrous_tuple_size(T)
  1512. when tuple_size(T) =:= 16#7777777777777777777777777777777777 -> ok;
  1513. ludicrous_tuple_size(T)
  1514. when tuple_size(T) =:= 16#10000000000000000 -> ok;
  1515. ludicrous_tuple_size(T)
  1516. when tuple_size(T) =:= (1 bsl 64) - 1 -> ok;
  1517. ludicrous_tuple_size(T)
  1518. when tuple_size(T) =:= 16#FFFFFFFFFFFFFFFF -> ok;
  1519. ludicrous_tuple_size(_) -> error.
  1520. good_ip(IP) ->
  1521. IP = validate_ip(IP).
  1522. validate_ip(Value) when is_tuple(Value) andalso
  1523. ((size(Value) =:= 4) orelse (size(Value) =:= 8)) ->
  1524. %% size/1 (converted to tuple_size) used more than once.
  1525. Value;
  1526. validate_ip(_) ->
  1527. error.
  1528. %%
  1529. %% The binary_part/2,3 guard BIFs
  1530. %%
  1531. -define(MASK_ERROR(EXPR),mask_error((catch (EXPR)))).
  1532. mask_error({'EXIT',{Err,_}}) ->
  1533. Err;
  1534. mask_error(Else) ->
  1535. Else.
  1536. %% Test the binary_part/2,3 guard (GC) BIFs.
  1537. binary_part(Config) when is_list(Config) ->
  1538. %% This is more or less a copy of what the guard_SUITE in emulator
  1539. %% does to cover the guard bif's
  1540. 1 = bptest(<<1,2,3>>),
  1541. 2 = bptest(<<2,1,3>>),
  1542. error = bptest(<<1>>),
  1543. error = bptest(<<>>),
  1544. error = bptest(apa),
  1545. 3 = bptest(<<2,3,3>>),
  1546. % With one variable (pos)
  1547. 1 = bptest(<<1,2,3>>,1),
  1548. 2 = bptest(<<2,1,3>>,1),
  1549. error = bptest(<<1>>,1),
  1550. error = bptest(<<>>,1),
  1551. error = bptest(apa,1),
  1552. 3 = bptest(<<2,3,3>>,1),
  1553. % With one variable (length)
  1554. 1 = bptesty(<<1,2,3>>,1),
  1555. 2 = bptesty(<<2,1,3>>,1),
  1556. error = bptesty(<<1>>,1),
  1557. error = bptesty(<<>>,1),
  1558. error = bptesty(apa,1),
  1559. 3 = bptesty(<<2,3,3>>,2),
  1560. % With one variable (whole tuple)
  1561. 1 = bptestx(<<1,2,3>>,{1,1}),
  1562. 2 = bptestx(<<2,1,3>>,{1,1}),
  1563. error = bptestx(<<1>>,{1,1}),
  1564. error = bptestx(<<>>,{1,1}),
  1565. error = bptestx(apa,{1,1}),
  1566. 3 = bptestx(<<2,3,3>>,{1,2}),
  1567. % With two variables
  1568. 1 = bptest(<<1,2,3>>,1,1),
  1569. 2 = bptest(<<2,1,3>>,1,1),
  1570. error = bptest(<<1>>,1,1),
  1571. error = bptest(<<>>,1,1),
  1572. error = bptest(apa,1,1),
  1573. 3 = bptest(<<2,3,3>>,1,2),
  1574. % Direct (autoimported) call, these will be evaluated by the compiler...
  1575. <<2>> = binary_part(<<1,2,3>>,1,1),
  1576. <<1>> = binary_part(<<2,1,3>>,1,1),
  1577. % Compiler warnings due to constant evaluation expected (3)
  1578. badarg = ?MASK_ERROR(binary_part(<<1>>,1,1)),
  1579. badarg = ?MASK_ERROR(binary_part(<<>>,1,1)),
  1580. badarg = ?MASK_ERROR(binary_part(apa,1,1)),
  1581. <<3,3>> = binary_part(<<2,3,3>>,1,2),
  1582. % Direct call through apply
  1583. <<2>> = apply(erlang,binary_part,[<<1,2,3>>,1,1]),
  1584. <<1>> = apply(erlang,binary_part,[<<2,1,3>>,1,1]),
  1585. % Compiler warnings due to constant evaluation expected (3)
  1586. badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<1>>,1,1])),
  1587. badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<>>,1,1])),
  1588. badarg = ?MASK_ERROR(apply(erlang,binary_part,[apa,1,1])),
  1589. <<3,3>> = apply(erlang,binary_part,[<<2,3,3>>,1,2]),
  1590. % Constant propagation
  1591. Bin = <<1,2,3>>,
  1592. ok = if
  1593. binary_part(Bin,1,1) =:= <<2>> ->
  1594. ok;
  1595. %% Compiler warning, clause cannot match (expected)
  1596. true ->
  1597. error
  1598. end,
  1599. ok = if
  1600. binary_part(Bin,{1,1}) =:= <<2>> ->
  1601. ok;
  1602. %% Compiler warning, clause cannot match (expected)
  1603. true ->
  1604. error
  1605. end,
  1606. ok.
  1607. bptest(B) when length(B) =:= 1337 ->
  1608. 1;
  1609. bptest(B) when binary_part(B,{1,1}) =:= <<2>> ->
  1610. 1;
  1611. bptest(B) when erlang:binary_part(B,1,1) =:= <<1>> ->
  1612. 2;
  1613. bptest(B) when erlang:binary_part(B,{1,2}) =:= <<3,3>> ->
  1614. 3;
  1615. bptest(_) ->
  1616. error.
  1617. bptest(B,A) when length(B) =:= A ->
  1618. 1;
  1619. bptest(B,A) when binary_part(B,{A,1}) =:= <<2>> ->
  1620. 1;
  1621. bptest(B,A) when erlang:binary_part(B,A,1) =:= <<1>> ->
  1622. 2;
  1623. bptest(B,A) when erlang:binary_part(B,{A,2}) =:= <<3,3>> ->
  1624. 3;
  1625. bptest(_,_) ->
  1626. error.
  1627. bptestx(B,A) when length(B) =:= A ->
  1628. 1;
  1629. bptestx(B,A) when binary_part(B,A) =:= <<2>> ->
  1630. 1;
  1631. bptestx(B,A) when erlang:binary_part(B,A) =:= <<1>> ->
  1632. 2;
  1633. bptestx(B,A) when erlang:binary_part(B,A) =:= <<3,3>> ->
  1634. 3;
  1635. bptestx(_,_) ->
  1636. error.
  1637. bptesty(B,A) when length(B) =:= A ->
  1638. 1;
  1639. bptesty(B,A) when binary_part(B,{1,A}) =:= <<2>> ->
  1640. 1;
  1641. bptesty(B,A) when erlang:binary_part(B,1,A) =:= <<1>> ->
  1642. 2;
  1643. bptesty(B,A) when erlang:binary_part(B,{1,A}) =:= <<3,3>> ->
  1644. 3;
  1645. bptesty(_,_) ->
  1646. error.
  1647. bptest(B,A,_C) when length(B) =:= A ->
  1648. 1;
  1649. bptest(B,A,C) when binary_part(B,{A,C}) =:= <<2>> ->
  1650. 1;
  1651. bptest(B,A,C) when erlang:binary_part(B,A,C) =:= <<1>> ->
  1652. 2;
  1653. bptest(B,A,C) when erlang:binary_part(B,{A,C}) =:= <<3,3>> ->
  1654. 3;
  1655. bptest(_,_,_) ->
  1656. error.
  1657. -define(FAILING(C),
  1658. if
  1659. C -> ct:fail(should_fail);
  1660. true -> ok
  1661. end,
  1662. if
  1663. true, C -> ct:fail(should_fail);
  1664. true -> ok
  1665. end).
  1666. bad_constants(Config) when is_list(Config) ->
  1667. ?FAILING(false),
  1668. ?FAILING([]),
  1669. ?FAILING([a]),
  1670. ?FAILING([Config]),
  1671. ?FAILING({a,b}),
  1672. ?FAILING({a,Config}),
  1673. ?FAILING(<<1>>),
  1674. ?FAILING(42),
  1675. ?FAILING(3.14),
  1676. ok.
  1677. bad_guards(Config) when is_list(Config) ->
  1678. if erlang:float(self()); true -> ok end,
  1679. fc(catch bad_guards_1(1, [])),
  1680. fc(catch bad_guards_1(1, [2])),
  1681. fc(catch bad_guards_1(atom, [2])),
  1682. fc(catch bad_guards_2(#{a=>0,b=>0}, [])),
  1683. fc(catch bad_guards_2(#{a=>0,b=>0}, [x])),
  1684. fc(catch bad_guards_2(not_a_map, [x])),
  1685. fc(catch bad_guards_2(42, [x])),
  1686. fc(catch bad_guards_3(#{a=>0,b=>0}, [])),
  1687. fc(catch bad_guards_3(#{a=>0,b=>0}, [x])),
  1688. fc(catch bad_guards_3(not_a_map, [x])),
  1689. fc(catch bad_guards_3(42, [x])),
  1690. fc(catch bad_guards_4()),
  1691. ok.
  1692. %% beam_bool used to produce GC BIF instructions whose
  1693. %% Live operands included uninitialized registers.
  1694. bad_guards_1(X, [_]) when {{X}}, -X ->
  1695. ok.
  1696. bad_guards_2(M, [_]) when M#{a := 0, b => 0}, map_size(M) ->
  1697. ok.
  1698. %% beam_type used to produce an GC BIF instruction whose Live operand
  1699. %% included uninitialized registers.
  1700. bad_guards_3(M, [_]) when is_map(M) andalso M#{a := 0, b => 0}, length(M) ->
  1701. ok.
  1702. %% v3_codegen would generate a jump to the failure label, but
  1703. %% without initializing x(0). The code at the failure label expected
  1704. %% x(0) to be initialized.
  1705. bad_guards_4() when not (error#{}); {not 0.0} -> freedom.
  1706. %% Building maps in a guard in a 'catch' would crash v3_codegen.
  1707. guard_in_catch(_Config) ->
  1708. {'EXIT',{if_clause,_}} = do_guard_in_catch_map_1(#{}),
  1709. {'EXIT',{if_clause,_}} = do_guard_in_catch_map_1(#{a=>b}),
  1710. {'EXIT',{if_clause,_}} = do_guard_in_catch_map_1(atom),
  1711. {'EXIT',{if_clause,_}} = do_guard_in_catch_map_2(#{}),
  1712. {'EXIT',{if_clause,_}} = do_guard_in_catch_map_2(#{a=>b}),
  1713. {'EXIT',{if_clause,_}} = do_guard_in_catch_map_2(atom),
  1714. {'EXIT',{if_clause,_}} = (catch do_guard_in_catch_map_3()),
  1715. {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(42),
  1716. {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(<<1,2,3>>),
  1717. {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(atom),
  1718. {'EXIT',{if_clause,_}} = do_guard_in_catch_bin(#{}),
  1719. ok.
  1720. do_guard_in_catch_map_1(From) ->
  1721. catch
  1722. if
  1723. From#{[] => sufficient} ->
  1724. saint
  1725. end.
  1726. do_guard_in_catch_map_2(From) ->
  1727. catch
  1728. if
  1729. From#{From => sufficient} ->
  1730. saint
  1731. end.
  1732. do_guard_in_catch_map_3() ->
  1733. try
  1734. if [] -> solo end
  1735. catch
  1736. Friendly when Friendly#{0 => []} -> minutes
  1737. after
  1738. membership
  1739. end.
  1740. do_guard_in_catch_bin(From) ->
  1741. %% Would not crash v3_codegen, but there would be an unnecessary
  1742. %% 'move' to a Y register.
  1743. catch
  1744. if
  1745. <<From:32>> ->
  1746. saint
  1747. end.
  1748. %%%
  1749. %%% The beam_bool pass has been eliminated. Here are the tests from
  1750. %%% beam_bool_SUITE.
  1751. %%%
  1752. beam_bool_SUITE(_Config) ->
  1753. before_and_inside_if(),
  1754. scotland(),
  1755. y_registers(),
  1756. protected(),
  1757. maps(),
  1758. ok.
  1759. before_and_inside_if() ->
  1760. no = before_and_inside_if([a], [b], delete),
  1761. no = before_and_inside_if([a], [b], x),
  1762. no = before_and_inside_if([a], [], delete),
  1763. no = before_and_inside_if([a], [], x),
  1764. no = before_and_inside_if([], [], delete),
  1765. yes = before_and_inside_if([], [], x),
  1766. yes = before_and_inside_if([], [b], delete),
  1767. yes = before_and_inside_if([], [b], x),
  1768. {ch1,ch2} = before_and_inside_if_2([a], [b], blah),
  1769. {ch1,ch2} = before_and_inside_if_2([a], [b], xx),
  1770. {ch1,ch2} = before_and_inside_if_2([a], [], blah),
  1771. {ch1,ch2} = before_and_inside_if_2([a], [], xx),
  1772. {no,no} = before_and_inside_if_2([], [b], blah),
  1773. {no,no} = before_and_inside_if_2([], [b], xx),
  1774. {ch1,no} = before_and_inside_if_2([], [], blah),
  1775. {no,ch2} = before_and_inside_if_2([], [], xx),
  1776. ok.
  1777. %% Thanks to Simon Cornish and Kostis Sagonas.
  1778. %% Used to crash beam_bool.
  1779. before_and_inside_if(XDo1, XDo2, Do3) ->
  1780. Do1 = (XDo1 =/= []),
  1781. Do2 = (XDo2 =/= []),
  1782. if
  1783. %% This expression occurs in a try/catch (protected)
  1784. %% block, which cannot refer to variables outside of
  1785. %% the block that are boolean expressions.
  1786. Do1 =:= true;
  1787. Do1 =:= false, Do2 =:= false, Do3 =:= delete ->
  1788. no;
  1789. true ->
  1790. yes
  1791. end.
  1792. %% Thanks to Simon Cornish.
  1793. %% Used to generate code that would not set {y,0} on
  1794. %% all paths before its use (and therefore fail
  1795. %% validation by the beam_validator).
  1796. before_and_inside_if_2(XDo1, XDo2, Do3) ->
  1797. Do1 = (XDo1 =/= []),
  1798. Do2 = (XDo2 =/= []),
  1799. CH1 = if Do1 == true;
  1800. Do1 == false,Do2==false,Do3 == blah ->
  1801. ch1;
  1802. true ->
  1803. no
  1804. end,
  1805. CH2 = if Do1 == true;
  1806. Do1 == false,Do2==false,Do3 == xx ->
  1807. ch2;
  1808. true ->
  1809. no
  1810. end,
  1811. {CH1,CH2}.
  1812. %% beam_bool would remove the initialization of {y,0}.
  1813. %% (Thanks to Thomas Arts and QuickCheck.)
  1814. scotland() ->
  1815. million = do_scotland(placed),
  1816. {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(false)),
  1817. {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(true)),
  1818. {'EXIT',{{badmatch,placed},_}} = (catch do_scotland(echo)),
  1819. ok.
  1820. do_scotland(Echo) ->
  1821. found(case Echo of
  1822. Echo when true; Echo, Echo, Echo ->
  1823. Echo;
  1824. echo ->
  1825. []
  1826. end,
  1827. Echo = placed).
  1828. found(_, _) -> million.
  1829. %% ERL-143: beam_bool could not handle Y registers as a destination.
  1830. y_registers() ->
  1831. {'EXIT',{badarith,[_|_]}} = (catch baker(valentine)),
  1832. {'EXIT',{badarith,[_|_]}} = (catch baker(clementine)),
  1833. {not_ok,true} = potter([]),
  1834. {ok,false} = potter([{encoding,any}]),
  1835. ok.
  1836. %% Thanks to Quickcheck.
  1837. baker(Baker) ->
  1838. (valentine == Baker) +
  1839. case Baker of
  1840. Baker when Baker; Baker ->
  1841. Baker;
  1842. Baker ->
  1843. []
  1844. end.
  1845. %% Thanks to Jose Valim.
  1846. potter(Modes) ->
  1847. Raw = lists:keyfind(encoding, 1, Modes) == false,
  1848. Final = case Raw of
  1849. X when X == false; X == nil -> ok;
  1850. _ -> not_ok
  1851. end,
  1852. {Final,Raw}.
  1853. protected() ->
  1854. {'EXIT',{if_clause,_}} = (catch photographs({1, surprise, true}, opinions)),
  1855. {{true}} = welcome({perfect, true}),
  1856. {'EXIT',{if_clause,_}} = (catch welcome({perfect, false})),
  1857. ok.
  1858. photographs({_Violation, surprise, Deep}, opinions) ->
  1859. {if
  1860. 0; "here", Deep ->
  1861. Deep = Deep
  1862. end}.
  1863. welcome({perfect, Profit}) ->
  1864. if
  1865. Profit, Profit, Profit; 0 ->
  1866. {id({Profit})}
  1867. end.
  1868. maps() ->
  1869. ok = evidence(#{0 => 42}).
  1870. %% Cover handling of put_map in in split_block_label_used/2.
  1871. evidence(#{0 := Charge}) when 0; #{[] => Charge} == #{[] => 42} ->
  1872. ok.
  1873. %% Call this function to turn off constant propagation.
  1874. id(I) -> I.
  1875. check(F, Result) ->
  1876. case F() of
  1877. Result -> ok;
  1878. Other ->
  1879. io:format("Expected: ~p\n", [Result]),
  1880. io:format(" Got: ~p\n", [Other]),
  1881. ct:fail(check_failed)
  1882. end.
  1883. fc({'EXIT',{function_clause,_}}) -> ok;
  1884. fc({'EXIT',{{case_clause,_},_}}) when ?MODULE =:= guard_inline_SUITE -> ok.