1: %% -*- coding: utf-8 -*- 2: %% 3: %% %CopyrightBegin% 4: %% 5: %% Copyright Ericsson AB 1998-2013. All Rights Reserved. 6: %% 7: %% The contents of this file are subject to the Erlang Public License, 8: %% Version 1.1, (the "License"); you may not use this file except in 9: %% compliance with the License. You should have received a copy of the 10: %% Erlang Public License along with this software. If not, it can be 11: %% retrieved online at http://www.erlang.org/. 12: %% 13: %% Software distributed under the License is distributed on an "AS IS" 14: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 15: %% the License for the specific language governing rights and limitations 16: %% under the License. 17: %% 18: %% %CopyrightEnd% 19: 20: -module(erl_eval_SUITE). 21: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 22: init_per_group/2,end_per_group/2]). 23: 24: -export([guard_1/1, guard_2/1, 25: match_pattern/1, 26: match_bin/1, 27: string_plusplus/1, 28: pattern_expr/1, 29: guard_3/1, guard_4/1, 30: lc/1, 31: simple_cases/1, 32: unary_plus/1, 33: apply_atom/1, 34: otp_5269/1, 35: otp_6539/1, 36: otp_6543/1, 37: otp_6787/1, 38: otp_6977/1, 39: otp_7550/1, 40: otp_8133/1, 41: otp_10622/1, 42: funs/1, 43: try_catch/1, 44: eval_expr_5/1, 45: zero_width/1]). 46: 47: %% 48: %% Define to run outside of test server 49: %% 50: %%-define(STANDALONE,1). 51: 52: -import(lists,[concat/1, sort/1]). 53: 54: -export([count_down/2, count_down_fun/0, do_apply/2, 55: local_func/3, local_func_value/2]). 56: 57: -ifdef(STANDALONE). 58: -define(config(A,B),config(A,B)). 59: -export([config/2]). 60: -define(line, noop, ). 61: config(priv_dir,_) -> 62: ".". 63: -else. 64: -include_lib("test_server/include/test_server.hrl"). 65: -export([init_per_testcase/2, end_per_testcase/2]). 66: % Default timetrap timeout (set in init_per_testcase). 67: -define(default_timeout, ?t:minutes(1)). 68: init_per_testcase(_Case, Config) -> 69: ?line Dog = ?t:timetrap(?default_timeout), 70: [{watchdog, Dog} | Config]. 71: end_per_testcase(_Case, Config) -> 72: Dog = ?config(watchdog, Config), 73: test_server:timetrap_cancel(Dog), 74: ok. 75: -endif. 76: 77: suite() -> [{ct_hooks,[ts_install_cth]}]. 78: 79: all() -> 80: [guard_1, guard_2, match_pattern, string_plusplus, 81: pattern_expr, match_bin, guard_3, guard_4, lc, 82: simple_cases, unary_plus, apply_atom, otp_5269, 83: otp_6539, otp_6543, otp_6787, otp_6977, otp_7550, 84: otp_8133, otp_10622, funs, try_catch, eval_expr_5, zero_width]. 85: 86: groups() -> 87: []. 88: 89: init_per_suite(Config) -> 90: Config. 91: 92: end_per_suite(_Config) -> 93: ok. 94: 95: init_per_group(_GroupName, Config) -> 96: Config. 97: 98: end_per_group(_GroupName, Config) -> 99: Config. 100: 101: guard_1(doc) -> 102: ["(OTP-2405)"]; 103: guard_1(suite) -> 104: []; 105: guard_1(Config) when is_list(Config) -> 106: ?line {ok,Tokens ,_} = 107: erl_scan:string("if a+4 == 4 -> yes; true -> no end. "), 108: ?line {ok, [Expr]} = erl_parse:parse_exprs(Tokens), 109: ?line no = guard_1_compiled(), 110: ?line {value, no, []} = erl_eval:expr(Expr, []), 111: ok. 112: 113: guard_1_compiled() -> 114: if a+4 == 4 -> yes; true -> no end. 115: 116: guard_2(doc) -> 117: ["Similar to guard_1, but type-correct"]; 118: guard_2(suite) -> 119: []; 120: guard_2(Config) when is_list(Config) -> 121: ?line {ok,Tokens ,_} = 122: erl_scan:string("if 6+4 == 4 -> yes; true -> no end. "), 123: ?line {ok, [Expr]} = erl_parse:parse_exprs(Tokens), 124: ?line no = guard_2_compiled(), 125: ?line {value, no, []} = erl_eval:expr(Expr, []), 126: ok. 127: 128: guard_2_compiled() -> 129: if 6+4 == 4 -> yes; true -> no end. 130: 131: string_plusplus(doc) -> 132: ["OTP-3069: syntactic sugar string ++ ..."]; 133: string_plusplus(suite) -> 134: []; 135: string_plusplus(Config) when is_list(Config) -> 136: ?line check(fun() -> case "abc" of "ab" ++ L -> L end end, 137: "case \"abc\" of \"ab\" ++ L -> L end. ", 138: "c"), 139: ?line check(fun() -> case "abcde" of "ab" ++ "cd" ++ L -> L end end, 140: "case \"abcde\" of \"ab\" ++ \"cd\" ++ L -> L end. ", 141: "e"), 142: ?line check(fun() -> case "abc" of [97, 98] ++ L -> L end end, 143: "case \"abc\" of [97, 98] ++ L -> L end. ", 144: "c"), 145: ok. 146: 147: match_pattern(doc) -> 148: ["OTP-2983: match operator in pattern"]; 149: match_pattern(suite) -> 150: []; 151: match_pattern(Config) when is_list(Config) -> 152: ?line check(fun() -> case {a, b} of {a, _X}=Y -> {x,Y} end end, 153: "case {a, b} of {a, X}=Y -> {x,Y} end. ", 154: {x, {a, b}}), 155: ?line check(fun() -> case {a, b} of Y={a, _X} -> {x,Y} end end, 156: "case {a, b} of Y={a, X} -> {x,Y} end. ", 157: {x, {a, b}}), 158: ?line check(fun() -> case {a, b} of Y={a, _X}=Z -> {Z,Y} end end, 159: "case {a, b} of Y={a, X}=Z -> {Z,Y} end. ", 160: {{a, b}, {a, b}}), 161: ?line check(fun() -> A = 4, B = 28, <<13:(A+(X=B))>>, X end, 162: "begin A = 4, B = 28, <<13:(A+(X=B))>>, X end.", 163: 28), 164: ok. 165: 166: match_bin(doc) -> 167: ["binary match problems"]; 168: match_bin(suite) -> 169: []; 170: match_bin(Config) when is_list(Config) -> 171: ?line check(fun() -> <<"abc">> = <<"abc">> end, 172: "<<\"abc\">> = <<\"abc\">>. ", 173: <<"abc">>), 174: ?line check(fun() -> 175: <<Size,B:Size/binary,Rest/binary>> = <<2,"AB","CD">>, 176: {Size,B,Rest} 177: end, 178: "begin <<Size,B:Size/binary,Rest/binary>> = <<2,\"AB\",\"CD\">>, " 179: "{Size,B,Rest} end. ", 180: {2,<<"AB">>,<<"CD">>}), 181: ok. 182: 183: pattern_expr(doc) -> 184: ["OTP-3144: compile-time expressions in pattern"]; 185: pattern_expr(suite) -> 186: []; 187: pattern_expr(Config) when is_list(Config) -> 188: ?line check(fun() -> case 4 of 2+2 -> ok end end, 189: "case 4 of 2+2 -> ok end. ", 190: ok), 191: ?line check(fun() -> case 2 of +2 -> ok end end, 192: "case 2 of +2 -> ok end. ", 193: ok), 194: ok. 195: 196: guard_3(doc) -> 197: ["OTP-4518."]; 198: guard_3(suite) -> 199: []; 200: guard_3(Config) when is_list(Config) -> 201: ?line check(fun() -> if false -> false; true -> true end end, 202: "if false -> false; true -> true end.", 203: true), 204: ?line check(fun() -> if <<"hej">> == <<"hopp">> -> true; 205: true -> false end end, 206: "begin if <<\"hej\">> == <<\"hopp\">> -> true; 207: true -> false end end.", 208: false), 209: ?line check(fun() -> if <<"hej">> == <<"hej">> -> true; 210: true -> false end end, 211: "begin if <<\"hej\">> == <<\"hej\">> -> true; 212: true -> false end end.", 213: true), 214: ok. 215: 216: guard_4(doc) -> 217: ["OTP-4885."]; 218: guard_4(suite) -> 219: []; 220: guard_4(Config) when is_list(Config) -> 221: check(fun() -> if erlang:'+'(3,a) -> true ; true -> false end end, 222: "if erlang:'+'(3,a) -> true ; true -> false end.", 223: false), 224: check(fun() -> if erlang:is_integer(3) -> true ; true -> false end 225: end, 226: "if erlang:is_integer(3) -> true ; true -> false end.", 227: true), 228: ?line check(fun() -> [X || X <- [1,2,3], erlang:is_integer(X)] end, 229: "[X || X <- [1,2,3], erlang:is_integer(X)].", 230: [1,2,3]), 231: ?line check(fun() -> if is_atom(is_integer(a)) -> true ; true -> false end 232: end, 233: "if is_atom(is_integer(a)) -> true ; true -> false end.", 234: true), 235: check(fun() -> if erlang:is_atom(erlang:is_integer(a)) -> true; 236: true -> false end end, 237: "if erlang:is_atom(erlang:is_integer(a)) -> true; " 238: "true -> false end.", 239: true), 240: ?line check(fun() -> if is_atom(3+a) -> true ; true -> false end end, 241: "if is_atom(3+a) -> true ; true -> false end.", 242: false), 243: ?line check(fun() -> if erlang:is_atom(3+a) -> true ; true -> false end 244: end, 245: "if erlang:is_atom(3+a) -> true ; true -> false end.", 246: false), 247: ok. 248: 249: 250: lc(doc) -> 251: ["OTP-4518."]; 252: lc(suite) -> 253: []; 254: lc(Config) when is_list(Config) -> 255: ?line check(fun() -> X = 32, [X || X <- [1,2,3]] end, 256: "begin X = 32, [X || X <- [1,2,3]] end.", 257: [1,2,3]), 258: ?line check(fun() -> X = 32, 259: [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end, 260: %% "binsize variable" ^ 261: "begin X = 32, 262: [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end.", 263: [1,2]), 264: ?line check(fun() -> Y = 13,[X || {X,Y} <- [{1,2}]] end, 265: "begin Y = 13,[X || {X,Y} <- [{1,2}]] end.", 266: [1]), 267: ?line error_check("begin [A || X <- [{1,2}], 1 == A] end.", 268: {unbound_var,'A'}), 269: ?line error_check("begin X = 32, 270: [{Y,W} || X <- [1,2,32,Y=4], Z <- [1,2,W=3]] end.", 271: {unbound_var,'Y'}), 272: ?line error_check("begin X = 32,<<A:B>> = <<100:X>> end.", 273: {unbound_var,'B'}), 274: ?line check(fun() -> [X || X <- [1,2,3,4], not (X < 2)] end, 275: "begin [X || X <- [1,2,3,4], not (X < 2)] end.", 276: [2,3,4]), 277: ?line check(fun() -> [X || X <- [true,false], X] end, 278: "[X || X <- [true,false], X].", [true]), 279: ok. 280: 281: simple_cases(doc) -> 282: ["Simple cases, just to cover some code."]; 283: simple_cases(suite) -> 284: []; 285: simple_cases(Config) when is_list(Config) -> 286: ?line check(fun() -> A = $C end, "A = $C.", $C), 287: %% ?line check(fun() -> A = 3.14 end, "A = 3.14.", 3.14), 288: ?line check(fun() -> self() ! a, A = receive a -> true end end, 289: "begin self() ! a, A = receive a -> true end end.", 290: true), 291: ?line check(fun() -> c:flush(), self() ! a, self() ! b, self() ! c, 292: receive b -> b end, 293: {messages, [a,c]} = 294: erlang:process_info(self(), messages), 295: c:flush() end, 296: "begin c:flush(), self() ! a, self() ! b, self() ! c," 297: "receive b -> b end," 298: "{messages, [a,c]} =" 299: " erlang:process_info(self(), messages), c:flush() end.", 300: ok), 301: ?line check(fun() -> self() ! a, A = receive a -> true 302: after 0 -> false end end, 303: "begin self() ! a, A = receive a -> true" 304: " after 0 -> false end end.", 305: true), 306: ?line check(fun() -> c:flush(), self() ! a, self() ! b, self() ! c, 307: receive b -> b after 0 -> true end, 308: {messages, [a,c]} = 309: erlang:process_info(self(), messages), 310: c:flush() end, 311: "begin c:flush(), self() ! a, self() ! b, self() ! c," 312: "receive b -> b after 0 -> true end," 313: "{messages, [a,c]} =" 314: " erlang:process_info(self(), messages), c:flush() end.", 315: ok), 316: ?line check(fun() -> receive _ -> true after 10 -> false end end, 317: "receive _ -> true after 10 -> false end.", 318: false), 319: ?line check(fun() -> F = fun(A) -> A end, true = 3 == F(3) end, 320: "begin F = fun(A) -> A end, true = 3 == F(3) end.", 321: true), 322: ?line check(fun() -> F = fun(A) -> A end, true = 3 == apply(F, [3]) end, 323: "begin F = fun(A) -> A end, true = 3 == apply(F,[3]) end.", 324: true), 325: ?line check(fun() -> catch throw(a) end, "catch throw(a).", a), 326: ?line check(fun() -> catch a end, "catch a.", a), 327: ?line check(fun() -> 4 == 3 end, "4 == 3.", false), 328: ?line check(fun() -> not true end, "not true.", false), 329: ?line check(fun() -> -3 end, "-3.", -3), 330: 331: ?line error_check("3.0 = 4.0.", {badmatch,4.0}), 332: ?line check(fun() -> <<(3.0+2.0):32/float>> = <<5.0:32/float>> end, 333: "<<(3.0+2.0):32/float>> = <<5.0:32/float>>.", 334: <<5.0:32/float>>), 335: 336: ?line check(fun() -> false andalso kludd end, "false andalso kludd.", 337: false), 338: ?line check(fun() -> true andalso true end, "true andalso true.", 339: true), 340: ?line check(fun() -> true andalso false end, "true andalso false.", 341: false), 342: ?line check(fun() -> true andalso kludd end, "true andalso kludd.", 343: kludd), 344: ?line error_check("kladd andalso kludd.", {badarg,kladd}), 345: 346: ?line check(fun() -> if false andalso kludd -> a; true -> b end end, 347: "if false andalso kludd -> a; true -> b end.", 348: b), 349: ?line check(fun() -> if true andalso true -> a; true -> b end end, 350: "if true andalso true -> a; true -> b end.", 351: a), 352: ?line check(fun() -> if true andalso false -> a; true -> b end end, 353: "if true andalso false -> a; true -> b end.", 354: b), 355: 356: ?line check(fun() -> true orelse kludd end, 357: "true orelse kludd.", true), 358: ?line check(fun() -> false orelse false end, 359: "false orelse false.", false), 360: ?line check(fun() -> false orelse true end, 361: "false orelse true.", true), 362: ?line check(fun() -> false orelse kludd end, 363: "false orelse kludd.", kludd), 364: ?line error_check("kladd orelse kludd.", {badarg,kladd}), 365: ?line error_check("[X || X <- [1,2,3], begin 1 end].",{bad_filter,1}), 366: ?line error_check("[X || X <- a].",{bad_generator,a}), 367: 368: ?line check(fun() -> if true orelse kludd -> a; true -> b end end, 369: "if true orelse kludd -> a; true -> b end.", a), 370: ?line check(fun() -> if false orelse false -> a; true -> b end end, 371: "if false orelse false -> a; true -> b end.", b), 372: ?line check(fun() -> if false orelse true -> a; true -> b end end, 373: "if false orelse true -> a; true -> b end.", a), 374: 375: ?line check(fun() -> [X || X <- [1,2,3], X+2] end, 376: "[X || X <- [1,2,3], X+2].", []), 377: 378: ?line check(fun() -> [X || X <- [1,2,3], [X] == [X || X <- [2]]] end, 379: "[X || X <- [1,2,3], [X] == [X || X <- [2]]].", 380: [2]), 381: ?line check(fun() -> F = fun(1) -> ett; (2) -> zwei end, 382: ett = F(1), zwei = F(2) end, 383: "begin F = fun(1) -> ett; (2) -> zwei end, 384: ett = F(1), zwei = F(2) end.", 385: zwei), 386: ?line check(fun() -> F = fun(X) when X == 1 -> ett; 387: (X) when X == 2 -> zwei end, 388: ett = F(1), zwei = F(2) end, 389: "begin F = fun(X) when X == 1 -> ett; 390: (X) when X == 2 -> zwei end, 391: ett = F(1), zwei = F(2) end.", 392: zwei), 393: ?line error_check("begin F = fun(1) -> ett end, zwei = F(2) end.", 394: function_clause), 395: ?line check(fun() -> if length([1]) == 1 -> yes; 396: true -> no end end, 397: "if length([1]) == 1 -> yes; 398: true -> no end.", 399: yes), 400: ?line check(fun() -> if is_integer(3) -> true; true -> false end end, 401: "if is_integer(3) -> true; true -> false end.", true), 402: ?line check(fun() -> if integer(3) -> true; true -> false end end, 403: "if integer(3) -> true; true -> false end.", true), 404: ?line check(fun() -> if is_float(3) -> true; true -> false end end, 405: "if is_float(3) -> true; true -> false end.", false), 406: ?line check(fun() -> if float(3) -> true; true -> false end end, 407: "if float(3) -> true; true -> false end.", false), 408: ?line check(fun() -> if is_number(3) -> true; true -> false end end, 409: "if is_number(3) -> true; true -> false end.", true), 410: ?line check(fun() -> if number(3) -> true; true -> false end end, 411: "if number(3) -> true; true -> false end.", true), 412: ?line check(fun() -> if is_atom(a) -> true; true -> false end end, 413: "if is_atom(a) -> true; true -> false end.", true), 414: ?line check(fun() -> if atom(a) -> true; true -> false end end, 415: "if atom(a) -> true; true -> false end.", true), 416: ?line check(fun() -> if is_list([]) -> true; true -> false end end, 417: "if is_list([]) -> true; true -> false end.", true), 418: ?line check(fun() -> if list([]) -> true; true -> false end end, 419: "if list([]) -> true; true -> false end.", true), 420: ?line check(fun() -> if is_tuple({}) -> true; true -> false end end, 421: "if is_tuple({}) -> true; true -> false end.", true), 422: ?line check(fun() -> if tuple({}) -> true; true -> false end end, 423: "if tuple({}) -> true; true -> false end.", true), 424: ?line check(fun() -> if is_pid(self()) -> true; true -> false end end, 425: "if is_pid(self()) -> true; true -> false end.", true), 426: ?line check(fun() -> if pid(self()) -> true; true -> false end end, 427: "if pid(self()) -> true; true -> false end.", true), 428: ?line check(fun() -> R = make_ref(), if is_reference(R) -> true; 429: true -> false end end, 430: "begin R = make_ref(), if is_reference(R) -> true;" 431: "true -> false end end.", true), 432: ?line check(fun() -> R = make_ref(), if reference(R) -> true; 433: true -> false end end, 434: "begin R = make_ref(), if reference(R) -> true;" 435: "true -> false end end.", true), 436: ?line check(fun() -> if is_port(a) -> true; true -> false end end, 437: "if is_port(a) -> true; true -> false end.", false), 438: ?line check(fun() -> if port(a) -> true; true -> false end end, 439: "if port(a) -> true; true -> false end.", false), 440: ?line check(fun() -> if is_function(a) -> true; true -> false end end, 441: "if is_function(a) -> true; true -> false end.", false), 442: ?line check(fun() -> if function(a) -> true; true -> false end end, 443: "if function(a) -> true; true -> false end.", false), 444: ?line check(fun() -> if is_binary(<<>>) -> true; true -> false end end, 445: "if is_binary(<<>>) -> true; true -> false end.", true), 446: ?line check(fun() -> if binary(<<>>) -> true; true -> false end end, 447: "if binary(<<>>) -> true; true -> false end.", true), 448: ?line check(fun() -> if is_integer(a) == true -> yes; 449: true -> no end end, 450: "if is_integer(a) == true -> yes; 451: true -> no end.", 452: no), 453: ?line check(fun() -> if [] -> true; true -> false end end, 454: "if [] -> true; true -> false end.", false), 455: ?line error_check("if lists:member(1,[1]) -> true; true -> false end.", 456: illegal_guard_expr), 457: ?line error_check("if false -> true end.", if_clause), 458: ?line check(fun() -> if a+b -> true; true -> false end end, 459: "if a + b -> true; true -> false end.", false), 460: ?line check(fun() -> if + b -> true; true -> false end end, 461: "if + b -> true; true -> false end.", false), 462: ?line error_check("case foo of bar -> true end.", {case_clause,foo}), 463: ?line error_check("case 4 of 2+a -> true; _ -> false end.", 464: illegal_pattern), 465: ?line error_check("case 4 of +a -> true; _ -> false end.", 466: illegal_pattern), 467: ?line check(fun() -> case a of 468: X when X == b -> one; 469: X when X == a -> two 470: end end, 471: "begin case a of 472: X when X == b -> one; 473: X when X == a -> two 474: end end.", two), 475: ?line error_check("3 = 4.", {badmatch,4}), 476: ?line error_check("a = 3.", {badmatch,3}), 477: %% ?line error_check("3.1 = 2.7.",{badmatch,2.7}), 478: ?line error_check("$c = 4.", {badmatch,4}), 479: ?line check(fun() -> $c = $c end, "$c = $c.", $c), 480: ?line check(fun() -> _ = bar end, "_ = bar.", bar), 481: ?line check(fun() -> A = 14, A = 14 end, 482: "begin A = 14, A = 14 end.", 14), 483: ?line error_check("begin A = 14, A = 16 end.", {badmatch,16}), 484: ?line error_check("\"hej\" = \"san\".", {badmatch,"san"}), 485: ?line check(fun() -> "hej" = "hej" end, 486: "\"hej\" = \"hej\".", "hej"), 487: ?line error_check("[] = [a].", {badmatch,[a]}), 488: ?line check(fun() -> [] = [] end, "[] = [].", []), 489: ?line error_check("[a] = [].", {badmatch,[]}), 490: ?line error_check("{a,b} = 34.", {badmatch,34}), 491: ?line check(fun() -> <<X:7>> = <<8:7>>, X end, 492: "begin <<X:7>> = <<8:7>>, X end.", 8), 493: ?line error_check("<<34:32>> = \"hej\".", {badmatch,"hej"}), 494: ?line check(fun() -> trunc((1 * 3 div 3 + 4 - 3) / 1) rem 2 end, 495: "begin trunc((1 * 3 div 3 + 4 - 3) / 1) rem 2 end.", 0), 496: ?line check(fun() -> (2#101 band 2#10101) bor (2#110 bxor 2#010) end, 497: "(2#101 band 2#10101) bor (2#110 bxor 2#010).", 5), 498: ?line check(fun() -> (2#1 bsl 4) + (2#10000 bsr 3) end, 499: "(2#1 bsl 4) + (2#10000 bsr 3).", 18), 500: ?line check(fun() -> ((1<3) and ((1 =:= 2) or (1 =/= 2))) xor (1=<2) end, 501: "((1<3) and ((1 =:= 2) or (1 =/= 2))) xor (1=<2).", false), 502: ?line check(fun() -> (a /= b) or (2 > 4) or (3 >= 3) end, 503: "(a /= b) or (2 > 4) or (3 >= 3).", true), 504: ?line check(fun() -> "hej" ++ "san" =/= "hejsan" -- "san" end, 505: "\"hej\" ++ \"san\" =/= \"hejsan\" -- \"san\".", true), 506: ?line check(fun() -> (bnot 1) < -0 end, "(bnot (+1)) < -0.", true), 507: ok. 508: 509: unary_plus(doc) -> 510: ["OTP-4929. Unary plus rejects non-numbers."]; 511: unary_plus(suite) -> 512: []; 513: unary_plus(Config) when is_list(Config) -> 514: ?line check(fun() -> F = fun(X) -> + X end, 515: true = -1 == F(-1) end, 516: "begin F = fun(X) -> + X end," 517: " true = -1 == F(-1) end.", true, ['F'], none, none), 518: ?line error_check("+a.", badarith), 519: ok. 520: 521: apply_atom(doc) -> 522: ["OTP-5064. Can no longer apply atoms."]; 523: apply_atom(suite) -> 524: []; 525: apply_atom(Config) when is_list(Config) -> 526: ?line error_check("[X || X <- [[1],[2]], 527: begin L = length, L(X) =:= 1 end].", 528: {badfun,length}), 529: ok. 530: 531: otp_5269(doc) -> 532: ["OTP-5269. Bugs in the bit syntax."]; 533: otp_5269(suite) -> 534: []; 535: otp_5269(Config) when is_list(Config) -> 536: ?line check(fun() -> L = 8, 537: F = fun(<<A:L,B:A>>) -> B end, 538: F(<<16:8, 7:16>>) 539: end, 540: "begin 541: L = 8, F = fun(<<A:L,B:A>>) -> B end, F(<<16:8, 7:16>>) 542: end.", 543: 7), 544: ?line check(fun() -> L = 8, 545: F = fun(<<L:L,B:L>>) -> B end, 546: F(<<16:8, 7:16>>) 547: end, 548: "begin 549: L = 8, F = fun(<<L:L,B:L>>) -> B end, F(<<16:8, 7:16>>) 550: end.", 551: 7), 552: ?line check(fun() -> L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end, 553: "begin L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end.", 554: 7), 555: ?line error_check("begin L = 8, <<L:L,B:L>> = <<16:8, 7:16>> end.", 556: {badmatch,<<16:8,7:16>>}), 557: 558: ?line error_check("begin <<L:16,L:L>> = <<16:16,8:16>>, L end.", 559: {badmatch, <<16:16,8:16>>}), 560: ?line check(fun() -> U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end, 561: "begin U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end.", 562: 32), 563: ?line check(fun() -> U = 8, [U || <<U:U>> <- [<<32:8>>]] end, 564: "begin U = 8, [U || <<U:U>> <- [<<32:8>>]] end.", 565: [32]), 566: ?line error_check("(fun({3,<<A:32,A:32>>}) -> a end) 567: ({3,<<17:32,19:32>>}).", 568: function_clause), 569: ?line check(fun() -> [X || <<A:8, 570: B:A>> <- [<<16:8,19:16>>], 571: <<X:8>> <- [<<B:8>>]] end, 572: "[X || <<A:8, 573: B:A>> <- [<<16:8,19:16>>], 574: <<X:8>> <- [<<B:8>>]].", 575: [19]), 576: ?line check(fun() -> 577: (fun (<<A:1/binary, B:8/integer, _C:B/binary>>) -> 578: case A of 579: B -> wrong; 580: _ -> ok 581: end 582: end)(<<1,2,3,4>>) end, 583: "(fun(<<A:1/binary, B:8/integer, _C:B/binary>>) ->" 584: " case A of B -> wrong; _ -> ok end" 585: " end)(<<1, 2, 3, 4>>).", 586: ok), 587: ok. 588: 589: otp_6539(doc) -> 590: ["OTP-6539. try/catch bugs."]; 591: otp_6539(suite) -> 592: []; 593: otp_6539(Config) when is_list(Config) -> 594: ?line check(fun() -> 595: F = fun(A,B) -> 596: try A+B 597: catch _:_ -> dontthinkso 598: end 599: end, 600: lists:zipwith(F, [1,2], [2,3]) 601: end, 602: "begin 603: F = fun(A,B) -> 604: try A+B 605: catch _:_ -> dontthinkso 606: end 607: end, 608: lists:zipwith(F, [1,2], [2,3]) 609: end.", 610: [3, 5]), 611: ok. 612: 613: otp_6543(doc) -> 614: ["OTP-6543. bitlevel binaries."]; 615: otp_6543(suite) -> 616: []; 617: otp_6543(Config) when is_list(Config) -> 618: ?line check(fun() -> 619: << <<X>> || <<X>> <- [1,2,3] >> 620: end, 621: "<< <<X>> || <<X>> <- [1,2,3] >>.", 622: <<>>), 623: ?line check(fun() -> 624: << <<X>> || X <- [1,2,3] >> 625: end, 626: "<< <<X>> || X <- [1,2,3] >>.", 627: <<1,2,3>>), 628: ?line check(fun() -> 629: << <<X:8>> || <<X:2>> <= <<"hej">> >> 630: end, 631: "<< <<X:8>> || <<X:2>> <= <<\"hej\">> >>.", 632: <<1,2,2,0,1,2,1,1,1,2,2,2>>), 633: ?line check(fun() -> 634: << <<X:8>> || 635: <<65,X:4>> <= <<65,7:4,65,3:4,66,8:4>> >> 636: end, 637: "<< <<X:8>> || 638: <<65,X:4>> <= <<65,7:4,65,3:4,66,8:4>> >>.", 639: <<7,3>>), 640: ?line check(fun() -> <<34:18/big>> end, 641: "<<34:18/big>>.", 642: <<0,8,2:2>>), 643: ?line check(fun() -> <<34:18/big-unit:2>> end, 644: "<<34:18/big-unit:2>>.", 645: <<0,0,0,2,2:4>>), 646: ?line check(fun() -> <<34:18/little>> end, 647: "<<34:18/little>>.", 648: <<34,0,0:2>>), 649: ?line case eval_string("<<34:18/native>>.") of 650: <<0,8,2:2>> -> ok; 651: <<34,0,0:2>> -> ok 652: end, 653: ?line check(fun() -> <<34:18/big-signed>> end, 654: "<<34:18/big-signed>>.", 655: <<0,8,2:2>>), 656: ?line check(fun() -> <<34:18/little-signed>> end, 657: "<<34:18/little-signed>>.", 658: <<34,0,0:2>>), 659: ?line case eval_string("<<34:18/native-signed>>.") of 660: <<0,8,2:2>> -> ok; 661: <<34,0,0:2>> -> ok 662: end, 663: ?line check(fun() -> <<34:18/big-unsigned>> end, 664: "<<34:18/big-unsigned>>.", 665: <<0,8,2:2>>), 666: ?line check(fun() -> <<34:18/little-unsigned>> end, 667: "<<34:18/little-unsigned>>.", 668: <<34,0,0:2>>), 669: ?line case eval_string("<<34:18/native-unsigned>>.") of 670: <<0,8,2:2>> -> ok; 671: <<34,0,0:2>> -> ok 672: end, 673: ?line check(fun() -> <<3.14:32/float-big>> end, 674: "<<3.14:32/float-big>>.", 675: <<64,72,245,195>>), 676: ?line check(fun() -> <<3.14:32/float-little>> end, 677: "<<3.14:32/float-little>>.", 678: <<195,245,72,64>>), 679: ?line case eval_string("<<3.14:32/float-native>>.") of 680: <<64,72,245,195>> -> ok; 681: <<195,245,72,64>> -> ok 682: end, 683: ?line error_check("<<(<<17,3:2>>)/binary>>.", badarg), 684: ?line check(fun() -> <<(<<17,3:2>>)/bitstring>> end, 685: "<<(<<17,3:2>>)/bitstring>>.", 686: <<17,3:2>>), 687: ?line check(fun() -> <<(<<17,3:2>>):10/bitstring>> end, 688: "<<(<<17,3:2>>):10/bitstring>>.", 689: <<17,3:2>>), 690: ?line check(fun() -> <<<<344:17>>/binary-unit:17>> end, 691: "<<<<344:17>>/binary-unit:17>>.", 692: <<344:17>>), 693: 694: ?line check(fun() -> <<X:18/big>> = <<34:18/big>>, X end, 695: "begin <<X:18/big>> = <<34:18/big>>, X end.", 696: 34), 697: ?line check(fun() -> <<X:18/big-unit:2>> = <<34:18/big-unit:2>>, X end, 698: "begin <<X:18/big-unit:2>> = <<34:18/big-unit:2>>, X end.", 699: 34), 700: ?line check(fun() -> <<X:18/little>> = <<34:18/little>>, X end, 701: "begin <<X:18/little>> = <<34:18/little>>, X end.", 702: 34), 703: ?line check(fun() -> <<X:18/native>> = <<34:18/native>>, X end, 704: "begin <<X:18/native>> = <<34:18/native>>, X end.", 705: 34), 706: ?line check(fun() -> <<X:18/big-signed>> = <<34:18/big-signed>>, X end, 707: "begin <<X:18/big-signed>> = <<34:18/big-signed>>, X end.", 708: 34), 709: ?line check(fun() -> <<X:18/little-signed>> = <<34:18/little-signed>>, 710: X end, 711: "begin <<X:18/little-signed>> = <<34:18/little-signed>>, 712: X end.", 713: 34), 714: ?line check(fun() -> <<X:18/native-signed>> = <<34:18/native-signed>>, 715: X end, 716: "begin <<X:18/native-signed>> = <<34:18/native-signed>>, 717: X end.", 718: 34), 719: ?line check(fun() -> <<X:18/big-unsigned>> = <<34:18/big-unsigned>>, 720: X end, 721: "begin <<X:18/big-unsigned>> = <<34:18/big-unsigned>>, 722: X end.", 723: 34), 724: ?line check(fun() -> 725: <<X:18/little-unsigned>> = <<34:18/little-unsigned>>, 726: X end, 727: "begin <<X:18/little-unsigned>> = <<34:18/little-unsigned>>, 728: X end.", 729: 34), 730: ?line check(fun() -> 731: <<X:18/native-unsigned>> = <<34:18/native-unsigned>>, 732: X end, 733: "begin <<X:18/native-unsigned>> = <<34:18/native-unsigned>>, 734: X end.", 735: 34), 736: ?line check(fun() -> <<X:32/float-big>> = <<2.0:32/float-big>>, X end, 737: "begin <<X:32/float-big>> = <<2.0:32/float-big>>, 738: X end.", 739: 2.0), 740: ?line check(fun() -> <<X:32/float-little>> = <<2.0:32/float-little>>, 741: X end, 742: "begin <<X:32/float-little>> = <<2.0:32/float-little>>, 743: X end.", 744: 2.0), 745: ?line check(fun() -> <<X:32/float-native>> = <<2.0:32/float-native>>, 746: X end, 747: "begin <<X:32/float-native>> = <<2.0:32/float-native>>, 748: X end.", 749: 2.0), 750: 751: ?line check( 752: fun() -> 753: [X || <<"hej",X:8>> <= <<"hej",8,"san",9,"hej",17,"hej">>] 754: end, 755: "[X || <<\"hej\",X:8>> <= 756: <<\"hej\",8,\"san\",9,\"hej\",17,\"hej\">>].", 757: [8,17]), 758: ?line check( 759: fun() -> 760: L = 8, << <<B:32>> || <<L:L,B:L>> <= <<16:8, 7:16>> >> 761: end, 762: "begin L = 8, << <<B:32>> || <<L:L,B:L>> <= <<16:8, 7:16>> >> 763: end.", 764: <<0,0,0,7>>), 765: %% Test the Value part of a binary segment. 766: %% "Old" bugs have been fixed (partial_eval is called on Value). 767: ?line check(fun() -> [ 3 || <<17/float>> <= <<17.0/float>>] end, 768: "[ 3 || <<17/float>> <= <<17.0/float>>].", 769: [3]), 770: ?line check(fun() -> [ 3 || <<17/float>> <- [<<17.0/float>>]] end, 771: "[ 3 || <<17/float>> <- [<<17.0/float>>]].", 772: [3]), 773: ?line check(fun() -> [ X || <<17/float,X:3>> <= <<17.0/float,2:3>>] end, 774: "[ X || <<17/float,X:3>> <= <<17.0/float,2:3>>].", 775: [2]), 776: ?line check(fun() -> 777: [ foo || <<(1 bsl 1023)/float>> <= <<(1 bsl 1023)/float>>] 778: end, 779: "[ foo || <<(1 bsl 1023)/float>> <= <<(1 bsl 1023)/float>>].", 780: [foo]), 781: ?line check(fun() -> 782: [ foo || <<(1 bsl 1023)/float>> <- [<<(1 bsl 1023)/float>>]] 783: end, 784: "[ foo || <<(1 bsl 1023)/float>> <- [<<(1 bsl 1023)/float>>]].", 785: [foo]), 786: ?line error_check("[ foo || <<(1 bsl 1024)/float>> <- 787: [<<(1 bsl 1024)/float>>]].", 788: badarg), 789: ?line check(fun() -> 790: [ foo || <<(1 bsl 1024)/float>> <- [<<(1 bsl 1023)/float>>]] 791: end, 792: "[ foo || <<(1 bsl 1024)/float>> <- 793: [<<(1 bsl 1023)/float>>]].", 794: []), 795: ?line check(fun() -> 796: [ foo || <<(1 bsl 1024)/float>> <= <<(1 bsl 1023)/float>>] 797: end, 798: "[ foo || <<(1 bsl 1024)/float>> <= 799: <<(1 bsl 1023)/float>>].", 800: []), 801: ?line check(fun() -> 802: L = 8, 803: [{L,B} || <<L:L,B:L/float>> <= <<32:8,7:32/float>>] 804: end, 805: "begin L = 8, 806: [{L,B} || <<L:L,B:L/float>> <= <<32:8,7:32/float>>] 807: end.", 808: [{32,7.0}]), 809: ?line check(fun() -> 810: L = 8, 811: [{L,B} || <<L:L,B:L/float>> <- [<<32:8,7:32/float>>]] 812: end, 813: "begin L = 8, 814: [{L,B} || <<L:L,B:L/float>> <- [<<32:8,7:32/float>>]] 815: end.", 816: [{32,7.0}]), 817: ?line check(fun() -> 818: [foo || <<"s">> <= <<"st">>] 819: end, 820: "[foo || <<\"s\">> <= <<\"st\">>].", 821: [foo]), 822: ?line check(fun() -> <<_:32>> = <<17:32>> end, 823: "<<_:32>> = <<17:32>>.", 824: <<17:32>>), 825: ?line check(fun() -> [foo || <<_:32>> <= <<17:32,20:32>>] end, 826: "[foo || <<_:32>> <= <<17:32,20:32>>].", 827: [foo,foo]), 828: 829: ?line check(fun() -> << <<X:32>> || X <- [1,2,3], X > 1 >> end, 830: "<< <<X:32>> || X <- [1,2,3], X > 1 >>.", 831: <<0,0,0,2,0,0,0,3>>), 832: ?line error_check("[X || <<X>> <= [a,b]].",{bad_generator,[a,b]}), 833: ok. 834: 835: otp_6787(doc) -> 836: ["OTP-6787. bitlevel binaries."]; 837: otp_6787(suite) -> 838: []; 839: otp_6787(Config) when is_list(Config) -> 840: ?line check( 841: fun() -> <<16:(1024*1024)>> = <<16:(1024*1024)>> end, 842: "<<16:(1024*1024)>> = <<16:(1024*1024)>>.", 843: <<16:1048576>>), 844: ok. 845: 846: otp_6977(doc) -> 847: ["OTP-6977. ++ bug."]; 848: otp_6977(suite) -> 849: []; 850: otp_6977(Config) when is_list(Config) -> 851: ?line check( 852: fun() -> (fun([$X] ++ _) -> ok end)("X") end, 853: "(fun([$X] ++ _) -> ok end)(\"X\").", 854: ok), 855: ok. 856: 857: otp_7550(doc) -> 858: ["OTP-7550. Support for UTF-8, UTF-16, UTF-32."]; 859: otp_7550(Config) when is_list(Config) -> 860: 861: %% UTF-8. 862: ?line check( 863: fun() -> <<65>> = <<65/utf8>> end, 864: "<<65>> = <<65/utf8>>.", 865: <<65>>), 866: ?line check( 867: fun() -> <<350/utf8>> = <<197,158>> end, 868: "<<350/utf8>> = <<197,158>>.", 869: <<197,158>>), 870: ?line check( 871: fun() -> <<$b,$j,$\303,$\266,$r,$n>> = <<"bj\366rn"/utf8>> end, 872: "<<$b,$j,$\303,$\266,$r,$n>> = <<\"bj\366rn\"/utf8>>.", 873: <<$b,$j,$\303,$\266,$r,$n>>), 874: 875: %% UTF-16. 876: ?line check( 877: fun() -> <<0,65>> = <<65/utf16>> end, 878: "<<0,65>> = <<65/utf16>>.", 879: <<0,65>>), 880: ?line check( 881: fun() -> <<16#D8,16#08,16#DF,16#45>> = <<16#12345/utf16>> end, 882: "<<16#D8,16#08,16#DF,16#45>> = <<16#12345/utf16>>.", 883: <<16#D8,16#08,16#DF,16#45>>), 884: ?line check( 885: fun() -> <<16#08,16#D8,16#45,16#DF>> = <<16#12345/little-utf16>> end, 886: "<<16#08,16#D8,16#45,16#DF>> = <<16#12345/little-utf16>>.", 887: <<16#08,16#D8,16#45,16#DF>>), 888: 889: ?line check( 890: fun() -> <<350/utf16>> = <<1,94>> end, 891: "<<350/utf16>> = <<1,94>>.", 892: <<1,94>>), 893: ?line check( 894: fun() -> <<350/little-utf16>> = <<94,1>> end, 895: "<<350/little-utf16>> = <<94,1>>.", 896: <<94,1>>), 897: ?line check( 898: fun() -> <<16#12345/utf16>> = <<16#D8,16#08,16#DF,16#45>> end, 899: "<<16#12345/utf16>> = <<16#D8,16#08,16#DF,16#45>>.", 900: <<16#D8,16#08,16#DF,16#45>>), 901: ?line check( 902: fun() -> <<16#12345/little-utf16>> = <<16#08,16#D8,16#45,16#DF>> end, 903: "<<16#12345/little-utf16>> = <<16#08,16#D8,16#45,16#DF>>.", 904: <<16#08,16#D8,16#45,16#DF>>), 905: 906: %% UTF-32. 907: ?line check( 908: fun() -> <<16#12345/utf32>> = <<16#0,16#01,16#23,16#45>> end, 909: "<<16#12345/utf32>> = <<16#0,16#01,16#23,16#45>>.", 910: <<16#0,16#01,16#23,16#45>>), 911: ?line check( 912: fun() -> <<16#0,16#01,16#23,16#45>> = <<16#12345/utf32>> end, 913: "<<16#0,16#01,16#23,16#45>> = <<16#12345/utf32>>.", 914: <<16#0,16#01,16#23,16#45>>), 915: ?line check( 916: fun() -> <<16#12345/little-utf32>> = <<16#45,16#23,16#01,16#00>> end, 917: "<<16#12345/little-utf32>> = <<16#45,16#23,16#01,16#00>>.", 918: <<16#45,16#23,16#01,16#00>>), 919: ?line check( 920: fun() -> <<16#12345/little-utf32>> end, 921: "<<16#12345/little-utf32>>.", 922: <<16#45,16#23,16#01,16#00>>), 923: 924: %% Mixed. 925: ?line check( 926: fun() -> <<16#41,16#12345/utf32,16#0391:16,16#2E:8>> end, 927: "<<16#41,16#12345/utf32,16#0391:16,16#2E:8>>.", 928: <<16#41,16#00,16#01,16#23,16#45,16#03,16#91,16#2E>>), 929: ok. 930: 931: 932: otp_8133(doc) -> 933: ["OTP-8133. Bit comprehension bug."]; 934: otp_8133(suite) -> 935: []; 936: otp_8133(Config) when is_list(Config) -> 937: ?line check( 938: fun() -> 939: E = fun(N) -> 940: if 941: is_integer(N) -> <<N/integer>>; 942: true -> throw(foo) 943: end 944: end, 945: try << << (E(V))/binary >> || V <- [1,2,3,a] >> 946: catch foo -> ok 947: end 948: end, 949: "begin 950: E = fun(N) -> 951: if is_integer(N) -> <<N/integer>>; 952: true -> throw(foo) 953: end 954: end, 955: try << << (E(V))/binary >> || V <- [1,2,3,a] >> 956: catch foo -> ok 957: end 958: end.", 959: ok), 960: ?line check( 961: fun() -> 962: E = fun(N) -> 963: if 964: is_integer(N) -> <<N/integer>>; 965: 966: true -> erlang:error(foo) 967: end 968: end, 969: try << << (E(V))/binary >> || V <- [1,2,3,a] >> 970: catch error:foo -> ok 971: end 972: end, 973: "begin 974: E = fun(N) -> 975: if is_integer(N) -> <<N/integer>>; 976: true -> erlang:error(foo) 977: end 978: end, 979: try << << (E(V))/binary >> || V <- [1,2,3,a] >> 980: catch error:foo -> ok 981: end 982: end.", 983: ok), 984: ok. 985: 986: otp_10622(doc) -> 987: ["OTP-10622. Bugs."]; 988: otp_10622(suite) -> 989: []; 990: otp_10622(Config) when is_list(Config) -> 991: check(fun() -> <<0>> = <<"\x{400}">> end, 992: "<<0>> = <<\"\\x{400}\">>. ", 993: <<0>>), 994: check(fun() -> <<"\x{aa}ff"/utf8>> = <<"\x{aa}ff"/utf8>> end, 995: "<<\"\\x{aa}ff\"/utf8>> = <<\"\\x{aa}ff\"/utf8>>. ", 996: <<"Â\xaaff">>), 997: %% The same bug as last example: 998: check(fun() -> case <<"foo"/utf8>> of 999: <<"foo"/utf8>> -> true 1000: end 1001: end, 1002: "case <<\"foo\"/utf8>> of <<\"foo\"/utf8>> -> true end.", 1003: true), 1004: check(fun() -> <<"\x{400}"/utf8>> = <<"\x{400}"/utf8>> end, 1005: "<<\"\\x{400}\"/utf8>> = <<\"\\x{400}\"/utf8>>. ", 1006: <<208,128>>), 1007: error_check("<<\"\\x{aaa}\">> = <<\"\\x{aaa}\">>.", 1008: {badmatch,<<"\xaa">>}), 1009: 1010: check(fun() -> [a || <<"\x{aaa}">> <= <<2703:16>>] end, 1011: "[a || <<\"\\x{aaa}\">> <= <<2703:16>>]. ", 1012: []), 1013: check(fun() -> [a || <<"\x{aa}"/utf8>> <= <<"\x{aa}"/utf8>>] end, 1014: "[a || <<\"\\x{aa}\"/utf8>> <= <<\"\\x{aa}\"/utf8>>]. ", 1015: [a]), 1016: check(fun() -> [a || <<"\x{aa}x"/utf8>> <= <<"\x{aa}y"/utf8>>] end, 1017: "[a || <<\"\\x{aa}x\"/utf8>> <= <<\"\\x{aa}y\"/utf8>>]. ", 1018: []), 1019: check(fun() -> [a || <<"\x{aaa}">> <= <<"\x{aaa}">>] end, 1020: "[a || <<\"\\x{aaa}\">> <= <<\"\\x{aaa}\">>]. ", 1021: []), 1022: check(fun() -> [a || <<"\x{aaa}"/utf8>> <= <<"\x{aaa}"/utf8>>] end, 1023: "[a || <<\"\\x{aaa}\"/utf8>> <= <<\"\\x{aaa}\"/utf8>>]. ", 1024: [a]), 1025: 1026: ok. 1027: 1028: funs(doc) -> 1029: ["Simple cases, just to cover some code."]; 1030: funs(suite) -> 1031: []; 1032: funs(Config) when is_list(Config) -> 1033: do_funs(none, none), 1034: do_funs(lfh(), none), 1035: do_funs(lfh(), efh()), 1036: 1037: ?line error_check("nix:foo().", {access_not_allowed,nix}, lfh(), efh()), 1038: ?line error_check("bar().", undef, none, none), 1039: 1040: ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end, 1041: F1(F1, 1000) end, 1042: "begin F1 = fun(F,N) -> count_down(F, N) end," 1043: "F1(F1,1000) end.", 1044: 0, ['F1'], lfh(), none), 1045: 1046: ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end, 1047: F1(F1, 1000) end, 1048: "begin F1 = fun(F,N) -> count_down(F, N) end," 1049: "F1(F1,1000) end.", 1050: 0, ['F1'], lfh_value(), none), 1051: 1052: ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end, 1053: F1(F1, 1000) end, 1054: "begin F1 = fun(F,N) -> count_down(F, N) end," 1055: "F1(F1,1000) end.", 1056: 0, ['F1'], lfh_value_extra(), none), 1057: 1058: ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end, 1059: F1(F1, 1000) end, 1060: "begin F1 = fun(F,N) -> count_down(F, N) end," 1061: "F1(F1,1000) end.", 1062: 0, ['F1'], {?MODULE,local_func_value}, none), 1063: %% This is not documented, and only for backward compatibility (good!). 1064: B0 = erl_eval:new_bindings(), 1065: ?line check(fun() -> is_function(?MODULE:count_down_fun()) end, 1066: "begin is_function(count_down_fun()) end.", 1067: true, [], {?MODULE,local_func,[B0]},none), 1068: 1069: EF = fun({timer,sleep}, As) when length(As) == 1 -> exit({got_it,sleep}); 1070: ({M,F}, As) -> apply(M, F, As) 1071: end, 1072: EFH = {value, EF}, 1073: ?line error_check("apply(timer, sleep, [1]).", got_it, none, EFH), 1074: ?line error_check("begin F = fun(T) -> timer:sleep(T) end,F(1) end.", 1075: got_it, none, EFH), 1076: ?line error_check("fun c/1.", undef), 1077: ?line error_check("fun a:b/0().", undef), 1078: 1079: MaxArgs = 20, 1080: ?line [true] = 1081: lists:usort([run_many_args(SAs) || SAs <- many_args(MaxArgs)]), 1082: ?line {'EXIT',{{argument_limit,_},_}} = 1083: (catch run_many_args(many_args1(MaxArgs+1))), 1084: 1085: ?line check(fun() -> M = lists, F = fun M:reverse/1, 1086: [1,2] = F([2,1]), ok end, 1087: "begin M = lists, F = fun M:reverse/1," 1088: " [1,2] = F([2,1]), ok end.", 1089: ok), 1090: 1091: %% Test that {M,F} is not accepted as a fun. 1092: error_check("{" ?MODULE_STRING ",module_info}().", 1093: {badfun,{?MODULE,module_info}}), 1094: ok. 1095: 1096: run_many_args({S, As}) -> 1097: apply(eval_string(S), As) =:= As. 1098: 1099: many_args(N) -> 1100: [many_args1(I) || I <- lists:seq(1, N)]. 1101: 1102: many_args1(N) -> 1103: F = fun(L, P) -> 1104: tl(lists:flatten([","++P++integer_to_list(E) || E <- L])) 1105: end, 1106: L = lists:seq(1, N), 1107: T = F(L, "V"), 1108: S = lists:flatten(io_lib:format("fun(~s) -> [~s] end.", [T, T])), 1109: {S, L}. 1110: 1111: do_funs(LFH, EFH) -> 1112: %% LFH is not really used by these examples... 1113: 1114: %% These tests do not prove that tail recursive functions really 1115: %% work (that the process does not grow); one should also run them 1116: %% manually with 1000 replaced by 1000000. 1117: 1118: M = atom_to_list(?MODULE), 1119: ?line check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end, 1120: F1(F1, 1000) end, 1121: concat(["begin F1 = fun(F,N) -> ", M, 1122: ":count_down(F, N) end, F1(F1,1000) end."]), 1123: 0, ['F1'], LFH, EFH), 1124: ?line check(fun() -> F1 = fun(F,N) -> apply(?MODULE,count_down,[F,N]) 1125: end, F1(F1, 1000) end, 1126: concat(["begin F1 = fun(F,N) -> apply(", M, 1127: ",count_down,[F, N]) end, F1(F1,1000) end."]), 1128: 0, ['F1'], LFH, EFH), 1129: ?line check(fun() -> F = fun(F,N) when N > 0 -> apply(F,[F,N-1]); 1130: (_F,0) -> ok end, 1131: F(F, 1000) 1132: end, 1133: "begin F = fun(F,N) when N > 0 -> apply(F,[F,N-1]);" 1134: "(_F,0) -> ok end," 1135: "F(F, 1000) end.", 1136: ok, ['F'], LFH, EFH), 1137: ?line check(fun() -> F = fun(F,N) when N > 0 -> 1138: apply(erlang,apply,[F,[F,N-1]]); 1139: (_F,0) -> ok end, 1140: F(F, 1000) 1141: end, 1142: "begin F = fun(F,N) when N > 0 ->" 1143: "apply(erlang,apply,[F,[F,N-1]]);" 1144: "(_F,0) -> ok end," 1145: "F(F, 1000) end.", 1146: ok, ['F'], LFH, EFH), 1147: ?line check(fun() -> F = count_down_fun(), 1148: SF = fun(SF, F1, N) -> F(SF, F1, N) end, 1149: SF(SF, F, 1000) end, 1150: concat(["begin F = ", M, ":count_down_fun()," 1151: "SF = fun(SF, F1, N) -> F(SF, F1, N) end," 1152: "SF(SF, F, 1000) end."]), 1153: ok, ['F','SF'], LFH, EFH), 1154: 1155: 1156: ?line check(fun() -> F = fun(X) -> A = 1+X, {X,A} end, 1157: true = {2,3} == F(2) end, 1158: "begin F = fun(X) -> A = 1+X, {X,A} end, 1159: true = {2,3} == F(2) end.", true, ['F'], LFH, EFH), 1160: check(fun() -> F = fun(X) -> erlang:'+'(X,2) end, 1161: true = 3 == F(1) end, 1162: "begin F = fun(X) -> erlang:'+'(X,2) end," 1163: " true = 3 == F(1) end.", true, ['F'], 1164: LFH, EFH), 1165: ?line check(fun() -> F = fun(X) -> byte_size(X) end, 1166: ?MODULE:do_apply(F,<<"hej">>) end, 1167: concat(["begin F = fun(X) -> size(X) end,", 1168: M,":do_apply(F,<<\"hej\">>) end."]), 1169: 3, ['F'], LFH, EFH), 1170: 1171: ?line check(fun() -> F1 = fun(X, Z) -> {X,Z} end, 1172: Z = 5, 1173: F2 = fun(X, Y) -> F1(Z,{X,Y}) end, 1174: F3 = fun(X, Y) -> {a,F1(Z,{X,Y})} end, 1175: {5,{x,y}} = F2(x,y), 1176: {a,{5,{y,x}}} = F3(y,x), 1177: {5,{5,y}} = F2(Z,y), 1178: true = {5,{x,5}} == F2(x,Z) end, 1179: "begin F1 = fun(X, Z) -> {X,Z} end, 1180: Z = 5, 1181: F2 = fun(X, Y) -> F1(Z,{X,Y}) end, 1182: F3 = fun(X, Y) -> {a,F1(Z,{X,Y})} end, 1183: {5,{x,y}} = F2(x,y), 1184: {a,{5,{y,x}}} = F3(y,x), 1185: {5,{5,y}} = F2(Z,y), 1186: true = {5,{x,5}} == F2(x,Z) end.", 1187: true, ['F1','Z','F2','F3'], LFH, EFH), 1188: ?line check(fun() -> F = fun(X) -> byte_size(X) end, 1189: F2 = fun(Y) -> F(Y) end, 1190: ?MODULE:do_apply(F2,<<"hej">>) end, 1191: concat(["begin F = fun(X) -> size(X) end,", 1192: "F2 = fun(Y) -> F(Y) end,", 1193: M,":do_apply(F2,<<\"hej\">>) end."]), 1194: 3, ['F','F2'], LFH, EFH), 1195: ?line check(fun() -> Z = 5, F = fun(X) -> {Z,X} end, 1196: F2 = fun(Z) -> F(Z) end, F2(3) end, 1197: "begin Z = 5, F = fun(X) -> {Z,X} end, 1198: F2 = fun(Z) -> F(Z) end, F2(3) end.", 1199: {5,3},['F','F2','Z'], LFH, EFH), 1200: ?line check(fun() -> F = fun(Z) -> Z end, 1201: F2 = fun(X) -> F(X), Z = {X,X}, Z end, 1202: {1,1} = F2(1), Z = 7, Z end, 1203: "begin F = fun(Z) -> Z end, 1204: F2 = fun(X) -> F(X), Z = {X,X}, Z end, 1205: {1,1} = F2(1), Z = 7, Z end.", 7, ['F','F2','Z'], 1206: LFH, EFH), 1207: ?line check(fun() -> F = fun(F, N) -> [?MODULE:count_down(F,N) || X <-[1]] 1208: end, F(F,2) end, 1209: concat(["begin F = fun(F, N) -> [", M, 1210: ":count_down(F,N) || X <-[1]] end, F(F,2) end."]), 1211: [[[0]]], ['F'], LFH, EFH), 1212: ok. 1213: 1214: count_down(F, N) when N > 0 -> 1215: F(F, N-1); 1216: count_down(_F, N) -> 1217: N. 1218: 1219: count_down_fun() -> 1220: fun(SF,F,N) when N > 0 -> SF(SF,F,N-1); 1221: (_SF,_F,_N) -> ok 1222: end. 1223: 1224: do_apply(F, V) -> 1225: F(V). 1226: 1227: lfh() -> 1228: {eval, fun(F, As, Bs) -> local_func(F, As, Bs) end}. 1229: 1230: local_func(F, As0, Bs0) when is_atom(F) -> 1231: {As,Bs} = erl_eval:expr_list(As0, Bs0, lfh()), 1232: case erlang:function_exported(?MODULE, F, length(As)) of 1233: true -> 1234: {value,apply(?MODULE, F, As),Bs}; 1235: false -> 1236: {value,apply(shell_default, F, As),Bs} 1237: end. 1238: 1239: lfh_value_extra() -> 1240: %% Not documented. 1241: {value, fun(F, As, a1, a2) -> local_func_value(F, As) end, [a1, a2]}. 1242: 1243: lfh_value() -> 1244: {value, fun(F, As) -> local_func_value(F, As) end}. 1245: 1246: local_func_value(F, As) when is_atom(F) -> 1247: case erlang:function_exported(?MODULE, F, length(As)) of 1248: true -> 1249: apply(?MODULE, F, As); 1250: false -> 1251: apply(shell_default, F, As) 1252: end. 1253: 1254: efh() -> 1255: {value, fun(F, As) -> external_func(F, As) end}. 1256: 1257: external_func({M,_}, _As) when M == nix -> 1258: exit({{access_not_allowed,M},[mfa]}); 1259: external_func(F, As) when is_function(F) -> 1260: apply(F, As); 1261: external_func({M,F}, As) -> 1262: apply(M, F, As). 1263: 1264: 1265: 1266: try_catch(doc) -> 1267: ["Test try-of-catch-after-end statement"]; 1268: try_catch(suite) -> 1269: []; 1270: try_catch(Config) when is_list(Config) -> 1271: %% Match in of with catch 1272: ?line check(fun() -> try 1 of 1 -> 2 catch _:_ -> 3 end end, 1273: "try 1 of 1 -> 2 catch _:_ -> 3 end.", 2), 1274: ?line check(fun() -> try 1 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end end, 1275: "try 1 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end.", 2), 1276: ?line check(fun() -> try 3 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end end, 1277: "try 3 of 1 -> 2; 3 -> 4 catch _:_ -> 5 end.", 4), 1278: %% Just after 1279: ?line check(fun () -> X = try 1 after put(try_catch, 2) end, 1280: {X,get(try_catch)} end, 1281: "begin X = try 1 after put(try_catch, 2) end, " 1282: "{X,get(try_catch)} end.", {1,2}), 1283: %% Match in of with after 1284: ?line check(fun() -> X = try 1 of 1 -> 2 after put(try_catch, 3) end, 1285: {X,get(try_catch)} end, 1286: "begin X = try 1 of 1 -> 2 after put(try_catch, 3) end, " 1287: "{X,get(try_catch)} end.", {2,3}), 1288: ?line check(fun() -> X = try 1 of 1 -> 2; 3 -> 4 1289: after put(try_catch, 5) end, 1290: {X,get(try_catch)} end, 1291: "begin X = try 1 of 1 -> 2; 3 -> 4 " 1292: " after put(try_catch, 5) end, " 1293: " {X,get(try_catch)} end.", {2,5}), 1294: ?line check(fun() -> X = try 3 of 1 -> 2; 3 -> 4 1295: after put(try_catch, 5) end, 1296: {X,get(try_catch)} end, 1297: "begin X = try 3 of 1 -> 2; 3 -> 4 " 1298: " after put(try_catch, 5) end, " 1299: " {X,get(try_catch)} end.", {4,5}), 1300: %% Nomatch in of 1301: ?line error_check("try 1 of 2 -> 3 catch _:_ -> 4 end.", 1302: {try_clause,1}), 1303: %% Nomatch in of with after 1304: ?line check(fun () -> {'EXIT',{{try_clause,1},_}} = 1305: begin catch try 1 of 2 -> 3 1306: after put(try_catch, 4) end end, 1307: get(try_catch) end, 1308: "begin {'EXIT',{{try_clause,1},_}} = " 1309: " begin catch try 1 of 2 -> 3 " 1310: " after put(try_catch, 4) end end, " 1311: " get(try_catch) end. ", 4), 1312: %% Exception in try 1313: ?line check(fun () -> try 1=2 catch error:{badmatch,2} -> 3 end end, 1314: "try 1=2 catch error:{badmatch,2} -> 3 end.", 3), 1315: ?line check(fun () -> try 1=2 of 3 -> 4 1316: catch error:{badmatch,2} -> 5 end end, 1317: "try 1=2 of 3 -> 4 " 1318: "catch error:{badmatch,2} -> 5 end.", 5), 1319: %% Exception in try with after 1320: ?line check(fun () -> X = try 1=2 1321: catch error:{badmatch,2} -> 3 1322: after put(try_catch, 4) end, 1323: {X,get(try_catch)} end, 1324: "begin X = try 1=2 " 1325: " catch error:{badmatch,2} -> 3 " 1326: " after put(try_catch, 4) end, " 1327: " {X,get(try_catch)} end. ", {3,4}), 1328: ?line check(fun () -> X = try 1=2 of 3 -> 4 1329: catch error:{badmatch,2} -> 5 1330: after put(try_catch, 6) end, 1331: {X,get(try_catch)} end, 1332: "begin X = try 1=2 of 3 -> 4" 1333: " catch error:{badmatch,2} -> 5 " 1334: " after put(try_catch, 6) end, " 1335: " {X,get(try_catch)} end. ", {5,6}), 1336: %% Uncaught exception 1337: ?line error_check("try 1=2 catch error:undefined -> 3 end. ", 1338: {badmatch,2}), 1339: ?line error_check("try 1=2 of 3 -> 4 catch error:undefined -> 5 end. ", 1340: {badmatch,2}), 1341: %% Uncaught exception with after 1342: ?line check(fun () -> {'EXIT',{{badmatch,2},_}} = 1343: begin catch try 1=2 1344: after put(try_catch, 3) end end, 1345: get(try_catch) end, 1346: "begin {'EXIT',{{badmatch,2},_}} = " 1347: " begin catch try 1=2 " 1348: " after put(try_catch, 3) end end, " 1349: " get(try_catch) end. ", 3), 1350: ?line check(fun () -> {'EXIT',{{badmatch,2},_}} = 1351: begin catch try 1=2 of 3 -> 4 1352: after put(try_catch, 5) end end, 1353: get(try_catch) end, 1354: "begin {'EXIT',{{badmatch,2},_}} = " 1355: " begin catch try 1=2 of 3 -> 4" 1356: " after put(try_catch, 5) end end, " 1357: " get(try_catch) end. ", 5), 1358: ?line check(fun () -> {'EXIT',{{badmatch,2},_}} = 1359: begin catch try 1=2 catch error:undefined -> 3 1360: after put(try_catch, 4) end end, 1361: get(try_catch) end, 1362: "begin {'EXIT',{{badmatch,2},_}} = " 1363: " begin catch try 1=2 catch error:undefined -> 3 " 1364: " after put(try_catch, 4) end end, " 1365: " get(try_catch) end. ", 4), 1366: ?line check(fun () -> {'EXIT',{{badmatch,2},_}} = 1367: begin catch try 1=2 of 3 -> 4 1368: catch error:undefined -> 5 1369: after put(try_catch, 6) end end, 1370: get(try_catch) end, 1371: "begin {'EXIT',{{badmatch,2},_}} = " 1372: " begin catch try 1=2 of 3 -> 4 " 1373: " catch error:undefined -> 5 " 1374: " after put(try_catch, 6) end end, " 1375: " get(try_catch) end. ", 6), 1376: ok. 1377: 1378: 1379: eval_expr_5(doc) -> 1380: ["(OTP-7933)"]; 1381: eval_expr_5(suite) -> 1382: []; 1383: eval_expr_5(Config) when is_list(Config) -> 1384: ?line {ok,Tokens ,_} = 1385: erl_scan:string("if a+4 == 4 -> yes; true -> no end. "), 1386: ?line {ok, [Expr]} = erl_parse:parse_exprs(Tokens), 1387: ?line {value, no, []} = erl_eval:expr(Expr, [], none, none, none), 1388: ?line no = erl_eval:expr(Expr, [], none, none, value), 1389: try 1390: erl_eval:expr(Expr, [], none, none, 4711), 1391: ?line function_clause = should_never_reach_here 1392: catch 1393: error:function_clause -> 1394: ok 1395: end. 1396: 1397: zero_width(Config) when is_list(Config) -> 1398: ?line check(fun() -> 1399: {'EXIT',{badarg,_}} = (catch <<not_a_number:0>>), 1400: ok 1401: end, "begin {'EXIT',{badarg,_}} = (catch <<not_a_number:0>>), " 1402: "ok end.", ok), 1403: ok. 1404: 1405: %% Check the string in different contexts: as is; in fun; from compiled code. 1406: check(F, String, Result) -> 1407: check1(F, String, Result), 1408: FunString = concat(["fun() -> ", no_final_dot(String), " end(). "]), 1409: check1(F, FunString, Result), 1410: CompileString = concat(["hd(lists:map(fun(_) -> ", no_final_dot(String), 1411: " end, [foo])). "]), 1412: check1(F, CompileString, Result). 1413: 1414: check1(F, String, Result) -> 1415: Result = F(), 1416: case catch parse_and_run(String) of 1417: {value, Result, _} -> 1418: ok; 1419: Other -> 1420: test_server:fail({eval, Other, Result}) 1421: end. 1422: 1423: check(F, String, Result, BoundVars, LFH, EFH) -> 1424: Result = F(), 1425: case catch parse_and_run(String, LFH, EFH) of 1426: {value, Result, Bs} -> 1427: %% We just assume that Bs is an orddict... 1428: Keys = orddict:fetch_keys(Bs), 1429: case sort(BoundVars) == Keys of 1430: true -> 1431: ok; 1432: false -> 1433: test_server:fail({check, BoundVars, Keys}) 1434: end, 1435: ok; 1436: Other -> 1437: test_server:fail({check, Other, Result}) 1438: end. 1439: 1440: error_check(String, Result) -> 1441: case catch parse_and_run(String) of 1442: {'EXIT', {Result,_}} -> 1443: ok; 1444: Other -> 1445: test_server:fail({eval, Other, Result}) 1446: end. 1447: 1448: error_check(String, Result, LFH, EFH) -> 1449: case catch parse_and_run(String, LFH, EFH) of 1450: {'EXIT', {Result,_}} -> 1451: ok; 1452: Other -> 1453: test_server:fail({eval, Other, Result}) 1454: end. 1455: 1456: eval_string(String) -> 1457: {value, Result, _} = parse_and_run(String), 1458: Result. 1459: 1460: parse_and_run(String) -> 1461: {ok,Tokens,_} = erl_scan:string(String), 1462: {ok, [Expr]} = erl_parse:parse_exprs(Tokens), 1463: erl_eval:expr(Expr, []). 1464: 1465: parse_and_run(String, LFH, EFH) -> 1466: {ok,Tokens,_} = erl_scan:string(String), 1467: {ok, [Expr]} = erl_parse:parse_exprs(Tokens), 1468: erl_eval:expr(Expr, [], LFH, EFH). 1469: 1470: no_final_dot(S) -> 1471: case lists:reverse(S) of 1472: " ." ++ R -> lists:reverse(R); 1473: "." ++ R -> lists:reverse(R); 1474: _ -> S 1475: end.